update external headers
This commit is contained in:
57
ios/include/CMakeLists.txt
Normal file
57
ios/include/CMakeLists.txt
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.19)
|
||||||
|
project(camutils)
|
||||||
|
|
||||||
|
set(TARGET camutils)
|
||||||
|
set(PUBLIC_HDR_DIR include)
|
||||||
|
|
||||||
|
# ==================================================================================================
|
||||||
|
# Sources and headers
|
||||||
|
# ==================================================================================================
|
||||||
|
set(PUBLIC_HDRS
|
||||||
|
include/camutils/Bookmark.h
|
||||||
|
include/camutils/compiler.h
|
||||||
|
include/camutils/Manipulator.h
|
||||||
|
)
|
||||||
|
|
||||||
|
set(SRCS
|
||||||
|
src/Bookmark.cpp
|
||||||
|
src/FreeFlightManipulator.h
|
||||||
|
src/Manipulator.cpp
|
||||||
|
src/MapManipulator.h
|
||||||
|
src/OrbitManipulator.h
|
||||||
|
)
|
||||||
|
|
||||||
|
# ==================================================================================================
|
||||||
|
# Include and target definitions
|
||||||
|
# ==================================================================================================
|
||||||
|
include_directories(${PUBLIC_HDR_DIR})
|
||||||
|
|
||||||
|
add_library(${TARGET} STATIC ${PUBLIC_HDRS} ${SRCS})
|
||||||
|
|
||||||
|
target_link_libraries(${TARGET} PUBLIC math)
|
||||||
|
|
||||||
|
target_include_directories(${TARGET} PUBLIC ${PUBLIC_HDR_DIR})
|
||||||
|
|
||||||
|
# ==================================================================================================
|
||||||
|
# Compiler flags
|
||||||
|
# ==================================================================================================
|
||||||
|
if (MSVC)
|
||||||
|
target_compile_options(${TARGET} PRIVATE $<$<CONFIG:Release>:/fp:fast>)
|
||||||
|
else()
|
||||||
|
target_compile_options(${TARGET} PRIVATE $<$<CONFIG:Release>:-ffast-math>)
|
||||||
|
target_compile_options(${TARGET} PRIVATE -Wno-deprecated-register)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# ==================================================================================================
|
||||||
|
# Installation
|
||||||
|
# ==================================================================================================
|
||||||
|
install(TARGETS ${TARGET} ARCHIVE DESTINATION lib/${DIST_DIR})
|
||||||
|
install(DIRECTORY ${PUBLIC_HDR_DIR}/camutils DESTINATION include)
|
||||||
|
|
||||||
|
# ==================================================================================================
|
||||||
|
# Tests
|
||||||
|
# ==================================================================================================
|
||||||
|
if (NOT ANDROID AND NOT WEBGL AND NOT IOS)
|
||||||
|
add_executable(test_${TARGET} tests/test_camutils.cpp)
|
||||||
|
target_link_libraries(test_${TARGET} PRIVATE camutils gtest)
|
||||||
|
endif()
|
||||||
@@ -27,6 +27,8 @@
|
|||||||
|
|
||||||
namespace filament::backend {
|
namespace filament::backend {
|
||||||
|
|
||||||
|
class CallbackHandler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A CPU memory-buffer descriptor, typically used to transfer data from the CPU to the GPU.
|
* A CPU memory-buffer descriptor, typically used to transfer data from the CPU to the GPU.
|
||||||
*
|
*
|
||||||
@@ -53,8 +55,8 @@ public:
|
|||||||
|
|
||||||
//! calls the callback to advertise BufferDescriptor no-longer owns the buffer
|
//! calls the callback to advertise BufferDescriptor no-longer owns the buffer
|
||||||
~BufferDescriptor() noexcept {
|
~BufferDescriptor() noexcept {
|
||||||
if (callback) {
|
if (mCallback) {
|
||||||
callback(buffer, size, user);
|
mCallback(buffer, size, mUser);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,19 +64,21 @@ public:
|
|||||||
BufferDescriptor& operator=(const BufferDescriptor& rhs) = delete;
|
BufferDescriptor& operator=(const BufferDescriptor& rhs) = delete;
|
||||||
|
|
||||||
BufferDescriptor(BufferDescriptor&& rhs) noexcept
|
BufferDescriptor(BufferDescriptor&& rhs) noexcept
|
||||||
: buffer(rhs.buffer), size(rhs.size), callback(rhs.callback), user(rhs.user) {
|
: buffer(rhs.buffer), size(rhs.size),
|
||||||
|
mCallback(rhs.mCallback), mUser(rhs.mUser), mHandler(rhs.mHandler) {
|
||||||
rhs.buffer = nullptr;
|
rhs.buffer = nullptr;
|
||||||
rhs.callback = nullptr;
|
rhs.mCallback = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferDescriptor& operator=(BufferDescriptor&& rhs) noexcept {
|
BufferDescriptor& operator=(BufferDescriptor&& rhs) noexcept {
|
||||||
if (this != &rhs) {
|
if (this != &rhs) {
|
||||||
buffer = rhs.buffer;
|
buffer = rhs.buffer;
|
||||||
size = rhs.size;
|
size = rhs.size;
|
||||||
callback = rhs.callback;
|
mCallback = rhs.mCallback;
|
||||||
user = rhs.user;
|
mUser = rhs.mUser;
|
||||||
|
mHandler = rhs.mHandler;
|
||||||
rhs.buffer = nullptr;
|
rhs.buffer = nullptr;
|
||||||
rhs.callback = nullptr;
|
rhs.mCallback = nullptr;
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -88,7 +92,20 @@ public:
|
|||||||
*/
|
*/
|
||||||
BufferDescriptor(void const* buffer, size_t size,
|
BufferDescriptor(void const* buffer, size_t size,
|
||||||
Callback callback = nullptr, void* user = nullptr) noexcept
|
Callback callback = nullptr, void* user = nullptr) noexcept
|
||||||
: buffer(const_cast<void*>(buffer)), size(size), callback(callback), user(user) {
|
: buffer(const_cast<void*>(buffer)), size(size), mCallback(callback), mUser(user) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a BufferDescriptor that references a CPU memory-buffer
|
||||||
|
* @param buffer Memory address of the CPU buffer to reference
|
||||||
|
* @param size Size of the CPU buffer in bytes
|
||||||
|
* @param callback A callback used to release the CPU buffer from this BufferDescriptor
|
||||||
|
* @param user An opaque user pointer passed to the callback function when it's called
|
||||||
|
*/
|
||||||
|
BufferDescriptor(void const* buffer, size_t size,
|
||||||
|
CallbackHandler* handler, Callback callback, void* user = nullptr) noexcept
|
||||||
|
: buffer(const_cast<void*>(buffer)), size(size),
|
||||||
|
mCallback(callback), mUser(user), mHandler(handler) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------------
|
||||||
@@ -100,14 +117,15 @@ public:
|
|||||||
*
|
*
|
||||||
* @param buffer Memory address of the CPU buffer to reference
|
* @param buffer Memory address of the CPU buffer to reference
|
||||||
* @param size Size of the CPU buffer in bytes
|
* @param size Size of the CPU buffer in bytes
|
||||||
|
* @param handler Handler to use to dispatch the callback, or nullptr for the default handler
|
||||||
* @return a new BufferDescriptor
|
* @return a new BufferDescriptor
|
||||||
*/
|
*/
|
||||||
template<typename T, void(T::*method)(void const* buffer, size_t size)>
|
template<typename T, void(T::*method)(void const*, size_t)>
|
||||||
static BufferDescriptor make(
|
static BufferDescriptor make(
|
||||||
void const* buffer, size_t size, T* data) noexcept {
|
void const* buffer, size_t size, T* data, CallbackHandler* handler = nullptr) noexcept {
|
||||||
return {
|
return {
|
||||||
buffer, size,
|
buffer, size,
|
||||||
[](void* b, size_t s, void* u) {
|
handler, [](void* b, size_t s, void* u) {
|
||||||
(*static_cast<T**>(u)->*method)(b, s);
|
(*static_cast<T**>(u)->*method)(b, s);
|
||||||
}, data
|
}, data
|
||||||
};
|
};
|
||||||
@@ -123,14 +141,15 @@ public:
|
|||||||
* @param buffer Memory address of the CPU buffer to reference
|
* @param buffer Memory address of the CPU buffer to reference
|
||||||
* @param size Size of the CPU buffer in bytes
|
* @param size Size of the CPU buffer in bytes
|
||||||
* @param functor functor of type f(void const* buffer, size_t size)
|
* @param functor functor of type f(void const* buffer, size_t size)
|
||||||
|
* @param handler Handler to use to dispatch the callback, or nullptr for the default handler
|
||||||
* @return a new BufferDescriptor
|
* @return a new BufferDescriptor
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static BufferDescriptor make(
|
static BufferDescriptor make(
|
||||||
void const* buffer, size_t size, T&& functor) noexcept {
|
void const* buffer, size_t size, T&& functor, CallbackHandler* handler = nullptr) noexcept {
|
||||||
return {
|
return {
|
||||||
buffer, size,
|
buffer, size,
|
||||||
[](void* b, size_t s, void* u) {
|
handler, [](void* b, size_t s, void* u) {
|
||||||
T& that = *static_cast<T*>(u);
|
T& that = *static_cast<T*>(u);
|
||||||
that(b, s);
|
that(b, s);
|
||||||
delete &that;
|
delete &that;
|
||||||
@@ -147,21 +166,39 @@ public:
|
|||||||
* @param user An opaque user pointer passed to the callbeck function when it's called
|
* @param user An opaque user pointer passed to the callbeck function when it's called
|
||||||
*/
|
*/
|
||||||
void setCallback(Callback callback, void* user = nullptr) noexcept {
|
void setCallback(Callback callback, void* user = nullptr) noexcept {
|
||||||
this->callback = callback;
|
this->mCallback = callback;
|
||||||
this->user = user;
|
this->mUser = user;
|
||||||
|
this->mHandler = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set or replace the release callback function
|
||||||
|
* @param handler The Handler to use to dispatch the callback
|
||||||
|
* @param callback The new callback function
|
||||||
|
* @param user An opaque user pointer passed to the callbeck function when it's called
|
||||||
|
*/
|
||||||
|
void setCallback(CallbackHandler* handler, Callback callback, void* user = nullptr) noexcept {
|
||||||
|
mCallback = callback;
|
||||||
|
mUser = user;
|
||||||
|
mHandler = handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Returns whether a release callback is set
|
//! Returns whether a release callback is set
|
||||||
bool hasCallback() const noexcept { return callback != nullptr; }
|
bool hasCallback() const noexcept { return mCallback != nullptr; }
|
||||||
|
|
||||||
//! Returns the currently set release callback function
|
//! Returns the currently set release callback function
|
||||||
Callback getCallback() const noexcept {
|
Callback getCallback() const noexcept {
|
||||||
return callback;
|
return mCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Returns the handler for this callback or nullptr if the default handler is to be used.
|
||||||
|
CallbackHandler* getHandler() const noexcept {
|
||||||
|
return mHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Returns the user opaque pointer associated to this BufferDescriptor
|
//! Returns the user opaque pointer associated to this BufferDescriptor
|
||||||
void* getUser() const noexcept {
|
void* getUser() const noexcept {
|
||||||
return user;
|
return mUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! CPU mempry-buffer virtual address
|
//! CPU mempry-buffer virtual address
|
||||||
@@ -172,8 +209,9 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
// callback when the buffer is consumed.
|
// callback when the buffer is consumed.
|
||||||
Callback callback = nullptr;
|
Callback mCallback = nullptr;
|
||||||
void* user = nullptr;
|
void* mUser = nullptr;
|
||||||
|
CallbackHandler* mHandler = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace filament::backend
|
} // namespace filament::backend
|
||||||
|
|||||||
74
ios/include/backend/CallbackHandler.h
Normal file
74
ios/include/backend/CallbackHandler.h
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TNT_FILAMENT_BACKEND_CALLBACKHANDLER_H
|
||||||
|
#define TNT_FILAMENT_BACKEND_CALLBACKHANDLER_H
|
||||||
|
|
||||||
|
#include <utils/compiler.h>
|
||||||
|
|
||||||
|
namespace filament::backend {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A generic interface to dispatch callbacks.
|
||||||
|
*
|
||||||
|
* All APIs that take a callback as argument also take a
|
||||||
|
* CallbackHandler* which is used to dispatch the
|
||||||
|
* callback: CallbackHandler::post() method is called from a service thread as soon
|
||||||
|
* as possible (this will NEVER be the main thread), CallbackHandler::post()
|
||||||
|
* is responsible for scheduling the callback onto the thread the
|
||||||
|
* user desires.
|
||||||
|
*
|
||||||
|
* This is intended to make callbacks interoperate with
|
||||||
|
* the platform/OS's own messaging system.
|
||||||
|
*
|
||||||
|
* CallbackHandler* can always be nullptr in which case the default handler is used. The
|
||||||
|
* default handler always dispatches callbacks on filament's main thread opportunistically.
|
||||||
|
*
|
||||||
|
* Life time:
|
||||||
|
* ---------
|
||||||
|
*
|
||||||
|
* Filament make no attempts to manage the life time of the CallbackHandler* and never takes
|
||||||
|
* ownership.
|
||||||
|
* In particular, this means that the CallbackHandler instance must stay valid until all
|
||||||
|
* pending callbacks are been dispatched.
|
||||||
|
*
|
||||||
|
* Similarly, when shutting down filament, care must be taken to ensure that all pending callbacks
|
||||||
|
* that might access filament's state have been dispatched. Filament can no longer ensure this
|
||||||
|
* because callback execution is the responsibility of the CallbackHandler, which is external to
|
||||||
|
* filament.
|
||||||
|
* Typically, the concrete CallbackHandler would have a mechanism to drain and/or wait for all
|
||||||
|
* callbacks to be processed.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class CallbackHandler {
|
||||||
|
public:
|
||||||
|
using Callback = void(*)(void* user);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedules the callback to be called onto the appropriate thread.
|
||||||
|
* Typically this will be the application's main thead.
|
||||||
|
*
|
||||||
|
* Must be thread-safe.
|
||||||
|
*/
|
||||||
|
virtual void post(void* user, Callback callback) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual ~CallbackHandler();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace filament::backend
|
||||||
|
|
||||||
|
#endif // TNT_FILAMENT_BACKEND_CALLBACKHANDLER_H
|
||||||
@@ -195,7 +195,9 @@ enum class PrimitiveType : uint8_t {
|
|||||||
// don't change the enums values (made to match GL)
|
// don't change the enums values (made to match GL)
|
||||||
POINTS = 0, //!< points
|
POINTS = 0, //!< points
|
||||||
LINES = 1, //!< lines
|
LINES = 1, //!< lines
|
||||||
|
LINE_STRIP = 3, //!< line strip
|
||||||
TRIANGLES = 4, //!< triangles
|
TRIANGLES = 4, //!< triangles
|
||||||
|
TRIANGLE_STRIP = 5, //!< triangle strip
|
||||||
NONE = 0xFF
|
NONE = 0xFF
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -220,7 +222,8 @@ enum class UniformType : uint8_t {
|
|||||||
UINT3,
|
UINT3,
|
||||||
UINT4,
|
UINT4,
|
||||||
MAT3, //!< a 3x3 float matrix
|
MAT3, //!< a 3x3 float matrix
|
||||||
MAT4 //!< a 4x4 float matrix
|
MAT4, //!< a 4x4 float matrix
|
||||||
|
STRUCT
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class Precision : uint8_t {
|
enum class Precision : uint8_t {
|
||||||
@@ -806,10 +809,10 @@ using AttributeArray = std::array<Attribute, MAX_VERTEX_ATTRIBUTE_COUNT>;
|
|||||||
//! Raster state descriptor
|
//! Raster state descriptor
|
||||||
struct RasterState {
|
struct RasterState {
|
||||||
|
|
||||||
using CullingMode = CullingMode;
|
using CullingMode = backend::CullingMode;
|
||||||
using DepthFunc = SamplerCompareFunc;
|
using DepthFunc = backend::SamplerCompareFunc;
|
||||||
using BlendEquation = BlendEquation;
|
using BlendEquation = backend::BlendEquation;
|
||||||
using BlendFunction = BlendFunction;
|
using BlendFunction = backend::BlendFunction;
|
||||||
|
|
||||||
RasterState() noexcept { // NOLINT
|
RasterState() noexcept { // NOLINT
|
||||||
static_assert(sizeof(RasterState) == sizeof(uint32_t),
|
static_assert(sizeof(RasterState) == sizeof(uint32_t),
|
||||||
|
|||||||
@@ -21,6 +21,8 @@
|
|||||||
#include <utils/Log.h>
|
#include <utils/Log.h>
|
||||||
#include <utils/debug.h>
|
#include <utils/debug.h>
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
namespace filament {
|
namespace filament {
|
||||||
namespace backend {
|
namespace backend {
|
||||||
|
|
||||||
|
|||||||
@@ -28,8 +28,7 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
namespace filament {
|
namespace filament::backend {
|
||||||
namespace backend {
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A descriptor to an image in main memory, typically used to transfer image data from the CPU
|
* A descriptor to an image in main memory, typically used to transfer image data from the CPU
|
||||||
@@ -58,9 +57,19 @@ public:
|
|||||||
* @param left Left coordinate in pixels
|
* @param left Left coordinate in pixels
|
||||||
* @param top Top coordinate in pixels
|
* @param top Top coordinate in pixels
|
||||||
* @param stride Stride of a row in pixels
|
* @param stride Stride of a row in pixels
|
||||||
|
* @param handler Handler to dispatch the callback or nullptr for the default handler
|
||||||
* @param callback A callback used to release the CPU buffer
|
* @param callback A callback used to release the CPU buffer
|
||||||
* @param user An opaque user pointer passed to the callback function when it's called
|
* @param user An opaque user pointer passed to the callback function when it's called
|
||||||
*/
|
*/
|
||||||
|
PixelBufferDescriptor(void const* buffer, size_t size,
|
||||||
|
PixelDataFormat format, PixelDataType type, uint8_t alignment,
|
||||||
|
uint32_t left, uint32_t top, uint32_t stride,
|
||||||
|
CallbackHandler* handler, Callback callback, void* user = nullptr) noexcept
|
||||||
|
: BufferDescriptor(buffer, size, handler, callback, user),
|
||||||
|
left(left), top(top), stride(stride),
|
||||||
|
format(format), type(type), alignment(alignment) {
|
||||||
|
}
|
||||||
|
|
||||||
PixelBufferDescriptor(void const* buffer, size_t size,
|
PixelBufferDescriptor(void const* buffer, size_t size,
|
||||||
PixelDataFormat format, PixelDataType type, uint8_t alignment = 1,
|
PixelDataFormat format, PixelDataType type, uint8_t alignment = 1,
|
||||||
uint32_t left = 0, uint32_t top = 0, uint32_t stride = 0,
|
uint32_t left = 0, uint32_t top = 0, uint32_t stride = 0,
|
||||||
@@ -77,9 +86,17 @@ public:
|
|||||||
* @param size Size in bytes of the buffer containing the image
|
* @param size Size in bytes of the buffer containing the image
|
||||||
* @param format Format of the image pixels
|
* @param format Format of the image pixels
|
||||||
* @param type Type of the image pixels
|
* @param type Type of the image pixels
|
||||||
|
* @param handler Handler to dispatch the callback or nullptr for the default handler
|
||||||
* @param callback A callback used to release the CPU buffer
|
* @param callback A callback used to release the CPU buffer
|
||||||
* @param user An opaque user pointer passed to the callback function when it's called
|
* @param user An opaque user pointer passed to the callback function when it's called
|
||||||
*/
|
*/
|
||||||
|
PixelBufferDescriptor(void const* buffer, size_t size,
|
||||||
|
PixelDataFormat format, PixelDataType type,
|
||||||
|
CallbackHandler* handler, Callback callback, void* user = nullptr) noexcept
|
||||||
|
: BufferDescriptor(buffer, size, handler, callback, user),
|
||||||
|
stride(0), format(format), type(type), alignment(1) {
|
||||||
|
}
|
||||||
|
|
||||||
PixelBufferDescriptor(void const* buffer, size_t size,
|
PixelBufferDescriptor(void const* buffer, size_t size,
|
||||||
PixelDataFormat format, PixelDataType type,
|
PixelDataFormat format, PixelDataType type,
|
||||||
Callback callback, void* user = nullptr) noexcept
|
Callback callback, void* user = nullptr) noexcept
|
||||||
@@ -87,6 +104,7 @@ public:
|
|||||||
stride(0), format(format), type(type), alignment(1) {
|
stride(0), format(format), type(type), alignment(1) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new PixelBufferDescriptor referencing a compressed image in main memory
|
* Creates a new PixelBufferDescriptor referencing a compressed image in main memory
|
||||||
*
|
*
|
||||||
@@ -94,9 +112,18 @@ public:
|
|||||||
* @param size Size in bytes of the buffer containing the image
|
* @param size Size in bytes of the buffer containing the image
|
||||||
* @param format Compressed format of the image
|
* @param format Compressed format of the image
|
||||||
* @param imageSize Compressed size of the image
|
* @param imageSize Compressed size of the image
|
||||||
|
* @param handler Handler to dispatch the callback or nullptr for the default handler
|
||||||
* @param callback A callback used to release the CPU buffer
|
* @param callback A callback used to release the CPU buffer
|
||||||
* @param user An opaque user pointer passed to the callback function when it's called
|
* @param user An opaque user pointer passed to the callback function when it's called
|
||||||
*/
|
*/
|
||||||
|
PixelBufferDescriptor(void const* buffer, size_t size,
|
||||||
|
backend::CompressedPixelDataType format, uint32_t imageSize,
|
||||||
|
CallbackHandler* handler, Callback callback, void* user = nullptr) noexcept
|
||||||
|
: BufferDescriptor(buffer, size, handler, callback, user),
|
||||||
|
imageSize(imageSize), compressedFormat(format), type(PixelDataType::COMPRESSED),
|
||||||
|
alignment(1) {
|
||||||
|
}
|
||||||
|
|
||||||
PixelBufferDescriptor(void const* buffer, size_t size,
|
PixelBufferDescriptor(void const* buffer, size_t size,
|
||||||
backend::CompressedPixelDataType format, uint32_t imageSize,
|
backend::CompressedPixelDataType format, uint32_t imageSize,
|
||||||
Callback callback, void* user = nullptr) noexcept
|
Callback callback, void* user = nullptr) noexcept
|
||||||
@@ -107,26 +134,29 @@ public:
|
|||||||
|
|
||||||
// --------------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
template<typename T, void(T::*method)(void const* buffer, size_t size)>
|
template<typename T, void(T::*method)(void const*, size_t)>
|
||||||
static PixelBufferDescriptor make(void const* buffer, size_t size,
|
static PixelBufferDescriptor make(void const* buffer, size_t size,
|
||||||
PixelDataFormat format, PixelDataType type, uint8_t alignment,
|
PixelDataFormat format, PixelDataType type, uint8_t alignment,
|
||||||
uint32_t left, uint32_t top, uint32_t stride, T* data) noexcept {
|
uint32_t left, uint32_t top, uint32_t stride, T* data,
|
||||||
|
CallbackHandler* handler = nullptr) noexcept {
|
||||||
return { buffer, size, format, type, alignment, left, top, stride,
|
return { buffer, size, format, type, alignment, left, top, stride,
|
||||||
[](void* b, size_t s, void* u) {
|
handler, [](void* b, size_t s, void* u) {
|
||||||
(*static_cast<T**>(u)->*method)(b, s); }, data };
|
(*static_cast<T**>(u)->*method)(b, s); }, data };
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, void(T::*method)(void const* buffer, size_t size)>
|
template<typename T, void(T::*method)(void const*, size_t)>
|
||||||
static PixelBufferDescriptor make(void const* buffer, size_t size,
|
static PixelBufferDescriptor make(void const* buffer, size_t size,
|
||||||
PixelDataFormat format, PixelDataType type, T* data) noexcept {
|
PixelDataFormat format, PixelDataType type, T* data,
|
||||||
return { buffer, size, format, type, [](void* b, size_t s, void* u) {
|
CallbackHandler* handler = nullptr) noexcept {
|
||||||
|
return { buffer, size, format, type, handler, [](void* b, size_t s, void* u) {
|
||||||
(*static_cast<T**>(u)->*method)(b, s); }, data };
|
(*static_cast<T**>(u)->*method)(b, s); }, data };
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, void(T::*method)(void const* buffer, size_t size)>
|
template<typename T, void(T::*method)(void const*, size_t)>
|
||||||
static PixelBufferDescriptor make(void const* buffer, size_t size,
|
static PixelBufferDescriptor make(void const* buffer, size_t size,
|
||||||
backend::CompressedPixelDataType format, uint32_t imageSize, T* data) noexcept {
|
backend::CompressedPixelDataType format, uint32_t imageSize, T* data,
|
||||||
return { buffer, size, format, imageSize, [](void* b, size_t s, void* u) {
|
CallbackHandler* handler = nullptr) noexcept {
|
||||||
|
return { buffer, size, format, imageSize, handler, [](void* b, size_t s, void* u) {
|
||||||
(*static_cast<T**>(u)->*method)(b, s); }, data
|
(*static_cast<T**>(u)->*method)(b, s); }, data
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -134,9 +164,10 @@ public:
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
static PixelBufferDescriptor make(void const* buffer, size_t size,
|
static PixelBufferDescriptor make(void const* buffer, size_t size,
|
||||||
PixelDataFormat format, PixelDataType type, uint8_t alignment,
|
PixelDataFormat format, PixelDataType type, uint8_t alignment,
|
||||||
uint32_t left, uint32_t top, uint32_t stride, T&& functor) noexcept {
|
uint32_t left, uint32_t top, uint32_t stride, T&& functor,
|
||||||
|
CallbackHandler* handler = nullptr) noexcept {
|
||||||
return { buffer, size, format, type, alignment, left, top, stride,
|
return { buffer, size, format, type, alignment, left, top, stride,
|
||||||
[](void* b, size_t s, void* u) {
|
handler, [](void* b, size_t s, void* u) {
|
||||||
T& that = *static_cast<T*>(u);
|
T& that = *static_cast<T*>(u);
|
||||||
that(b, s);
|
that(b, s);
|
||||||
delete &that;
|
delete &that;
|
||||||
@@ -146,9 +177,10 @@ public:
|
|||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static PixelBufferDescriptor make(void const* buffer, size_t size,
|
static PixelBufferDescriptor make(void const* buffer, size_t size,
|
||||||
PixelDataFormat format, PixelDataType type, T&& functor) noexcept {
|
PixelDataFormat format, PixelDataType type, T&& functor,
|
||||||
|
CallbackHandler* handler = nullptr) noexcept {
|
||||||
return { buffer, size, format, type,
|
return { buffer, size, format, type,
|
||||||
[](void* b, size_t s, void* u) {
|
handler, [](void* b, size_t s, void* u) {
|
||||||
T& that = *static_cast<T*>(u);
|
T& that = *static_cast<T*>(u);
|
||||||
that(b, s);
|
that(b, s);
|
||||||
delete &that;
|
delete &that;
|
||||||
@@ -158,9 +190,10 @@ public:
|
|||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static PixelBufferDescriptor make(void const* buffer, size_t size,
|
static PixelBufferDescriptor make(void const* buffer, size_t size,
|
||||||
backend::CompressedPixelDataType format, uint32_t imageSize, T&& functor) noexcept {
|
backend::CompressedPixelDataType format, uint32_t imageSize, T&& functor,
|
||||||
|
CallbackHandler* handler = nullptr) noexcept {
|
||||||
return { buffer, size, format, imageSize,
|
return { buffer, size, format, imageSize,
|
||||||
[](void* b, size_t s, void* u) {
|
handler, [](void* b, size_t s, void* u) {
|
||||||
T& that = *static_cast<T*>(u);
|
T& that = *static_cast<T*>(u);
|
||||||
that(b, s);
|
that(b, s);
|
||||||
delete &that;
|
delete &that;
|
||||||
@@ -275,8 +308,7 @@ public:
|
|||||||
uint8_t alignment : 4;
|
uint8_t alignment : 4;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace backend
|
} // namespace backend::filament
|
||||||
} // namespace filament
|
|
||||||
|
|
||||||
#if !defined(NDEBUG)
|
#if !defined(NDEBUG)
|
||||||
utils::io::ostream& operator<<(utils::io::ostream& out, const filament::backend::PixelBufferDescriptor& b);
|
utils::io::ostream& operator<<(utils::io::ostream& out, const filament::backend::PixelBufferDescriptor& b);
|
||||||
|
|||||||
6552
ios/include/cgltf.h
Normal file
6552
ios/include/cgltf.h
Normal file
File diff suppressed because it is too large
Load Diff
120
ios/include/common/CallbackUtils.cpp
Normal file
120
ios/include/common/CallbackUtils.cpp
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CallbackUtils.h"
|
||||||
|
|
||||||
|
#include "private/backend/VirtualMachineEnv.h"
|
||||||
|
|
||||||
|
void acquireCallbackJni(JNIEnv* env, CallbackJni& callbackUtils) {
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
callbackUtils.handlerClass = env->FindClass("android/os/Handler");
|
||||||
|
callbackUtils.handlerClass = (jclass) env->NewGlobalRef(callbackUtils.handlerClass);
|
||||||
|
callbackUtils.post = env->GetMethodID(callbackUtils.handlerClass,
|
||||||
|
"post", "(Ljava/lang/Runnable;)Z");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
callbackUtils.executorClass = env->FindClass("java/util/concurrent/Executor");
|
||||||
|
callbackUtils.executorClass = (jclass) env->NewGlobalRef(callbackUtils.executorClass);
|
||||||
|
callbackUtils.execute = env->GetMethodID(callbackUtils.executorClass,
|
||||||
|
"execute", "(Ljava/lang/Runnable;)V");
|
||||||
|
}
|
||||||
|
|
||||||
|
void releaseCallbackJni(JNIEnv* env, CallbackJni callbackUtils, jobject handler, jobject callback) {
|
||||||
|
if (handler && callback) {
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
if (env->IsInstanceOf(handler, callbackUtils.handlerClass)) {
|
||||||
|
env->CallBooleanMethod(handler, callbackUtils.post, callback);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (env->IsInstanceOf(handler, callbackUtils.executorClass)) {
|
||||||
|
env->CallVoidMethod(handler, callbackUtils.execute, callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
env->DeleteGlobalRef(handler);
|
||||||
|
env->DeleteGlobalRef(callback);
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
env->DeleteGlobalRef(callbackUtils.handlerClass);
|
||||||
|
#endif
|
||||||
|
env->DeleteGlobalRef(callbackUtils.executorClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
JniCallback* JniCallback::make(JNIEnv* env, jobject handler, jobject callback) {
|
||||||
|
return new JniCallback(env, handler, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
JniCallback::JniCallback(JNIEnv* env, jobject handler, jobject callback)
|
||||||
|
: mHandler(env->NewGlobalRef(handler)),
|
||||||
|
mCallback(env->NewGlobalRef(callback)) {
|
||||||
|
acquireCallbackJni(env, mCallbackUtils);
|
||||||
|
}
|
||||||
|
|
||||||
|
JniCallback::~JniCallback() = default;
|
||||||
|
|
||||||
|
void JniCallback::post(void* user, filament::backend::CallbackHandler::Callback callback) {
|
||||||
|
callback(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
void JniCallback::postToJavaAndDestroy(JniCallback* callback) {
|
||||||
|
JNIEnv* env = filament::VirtualMachineEnv::get().getEnvironment();
|
||||||
|
releaseCallbackJni(env, callback->mCallbackUtils, callback->mHandler, callback->mCallback);
|
||||||
|
delete callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
JniBufferCallback* JniBufferCallback::make(filament::Engine*,
|
||||||
|
JNIEnv* env, jobject handler, jobject callback, AutoBuffer&& buffer) {
|
||||||
|
return new JniBufferCallback(env, handler, callback, std::move(buffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
JniBufferCallback::JniBufferCallback(JNIEnv* env, jobject handler, jobject callback,
|
||||||
|
AutoBuffer&& buffer)
|
||||||
|
: JniCallback(env, handler, callback),
|
||||||
|
mBuffer(std::move(buffer)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
JniBufferCallback::~JniBufferCallback() = default;
|
||||||
|
|
||||||
|
void JniBufferCallback::postToJavaAndDestroy(void*, size_t, void* user) {
|
||||||
|
JniBufferCallback* callback = (JniBufferCallback*)user;
|
||||||
|
JNIEnv* env = filament::VirtualMachineEnv::get().getEnvironment();
|
||||||
|
callback->mBuffer.attachToJniThread(env);
|
||||||
|
releaseCallbackJni(env, callback->mCallbackUtils, callback->mHandler, callback->mCallback);
|
||||||
|
delete callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
JniImageCallback* JniImageCallback::make(filament::Engine*,
|
||||||
|
JNIEnv* env, jobject handler, jobject callback, long image) {
|
||||||
|
return new JniImageCallback(env, handler, callback, image);
|
||||||
|
}
|
||||||
|
|
||||||
|
JniImageCallback::JniImageCallback(JNIEnv* env, jobject handler, jobject callback, long image)
|
||||||
|
: JniCallback(env, handler, callback),
|
||||||
|
mImage(image) {
|
||||||
|
}
|
||||||
|
|
||||||
|
JniImageCallback::~JniImageCallback() = default;
|
||||||
|
|
||||||
|
void JniImageCallback::postToJavaAndDestroy(void*, void* user) {
|
||||||
|
JniImageCallback* callback = (JniImageCallback*)user;
|
||||||
|
JNIEnv* env = filament::VirtualMachineEnv::get().getEnvironment();
|
||||||
|
releaseCallbackJni(env, callback->mCallbackUtils, callback->mHandler, callback->mCallback);
|
||||||
|
delete callback;
|
||||||
|
}
|
||||||
95
ios/include/common/CallbackUtils.h
Normal file
95
ios/include/common/CallbackUtils.h
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <jni.h>
|
||||||
|
|
||||||
|
#include "common/NioUtils.h"
|
||||||
|
|
||||||
|
#include <backend/CallbackHandler.h>
|
||||||
|
|
||||||
|
#include <filament/Engine.h>
|
||||||
|
|
||||||
|
struct CallbackJni {
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
jclass handlerClass = nullptr;
|
||||||
|
jmethodID post = nullptr;
|
||||||
|
#endif
|
||||||
|
jclass executorClass = nullptr;
|
||||||
|
jmethodID execute = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
void acquireCallbackJni(JNIEnv* env, CallbackJni& callbackUtils);
|
||||||
|
void releaseCallbackJni(JNIEnv* env, CallbackJni callbackUtils, jobject handler, jobject callback);
|
||||||
|
|
||||||
|
struct JniCallback : private filament::backend::CallbackHandler {
|
||||||
|
JniCallback(JniCallback const &) = delete;
|
||||||
|
JniCallback(JniCallback&&) = delete;
|
||||||
|
JniCallback& operator=(JniCallback const &) = delete;
|
||||||
|
JniCallback& operator=(JniCallback&&) = delete;
|
||||||
|
|
||||||
|
// create a JniCallback
|
||||||
|
static JniCallback* make(JNIEnv* env, jobject handler, jobject runnable);
|
||||||
|
|
||||||
|
// execute the callback on the java thread and destroy ourselves
|
||||||
|
static void postToJavaAndDestroy(JniCallback* callback);
|
||||||
|
|
||||||
|
// CallbackHandler interface.
|
||||||
|
void post(void* user, Callback callback) override;
|
||||||
|
|
||||||
|
// Get the CallbackHandler interface
|
||||||
|
filament::backend::CallbackHandler* getHandler() noexcept { return this; }
|
||||||
|
|
||||||
|
jobject getCallbackObject() { return mCallback; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
JniCallback(JNIEnv* env, jobject handler, jobject runnable);
|
||||||
|
explicit JniCallback() = default; // this version does nothing
|
||||||
|
virtual ~JniCallback();
|
||||||
|
jobject mHandler{};
|
||||||
|
jobject mCallback{};
|
||||||
|
CallbackJni mCallbackUtils{};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct JniBufferCallback : public JniCallback {
|
||||||
|
// create a JniBufferCallback
|
||||||
|
static JniBufferCallback* make(filament::Engine* engine,
|
||||||
|
JNIEnv* env, jobject handler, jobject callback, AutoBuffer&& buffer);
|
||||||
|
|
||||||
|
// execute the callback on the java thread and destroy ourselves
|
||||||
|
static void postToJavaAndDestroy(void*, size_t, void* user);
|
||||||
|
|
||||||
|
private:
|
||||||
|
JniBufferCallback(JNIEnv* env, jobject handler, jobject callback, AutoBuffer&& buffer);
|
||||||
|
virtual ~JniBufferCallback();
|
||||||
|
AutoBuffer mBuffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct JniImageCallback : public JniCallback {
|
||||||
|
// create a JniImageCallback
|
||||||
|
static JniImageCallback* make(filament::Engine* engine, JNIEnv* env, jobject handler,
|
||||||
|
jobject runnable, long image);
|
||||||
|
|
||||||
|
// execute the callback on the java thread and destroy ourselves
|
||||||
|
static void postToJavaAndDestroy(void*, void* user);
|
||||||
|
|
||||||
|
private:
|
||||||
|
JniImageCallback(JNIEnv* env, jobject handler, jobject runnable, long image);
|
||||||
|
virtual ~JniImageCallback();
|
||||||
|
long mImage;
|
||||||
|
};
|
||||||
151
ios/include/common/NioUtils.cpp
Normal file
151
ios/include/common/NioUtils.cpp
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "common/NioUtils.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include <utils/Log.h>
|
||||||
|
|
||||||
|
AutoBuffer::AutoBuffer(JNIEnv *env, jobject buffer, jint size, bool commit) noexcept :
|
||||||
|
mEnv(env),
|
||||||
|
mDoCommit(commit) {
|
||||||
|
|
||||||
|
mNioUtils.jniClass = env->FindClass("com/google/android/filament/NioUtils");
|
||||||
|
mNioUtils.jniClass = (jclass) env->NewGlobalRef(mNioUtils.jniClass);
|
||||||
|
|
||||||
|
mNioUtils.getBasePointer = env->GetStaticMethodID(mNioUtils.jniClass,
|
||||||
|
"getBasePointer", "(Ljava/nio/Buffer;JI)J");
|
||||||
|
mNioUtils.getBaseArray = env->GetStaticMethodID(mNioUtils.jniClass,
|
||||||
|
"getBaseArray", "(Ljava/nio/Buffer;)Ljava/lang/Object;");
|
||||||
|
mNioUtils.getBaseArrayOffset = env->GetStaticMethodID(mNioUtils.jniClass,
|
||||||
|
"getBaseArrayOffset", "(Ljava/nio/Buffer;I)I");
|
||||||
|
mNioUtils.getBufferType = env->GetStaticMethodID(mNioUtils.jniClass,
|
||||||
|
"getBufferType", "(Ljava/nio/Buffer;)I");
|
||||||
|
|
||||||
|
mBuffer = env->NewGlobalRef(buffer);
|
||||||
|
|
||||||
|
mType = (BufferType) env->CallStaticIntMethod(
|
||||||
|
mNioUtils.jniClass, mNioUtils.getBufferType, mBuffer);
|
||||||
|
|
||||||
|
switch (mType) {
|
||||||
|
case BufferType::BYTE:
|
||||||
|
mShift = 0;
|
||||||
|
break;
|
||||||
|
case BufferType::CHAR:
|
||||||
|
case BufferType::SHORT:
|
||||||
|
mShift = 1;
|
||||||
|
break;
|
||||||
|
case BufferType::INT:
|
||||||
|
case BufferType::FLOAT:
|
||||||
|
mShift = 2;
|
||||||
|
break;
|
||||||
|
case BufferType::LONG:
|
||||||
|
case BufferType::DOUBLE:
|
||||||
|
mShift = 3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
mSize = (size_t) size << mShift;
|
||||||
|
|
||||||
|
jlong address = (jlong) env->GetDirectBufferAddress(mBuffer);
|
||||||
|
if (address) {
|
||||||
|
// Direct buffer case
|
||||||
|
mData = reinterpret_cast<void *>(env->CallStaticLongMethod(mNioUtils.jniClass,
|
||||||
|
mNioUtils.getBasePointer, mBuffer, address, mShift));
|
||||||
|
mUserData = mData;
|
||||||
|
} else {
|
||||||
|
// wrapped array case
|
||||||
|
jarray array = (jarray) env->CallStaticObjectMethod(mNioUtils.jniClass,
|
||||||
|
mNioUtils.getBaseArray, mBuffer);
|
||||||
|
|
||||||
|
jint offset = env->CallStaticIntMethod(mNioUtils.jniClass,
|
||||||
|
mNioUtils.getBaseArrayOffset, mBuffer, mShift);
|
||||||
|
|
||||||
|
mBaseArray = (jarray) env->NewGlobalRef(array);
|
||||||
|
switch (mType) {
|
||||||
|
case BufferType::BYTE:
|
||||||
|
mData = env->GetByteArrayElements((jbyteArray)mBaseArray, nullptr);
|
||||||
|
break;
|
||||||
|
case BufferType::CHAR:
|
||||||
|
mData = env->GetCharArrayElements((jcharArray)mBaseArray, nullptr);
|
||||||
|
break;
|
||||||
|
case BufferType::SHORT:
|
||||||
|
mData = env->GetShortArrayElements((jshortArray)mBaseArray, nullptr);
|
||||||
|
break;
|
||||||
|
case BufferType::INT:
|
||||||
|
mData = env->GetIntArrayElements((jintArray)mBaseArray, nullptr);
|
||||||
|
break;
|
||||||
|
case BufferType::LONG:
|
||||||
|
mData = env->GetLongArrayElements((jlongArray)mBaseArray, nullptr);
|
||||||
|
break;
|
||||||
|
case BufferType::FLOAT:
|
||||||
|
mData = env->GetFloatArrayElements((jfloatArray)mBaseArray, nullptr);
|
||||||
|
break;
|
||||||
|
case BufferType::DOUBLE:
|
||||||
|
mData = env->GetDoubleArrayElements((jdoubleArray)mBaseArray, nullptr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
mUserData = (void *) ((char *) mData + offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AutoBuffer::AutoBuffer(AutoBuffer &&rhs) noexcept {
|
||||||
|
mEnv = rhs.mEnv;
|
||||||
|
std::swap(mData, rhs.mData);
|
||||||
|
std::swap(mUserData, rhs.mUserData);
|
||||||
|
std::swap(mSize, rhs.mSize);
|
||||||
|
std::swap(mType, rhs.mType);
|
||||||
|
std::swap(mShift, rhs.mShift);
|
||||||
|
std::swap(mBuffer, rhs.mBuffer);
|
||||||
|
std::swap(mBaseArray, rhs.mBaseArray);
|
||||||
|
std::swap(mNioUtils, rhs.mNioUtils);
|
||||||
|
}
|
||||||
|
|
||||||
|
AutoBuffer::~AutoBuffer() noexcept {
|
||||||
|
JNIEnv *env = mEnv;
|
||||||
|
if (mBaseArray) {
|
||||||
|
jint mode = mDoCommit ? 0 : JNI_ABORT;
|
||||||
|
switch (mType) {
|
||||||
|
case BufferType::BYTE:
|
||||||
|
env->ReleaseByteArrayElements((jbyteArray)mBaseArray, (jbyte *) mData, mode);
|
||||||
|
break;
|
||||||
|
case BufferType::CHAR:
|
||||||
|
env->ReleaseCharArrayElements((jcharArray)mBaseArray, (jchar *) mData, mode);
|
||||||
|
break;
|
||||||
|
case BufferType::SHORT:
|
||||||
|
env->ReleaseShortArrayElements((jshortArray)mBaseArray, (jshort *) mData, mode);
|
||||||
|
break;
|
||||||
|
case BufferType::INT:
|
||||||
|
env->ReleaseIntArrayElements((jintArray)mBaseArray, (jint *) mData, mode);
|
||||||
|
break;
|
||||||
|
case BufferType::LONG:
|
||||||
|
env->ReleaseLongArrayElements((jlongArray)mBaseArray, (jlong *) mData, mode);
|
||||||
|
break;
|
||||||
|
case BufferType::FLOAT:
|
||||||
|
env->ReleaseFloatArrayElements((jfloatArray)mBaseArray, (jfloat *) mData, mode);
|
||||||
|
break;
|
||||||
|
case BufferType::DOUBLE:
|
||||||
|
env->ReleaseDoubleArrayElements((jdoubleArray)mBaseArray, (jdouble *) mData, mode);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
env->DeleteGlobalRef(mBaseArray);
|
||||||
|
}
|
||||||
|
if (mBuffer) {
|
||||||
|
env->DeleteGlobalRef(mBuffer);
|
||||||
|
}
|
||||||
|
mEnv->DeleteGlobalRef(mNioUtils.jniClass);
|
||||||
|
}
|
||||||
80
ios/include/common/NioUtils.h
Normal file
80
ios/include/common/NioUtils.h
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#include <jni.h>
|
||||||
|
|
||||||
|
class AutoBuffer {
|
||||||
|
public:
|
||||||
|
enum class BufferType : uint8_t {
|
||||||
|
BYTE,
|
||||||
|
CHAR,
|
||||||
|
SHORT,
|
||||||
|
INT,
|
||||||
|
LONG,
|
||||||
|
FLOAT,
|
||||||
|
DOUBLE
|
||||||
|
};
|
||||||
|
|
||||||
|
// Clients should pass "true" for the commit argument if they intend to mutate the buffer
|
||||||
|
// contents from native code.
|
||||||
|
AutoBuffer(JNIEnv* env, jobject buffer, jint size, bool commit = false) noexcept;
|
||||||
|
AutoBuffer(AutoBuffer&& rhs) noexcept;
|
||||||
|
~AutoBuffer() noexcept;
|
||||||
|
|
||||||
|
void attachToJniThread(JNIEnv* env) noexcept {
|
||||||
|
mEnv = env;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* getData() const noexcept {
|
||||||
|
return mUserData;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getSize() const noexcept {
|
||||||
|
return mSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getShift() const noexcept {
|
||||||
|
return mShift;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t countToByte(size_t count) const noexcept {
|
||||||
|
return count << mShift;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void* mUserData = nullptr;
|
||||||
|
size_t mSize = 0;
|
||||||
|
BufferType mType = BufferType::BYTE;
|
||||||
|
uint8_t mShift = 0;
|
||||||
|
|
||||||
|
JNIEnv* mEnv;
|
||||||
|
void* mData = nullptr;
|
||||||
|
jobject mBuffer = nullptr;
|
||||||
|
jarray mBaseArray = nullptr;
|
||||||
|
bool mDoCommit = false;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
jclass jniClass;
|
||||||
|
jmethodID getBasePointer;
|
||||||
|
jmethodID getBaseArray;
|
||||||
|
jmethodID getBaseArrayOffset;
|
||||||
|
jmethodID getBufferType;
|
||||||
|
} mNioUtils{};
|
||||||
|
};
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2018 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef TNT_ENUMMANAGER_H
|
|
||||||
#define TNT_ENUMMANAGER_H
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <string>
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
#include <filamat/MaterialBuilder.h>
|
|
||||||
|
|
||||||
namespace filamat {
|
|
||||||
|
|
||||||
using Property = MaterialBuilder::Property;
|
|
||||||
using UniformType = MaterialBuilder::UniformType;
|
|
||||||
using SamplerType = MaterialBuilder::SamplerType;
|
|
||||||
using SubpassType = MaterialBuilder::SubpassType;
|
|
||||||
using SamplerFormat = MaterialBuilder::SamplerFormat;
|
|
||||||
using ParameterPrecision = MaterialBuilder::ParameterPrecision;
|
|
||||||
using OutputTarget = MaterialBuilder::OutputTarget;
|
|
||||||
using OutputQualifier = MaterialBuilder::VariableQualifier;
|
|
||||||
using OutputType = MaterialBuilder::OutputType;
|
|
||||||
|
|
||||||
// Convenience methods to convert std::string to Enum and also iterate over Enum values.
|
|
||||||
class Enums {
|
|
||||||
public:
|
|
||||||
|
|
||||||
// Returns true if string "s" is a valid string representation of an element of enum T.
|
|
||||||
template<typename T>
|
|
||||||
static bool isValid(const std::string& s) noexcept {
|
|
||||||
std::unordered_map<std::string, T>& map = getMap<T>();
|
|
||||||
return map.find(s) != map.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return enum matching its string representation. Returns undefined if s is not a valid enum T
|
|
||||||
// value. You should always call isValid() first to validate a string before calling toEnum().
|
|
||||||
template<typename T>
|
|
||||||
static T toEnum(const std::string& s) noexcept {
|
|
||||||
std::unordered_map<std::string, T>& map = getMap<T>();
|
|
||||||
return map.at(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
static std::string toString(T t) noexcept;
|
|
||||||
|
|
||||||
// Return a map of all values in an enum with their string representation.
|
|
||||||
template<typename T>
|
|
||||||
static std::unordered_map<std::string, T>& map() noexcept {
|
|
||||||
std::unordered_map<std::string, T>& map = getMap<T>();
|
|
||||||
return map;
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
template<typename T>
|
|
||||||
static std::unordered_map<std::string, T>& getMap() noexcept;
|
|
||||||
|
|
||||||
static std::unordered_map<std::string, Property> mStringToProperty;
|
|
||||||
static std::unordered_map<std::string, UniformType> mStringToUniformType;
|
|
||||||
static std::unordered_map<std::string, SamplerType> mStringToSamplerType;
|
|
||||||
static std::unordered_map<std::string, SubpassType> mStringToSubpassType;
|
|
||||||
static std::unordered_map<std::string, SamplerFormat> mStringToSamplerFormat;
|
|
||||||
static std::unordered_map<std::string, ParameterPrecision> mStringToSamplerPrecision;
|
|
||||||
static std::unordered_map<std::string, OutputTarget> mStringToOutputTarget;
|
|
||||||
static std::unordered_map<std::string, OutputQualifier> mStringToOutputQualifier;
|
|
||||||
static std::unordered_map<std::string, OutputType> mStringToOutputType;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
std::string Enums::toString(T t) noexcept {
|
|
||||||
std::unordered_map<std::string, T>& map = getMap<T>();
|
|
||||||
auto result = std::find_if(map.begin(), map.end(), [t](auto& pair) {
|
|
||||||
return pair.second == t;
|
|
||||||
});
|
|
||||||
if (result != map.end()) {
|
|
||||||
return result->first;
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace filamat
|
|
||||||
|
|
||||||
#endif //TNT_ENUMMANAGER_H
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2019 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef TNT_FILAMAT_INCLUDER_H
|
|
||||||
#define TNT_FILAMAT_INCLUDER_H
|
|
||||||
|
|
||||||
#include <utils/CString.h>
|
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
namespace filamat {
|
|
||||||
|
|
||||||
struct IncludeResult {
|
|
||||||
// The include name of the root file, as if it were being included.
|
|
||||||
// I.e., 'foobar.h' in the case of #include "foobar.h"
|
|
||||||
const utils::CString includeName;
|
|
||||||
|
|
||||||
// The following fields should be filled out by the IncludeCallback when processing an include,
|
|
||||||
// or when calling resolveIncludes for the root file.
|
|
||||||
|
|
||||||
// The full contents of the include file. This may contain additional, recursive include
|
|
||||||
// directives.
|
|
||||||
utils::CString text;
|
|
||||||
|
|
||||||
// The line number for the first line of text (first line is 0).
|
|
||||||
size_t lineNumberOffset = 0;
|
|
||||||
|
|
||||||
// The name of the include file. This gets passed as "includerName" for any includes inside of
|
|
||||||
// source. This field isn't used by the include system; it's up to the callback to give meaning
|
|
||||||
// to this value and interpret it accordingly. In the case of DirIncluder, this is an empty
|
|
||||||
// string to represent the root include file, and a canonical path for subsequent included
|
|
||||||
// files.
|
|
||||||
utils::CString name;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A callback invoked by the include system when an #include "file.h" directive is found.
|
|
||||||
*
|
|
||||||
* For example, if a file main.h includes file.h on line 10, then IncludeCallback would be called
|
|
||||||
* with the following:
|
|
||||||
* includeCallback("main.h", {.includeName = "file.h" })
|
|
||||||
* It's then up to the IncludeCallback to fill out the .text, .name, and (optionally)
|
|
||||||
* lineNumberOffset fields.
|
|
||||||
*
|
|
||||||
* @param includedBy is the value that was given to IncludeResult.name for this source file, or
|
|
||||||
* the empty string for the root source file.
|
|
||||||
* @param result is the IncludeResult that the callback should fill out.
|
|
||||||
* @return true, if the include was resolved successfully, false otherwise.
|
|
||||||
*
|
|
||||||
* For an example of implementing this callback, see tools/matc/src/matc/DirIncluder.h.
|
|
||||||
*/
|
|
||||||
using IncludeCallback = std::function<bool(
|
|
||||||
const utils::CString& includedBy,
|
|
||||||
IncludeResult& result)>;
|
|
||||||
|
|
||||||
} // namespace filamat
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,746 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2017 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
//! \file
|
|
||||||
|
|
||||||
#ifndef TNT_FILAMAT_MATERIAL_PACKAGE_BUILDER_H
|
|
||||||
#define TNT_FILAMAT_MATERIAL_PACKAGE_BUILDER_H
|
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
#include <atomic>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include <backend/DriverEnums.h>
|
|
||||||
#include <backend/TargetBufferInfo.h>
|
|
||||||
#include <filament/MaterialEnums.h>
|
|
||||||
|
|
||||||
#include <filamat/IncludeCallback.h>
|
|
||||||
#include <filamat/Package.h>
|
|
||||||
|
|
||||||
#include <utils/BitmaskEnum.h>
|
|
||||||
#include <utils/bitset.h>
|
|
||||||
#include <utils/compiler.h>
|
|
||||||
#include <utils/CString.h>
|
|
||||||
|
|
||||||
namespace utils {
|
|
||||||
class JobSystem;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace filamat {
|
|
||||||
|
|
||||||
struct MaterialInfo;
|
|
||||||
class ChunkContainer;
|
|
||||||
struct Variant;
|
|
||||||
|
|
||||||
class UTILS_PUBLIC MaterialBuilderBase {
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* High-level hint that works in concert with TargetApi to determine the shader models (used to
|
|
||||||
* generate GLSL) and final output representations (spirv and/or text).
|
|
||||||
*/
|
|
||||||
enum class Platform {
|
|
||||||
DESKTOP,
|
|
||||||
MOBILE,
|
|
||||||
ALL
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class TargetApi : uint8_t {
|
|
||||||
OPENGL = 0x01u,
|
|
||||||
VULKAN = 0x02u,
|
|
||||||
METAL = 0x04u,
|
|
||||||
ALL = OPENGL | VULKAN | METAL
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class TargetLanguage {
|
|
||||||
GLSL, // GLSL with OpenGL semantics
|
|
||||||
SPIRV // GLSL with Vulkan semantics
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class Optimization {
|
|
||||||
NONE,
|
|
||||||
PREPROCESSOR,
|
|
||||||
SIZE,
|
|
||||||
PERFORMANCE
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize MaterialBuilder.
|
|
||||||
*
|
|
||||||
* init must be called first before building any materials.
|
|
||||||
*/
|
|
||||||
static void init();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Release internal MaterialBuilder resources.
|
|
||||||
*
|
|
||||||
* Call shutdown when finished building materials to release all internal resources. After
|
|
||||||
* calling shutdown, another call to MaterialBuilder::init must precede another material build.
|
|
||||||
*/
|
|
||||||
static void shutdown();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// Looks at platform and target API, then decides on shader models and output formats.
|
|
||||||
void prepare(bool vulkanSemantics);
|
|
||||||
|
|
||||||
using ShaderModel = filament::backend::ShaderModel;
|
|
||||||
Platform mPlatform = Platform::DESKTOP;
|
|
||||||
TargetApi mTargetApi = (TargetApi) 0;
|
|
||||||
Optimization mOptimization = Optimization::PERFORMANCE;
|
|
||||||
bool mPrintShaders = false;
|
|
||||||
bool mGenerateDebugInfo = false;
|
|
||||||
utils::bitset32 mShaderModels;
|
|
||||||
struct CodeGenParams {
|
|
||||||
int shaderModel;
|
|
||||||
TargetApi targetApi;
|
|
||||||
TargetLanguage targetLanguage;
|
|
||||||
};
|
|
||||||
std::vector<CodeGenParams> mCodeGenPermutations;
|
|
||||||
// For finding properties and running semantic analysis, we always use the same code gen
|
|
||||||
// permutation. This is the first permutation generated with default arguments passed to matc.
|
|
||||||
const CodeGenParams mSemanticCodeGenParams = {
|
|
||||||
.shaderModel = (int) ShaderModel::GL_ES_30,
|
|
||||||
.targetApi = TargetApi::OPENGL,
|
|
||||||
.targetLanguage = TargetLanguage::SPIRV
|
|
||||||
};
|
|
||||||
uint8_t mVariantFilter = 0;
|
|
||||||
|
|
||||||
// Keeps track of how many times MaterialBuilder::init() has been called without a call to
|
|
||||||
// MaterialBuilder::shutdown(). Internally, glslang does something similar. We keep track for
|
|
||||||
// ourselves so we can inform the user if MaterialBuilder::init() hasn't been called before
|
|
||||||
// attempting to build a material.
|
|
||||||
static std::atomic<int> materialBuilderClients;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Utility function that looks at an Engine backend to determine TargetApi
|
|
||||||
inline constexpr MaterialBuilderBase::TargetApi targetApiFromBackend(
|
|
||||||
filament::backend::Backend backend) noexcept {
|
|
||||||
using filament::backend::Backend;
|
|
||||||
using TargetApi = MaterialBuilderBase::TargetApi;
|
|
||||||
switch (backend) {
|
|
||||||
case Backend::DEFAULT: return TargetApi::ALL;
|
|
||||||
case Backend::OPENGL: return TargetApi::OPENGL;
|
|
||||||
case Backend::VULKAN: return TargetApi::VULKAN;
|
|
||||||
case Backend::METAL: return TargetApi::METAL;
|
|
||||||
case Backend::NOOP: return TargetApi::OPENGL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MaterialBuilder builds Filament materials from shader code.
|
|
||||||
*
|
|
||||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
* #include <filamat/MaterialBuilder.h>
|
|
||||||
* using namespace filamat;
|
|
||||||
*
|
|
||||||
* // Must be called before any materials can be built.
|
|
||||||
* MaterialBuilder::init();
|
|
||||||
|
|
||||||
* MaterialBuilder builder;
|
|
||||||
* builder
|
|
||||||
* .name("My material")
|
|
||||||
* .material("void material (inout MaterialInputs material) {"
|
|
||||||
* " prepareMaterial(material);"
|
|
||||||
* " material.baseColor.rgb = float3(1.0, 0.0, 0.0);"
|
|
||||||
* "}")
|
|
||||||
* .shading(MaterialBuilder::Shading::LIT)
|
|
||||||
* .targetApi(MaterialBuilder::TargetApi::ALL)
|
|
||||||
* .platform(MaterialBuilder::Platform::ALL);
|
|
||||||
|
|
||||||
* Package package = builder.build();
|
|
||||||
* if (package.isValid()) {
|
|
||||||
* // success!
|
|
||||||
* }
|
|
||||||
|
|
||||||
* // Call when finished building all materials to release internal
|
|
||||||
* // MaterialBuilder resources.
|
|
||||||
* MaterialBuilder::shutdown();
|
|
||||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
*
|
|
||||||
* @see filament::Material
|
|
||||||
*/
|
|
||||||
class UTILS_PUBLIC MaterialBuilder : public MaterialBuilderBase {
|
|
||||||
public:
|
|
||||||
MaterialBuilder();
|
|
||||||
|
|
||||||
static constexpr size_t MATERIAL_VARIABLES_COUNT = 4;
|
|
||||||
enum class Variable : uint8_t {
|
|
||||||
CUSTOM0,
|
|
||||||
CUSTOM1,
|
|
||||||
CUSTOM2,
|
|
||||||
CUSTOM3
|
|
||||||
// when adding more variables, make sure to update MATERIAL_VARIABLES_COUNT
|
|
||||||
};
|
|
||||||
|
|
||||||
using MaterialDomain = filament::MaterialDomain;
|
|
||||||
using RefractionMode = filament::RefractionMode;
|
|
||||||
using RefractionType = filament::RefractionType;
|
|
||||||
|
|
||||||
using ShaderQuality = filament::ShaderQuality;
|
|
||||||
using BlendingMode = filament::BlendingMode;
|
|
||||||
using Shading = filament::Shading;
|
|
||||||
using Interpolation = filament::Interpolation;
|
|
||||||
using VertexDomain = filament::VertexDomain;
|
|
||||||
using TransparencyMode = filament::TransparencyMode;
|
|
||||||
using SpecularAmbientOcclusion = filament::SpecularAmbientOcclusion;
|
|
||||||
|
|
||||||
using UniformType = filament::backend::UniformType;
|
|
||||||
using SamplerType = filament::backend::SamplerType;
|
|
||||||
using SubpassType = filament::backend::SubpassType;
|
|
||||||
using SamplerFormat = filament::backend::SamplerFormat;
|
|
||||||
using ParameterPrecision = filament::backend::Precision;
|
|
||||||
using CullingMode = filament::backend::CullingMode;
|
|
||||||
|
|
||||||
enum class VariableQualifier : uint8_t {
|
|
||||||
OUT
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class OutputTarget : uint8_t {
|
|
||||||
COLOR,
|
|
||||||
DEPTH
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class OutputType : uint8_t {
|
|
||||||
FLOAT,
|
|
||||||
FLOAT2,
|
|
||||||
FLOAT3,
|
|
||||||
FLOAT4
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PreprocessorDefine {
|
|
||||||
std::string name;
|
|
||||||
std::string value;
|
|
||||||
|
|
||||||
PreprocessorDefine(const std::string& name, const std::string& value) :
|
|
||||||
name(name), value(value) {}
|
|
||||||
};
|
|
||||||
using PreprocessorDefineList = std::vector<PreprocessorDefine>;
|
|
||||||
|
|
||||||
//! Set the name of this material.
|
|
||||||
MaterialBuilder& name(const char* name) noexcept;
|
|
||||||
|
|
||||||
//! Set the file name of this material file. Used in error reporting.
|
|
||||||
MaterialBuilder& fileName(const char* name) noexcept;
|
|
||||||
|
|
||||||
//! Set the shading model.
|
|
||||||
MaterialBuilder& shading(Shading shading) noexcept;
|
|
||||||
|
|
||||||
//! Set the interpolation mode.
|
|
||||||
MaterialBuilder& interpolation(Interpolation interpolation) noexcept;
|
|
||||||
|
|
||||||
//! Add a parameter (i.e., a uniform) to this material.
|
|
||||||
MaterialBuilder& parameter(UniformType type, ParameterPrecision precision,
|
|
||||||
const char* name) noexcept;
|
|
||||||
|
|
||||||
//! Add a parameter (i.e., a uniform) to this material.
|
|
||||||
MaterialBuilder& parameter(UniformType type, const char* name) noexcept {
|
|
||||||
return parameter(type, ParameterPrecision::DEFAULT, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Add a parameter array to this material.
|
|
||||||
MaterialBuilder& parameter(UniformType type, size_t size,
|
|
||||||
ParameterPrecision precision, const char* name) noexcept;
|
|
||||||
|
|
||||||
//! Add a parameter array to this material.
|
|
||||||
MaterialBuilder& parameter(UniformType type, size_t size, const char* name) noexcept {
|
|
||||||
return parameter(type, size, ParameterPrecision::DEFAULT, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a sampler parameter to this material.
|
|
||||||
*
|
|
||||||
* When SamplerType::SAMPLER_EXTERNAL is specifed, format and precision are ignored.
|
|
||||||
*/
|
|
||||||
MaterialBuilder& parameter(SamplerType samplerType, SamplerFormat format,
|
|
||||||
ParameterPrecision precision, const char* name) noexcept;
|
|
||||||
/// @copydoc parameter(SamplerType, SamplerFormat, ParameterPrecision, const char*)
|
|
||||||
MaterialBuilder& parameter(SamplerType samplerType, SamplerFormat format,
|
|
||||||
const char* name) noexcept;
|
|
||||||
/// @copydoc parameter(SamplerType, SamplerFormat, ParameterPrecision, const char*)
|
|
||||||
MaterialBuilder& parameter(SamplerType samplerType, ParameterPrecision precision,
|
|
||||||
const char* name) noexcept;
|
|
||||||
/// @copydoc parameter(SamplerType, SamplerFormat, ParameterPrecision, const char*)
|
|
||||||
MaterialBuilder& parameter(SamplerType samplerType, const char* name) noexcept;
|
|
||||||
|
|
||||||
//! Custom variables (all float4).
|
|
||||||
MaterialBuilder& variable(Variable v, const char* name) noexcept;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Require a specified attribute.
|
|
||||||
*
|
|
||||||
* position is always required and normal depends on the shading model.
|
|
||||||
*/
|
|
||||||
MaterialBuilder& require(filament::VertexAttribute attribute) noexcept;
|
|
||||||
|
|
||||||
//! Specify the domain that this material will operate in.
|
|
||||||
MaterialBuilder& materialDomain(MaterialDomain materialDomain) noexcept;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the code content of this material.
|
|
||||||
*
|
|
||||||
* Surface Domain
|
|
||||||
* --------------
|
|
||||||
*
|
|
||||||
* Materials in the SURFACE domain must declare a function:
|
|
||||||
* ~~~~~
|
|
||||||
* void material(inout MaterialInputs material) {
|
|
||||||
* prepareMaterial(material);
|
|
||||||
* material.baseColor.rgb = float3(1.0, 0.0, 0.0);
|
|
||||||
* }
|
|
||||||
* ~~~~~
|
|
||||||
* this function *must* call `prepareMaterial(material)` before it returns.
|
|
||||||
*
|
|
||||||
* Post-process Domain
|
|
||||||
* -------------------
|
|
||||||
*
|
|
||||||
* Materials in the POST_PROCESS domain must declare a function:
|
|
||||||
* ~~~~~
|
|
||||||
* void postProcess(inout PostProcessInputs postProcess) {
|
|
||||||
* postProcess.color = float4(1.0);
|
|
||||||
* }
|
|
||||||
* ~~~~~
|
|
||||||
*
|
|
||||||
* @param code The source code of the material.
|
|
||||||
* @param line The line number offset of the material, where 0 is the first line. Used for error
|
|
||||||
* reporting
|
|
||||||
*/
|
|
||||||
MaterialBuilder& material(const char* code, size_t line = 0) noexcept;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the callback used for resolving include directives.
|
|
||||||
* The default is no callback, which disallows all includes.
|
|
||||||
*/
|
|
||||||
MaterialBuilder& includeCallback(IncludeCallback callback) noexcept;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the vertex code content of this material.
|
|
||||||
*
|
|
||||||
* Surface Domain
|
|
||||||
* --------------
|
|
||||||
*
|
|
||||||
* Materials in the SURFACE domain must declare a function:
|
|
||||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
* void materialVertex(inout MaterialVertexInputs material) {
|
|
||||||
*
|
|
||||||
* }
|
|
||||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
*
|
|
||||||
* Post-process Domain
|
|
||||||
* -------------------
|
|
||||||
*
|
|
||||||
* Materials in the POST_PROCESS domain must declare a function:
|
|
||||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
* void postProcessVertex(inout PostProcessVertexInputs postProcess) {
|
|
||||||
*
|
|
||||||
* }
|
|
||||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
* @param code The source code of the material.
|
|
||||||
* @param line The line number offset of the material, where 0 is the first line. Used for error
|
|
||||||
* reporting
|
|
||||||
*/
|
|
||||||
MaterialBuilder& materialVertex(const char* code, size_t line = 0) noexcept;
|
|
||||||
|
|
||||||
|
|
||||||
MaterialBuilder& quality(ShaderQuality quality) noexcept;
|
|
||||||
|
|
||||||
//! Set the blending mode for this material.
|
|
||||||
MaterialBuilder& blending(BlendingMode blending) noexcept;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the blending mode of the post-lighting color for this material.
|
|
||||||
* Only OPAQUE, TRANSPARENT and ADD are supported, the default is TRANSPARENT.
|
|
||||||
* This setting requires the material property "postLightingColor" to be set.
|
|
||||||
*/
|
|
||||||
MaterialBuilder& postLightingBlending(BlendingMode blending) noexcept;
|
|
||||||
|
|
||||||
//! Set the vertex domain for this material.
|
|
||||||
MaterialBuilder& vertexDomain(VertexDomain domain) noexcept;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* How triangles are culled by default (doesn't affect points or lines, BACK by default).
|
|
||||||
* Material instances can override this.
|
|
||||||
*/
|
|
||||||
MaterialBuilder& culling(CullingMode culling) noexcept;
|
|
||||||
|
|
||||||
//! Enable / disable color-buffer write (enabled by default, material instances can override).
|
|
||||||
MaterialBuilder& colorWrite(bool enable) noexcept;
|
|
||||||
|
|
||||||
//! Enable / disable depth-buffer write (enabled by default for opaque, disabled for others, material instances can override).
|
|
||||||
MaterialBuilder& depthWrite(bool enable) noexcept;
|
|
||||||
|
|
||||||
//! Enable / disable depth based culling (enabled by default, material instances can override).
|
|
||||||
MaterialBuilder& depthCulling(bool enable) noexcept;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Double-sided materials don't cull faces, equivalent to culling(CullingMode::NONE).
|
|
||||||
* doubleSided() overrides culling() if called.
|
|
||||||
* When called with "false", this enables the capability for a run-time toggle.
|
|
||||||
*/
|
|
||||||
MaterialBuilder& doubleSided(bool doubleSided) noexcept;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Any fragment with an alpha below this threshold is clipped (MASKED blending mode only).
|
|
||||||
* The mask threshold can also be controlled by using the float material parameter called
|
|
||||||
* `_maskThreshold`, or by calling
|
|
||||||
* @ref filament::MaterialInstance::setMaskThreshold "MaterialInstance::setMaskThreshold".
|
|
||||||
*/
|
|
||||||
MaterialBuilder& maskThreshold(float threshold) noexcept;
|
|
||||||
|
|
||||||
//! The material output is multiplied by the shadowing factor (UNLIT model only).
|
|
||||||
MaterialBuilder& shadowMultiplier(bool shadowMultiplier) noexcept;
|
|
||||||
|
|
||||||
//! This material casts transparent shadows. The blending mode must be TRANSPARENT or FADE.
|
|
||||||
MaterialBuilder& transparentShadow(bool transparentShadow) noexcept;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reduces specular aliasing for materials that have low roughness. Turning this feature on also
|
|
||||||
* helps preserve the shapes of specular highlights as an object moves away from the camera.
|
|
||||||
* When turned on, two float material parameters are added to control the effect:
|
|
||||||
* `_specularAAScreenSpaceVariance` and `_specularAAThreshold`. You can also use
|
|
||||||
* @ref filament::MaterialInstance::setSpecularAntiAliasingVariance
|
|
||||||
* "MaterialInstance::setSpecularAntiAliasingVariance" and
|
|
||||||
* @ref filament::MaterialInstance::setSpecularAntiAliasingThreshold
|
|
||||||
* "setSpecularAntiAliasingThreshold"
|
|
||||||
*
|
|
||||||
* Disabled by default.
|
|
||||||
*/
|
|
||||||
MaterialBuilder& specularAntiAliasing(bool specularAntiAliasing) noexcept;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the screen-space variance of the filter kernel used when applying specular
|
|
||||||
* anti-aliasing. The default value is set to 0.15. The specified value should be between 0 and
|
|
||||||
* 1 and will be clamped if necessary.
|
|
||||||
*/
|
|
||||||
MaterialBuilder& specularAntiAliasingVariance(float screenSpaceVariance) noexcept;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the clamping threshold used to suppress estimation errors when applying specular
|
|
||||||
* anti-aliasing. The default value is set to 0.2. The specified value should be between 0 and 1
|
|
||||||
* and will be clamped if necessary.
|
|
||||||
*/
|
|
||||||
MaterialBuilder& specularAntiAliasingThreshold(float threshold) noexcept;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enables or disables the index of refraction (IoR) change caused by the clear coat layer when
|
|
||||||
* present. When the IoR changes, the base color is darkened. Disabling this feature preserves
|
|
||||||
* the base color as initially specified.
|
|
||||||
*
|
|
||||||
* Enabled by default.
|
|
||||||
*/
|
|
||||||
MaterialBuilder& clearCoatIorChange(bool clearCoatIorChange) noexcept;
|
|
||||||
|
|
||||||
//! Enable / disable flipping of the Y coordinate of UV attributes, enabled by default.
|
|
||||||
MaterialBuilder& flipUV(bool flipUV) noexcept;
|
|
||||||
|
|
||||||
//! Enable / disable multi-bounce ambient occlusion, disabled by default on mobile.
|
|
||||||
MaterialBuilder& multiBounceAmbientOcclusion(bool multiBounceAO) noexcept;
|
|
||||||
|
|
||||||
//! Set the specular ambient occlusion technique. Disabled by default on mobile.
|
|
||||||
MaterialBuilder& specularAmbientOcclusion(SpecularAmbientOcclusion specularAO) noexcept;
|
|
||||||
|
|
||||||
//! Specify the refraction
|
|
||||||
MaterialBuilder& refractionMode(RefractionMode refraction) noexcept;
|
|
||||||
|
|
||||||
//! Specify the refraction type
|
|
||||||
MaterialBuilder& refractionType(RefractionType refractionType) noexcept;
|
|
||||||
|
|
||||||
//! Specifies how transparent objects should be rendered (default is DEFAULT).
|
|
||||||
MaterialBuilder& transparencyMode(TransparencyMode mode) noexcept;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enable / disable custom surface shading. Custom surface shading requires the LIT
|
|
||||||
* shading model. In addition, the following function must be defined in the fragment
|
|
||||||
* block:
|
|
||||||
*
|
|
||||||
* ~~~~~
|
|
||||||
* vec3 surfaceShading(const MaterialInputs materialInputs,
|
|
||||||
* const ShadingData shadingData, const LightData lightData) {
|
|
||||||
*
|
|
||||||
* return vec3(1.0); // Compute surface shading with custom BRDF, etc.
|
|
||||||
* }
|
|
||||||
* ~~~~~
|
|
||||||
*
|
|
||||||
* This function is invoked once per light. Please refer to the materials documentation
|
|
||||||
* for more information about the different parameters.
|
|
||||||
*
|
|
||||||
* @param customSurfaceShading Enables or disables custom surface shading
|
|
||||||
*/
|
|
||||||
MaterialBuilder& customSurfaceShading(bool customSurfaceShading) noexcept;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specifies desktop vs mobile; works in concert with TargetApi to determine the shader models
|
|
||||||
* (used to generate code) and final output representations (spirv and/or text).
|
|
||||||
*/
|
|
||||||
MaterialBuilder& platform(Platform platform) noexcept;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specifies OpenGL, Vulkan, or Metal.
|
|
||||||
* This can be called repeatedly to build for multiple APIs.
|
|
||||||
* Works in concert with Platform to determine the shader models (used to generate code) and
|
|
||||||
* final output representations (spirv and/or text).
|
|
||||||
* If linking against filamat_lite, only `OPENGL` is allowed.
|
|
||||||
*/
|
|
||||||
MaterialBuilder& targetApi(TargetApi targetApi) noexcept;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specifies the level of optimization to apply to the shaders (default is PERFORMANCE).
|
|
||||||
* If linking against filamat_lite, this _must_ be called with Optimization::NONE.
|
|
||||||
*/
|
|
||||||
MaterialBuilder& optimization(Optimization optimization) noexcept;
|
|
||||||
|
|
||||||
// TODO: this is present here for matc's "--print" flag, but ideally does not belong inside
|
|
||||||
// MaterialBuilder.
|
|
||||||
//! If true, will output the generated GLSL shader code to stdout.
|
|
||||||
MaterialBuilder& printShaders(bool printShaders) noexcept;
|
|
||||||
|
|
||||||
//! If true, will include debugging information in generated SPIRV.
|
|
||||||
MaterialBuilder& generateDebugInfo(bool generateDebugInfo) noexcept;
|
|
||||||
|
|
||||||
//! Specifies a list of variants that should be filtered out during code generation.
|
|
||||||
MaterialBuilder& variantFilter(uint8_t variantFilter) noexcept;
|
|
||||||
|
|
||||||
//! Adds a new preprocessor macro definition to the shader code. Can be called repeatedly.
|
|
||||||
MaterialBuilder& shaderDefine(const char* name, const char* value) noexcept;
|
|
||||||
|
|
||||||
//! Add a new fragment shader output variable. Only valid for materials in the POST_PROCESS domain.
|
|
||||||
MaterialBuilder& output(VariableQualifier qualifier, OutputTarget target,
|
|
||||||
OutputType type, const char* name, int location = -1) noexcept;
|
|
||||||
|
|
||||||
MaterialBuilder& enableFramebufferFetch() noexcept;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build the material. If you are using the Filament engine with this library, you should use
|
|
||||||
* the job system provided by Engine.
|
|
||||||
*/
|
|
||||||
Package build(utils::JobSystem& jobSystem) noexcept;
|
|
||||||
|
|
||||||
public:
|
|
||||||
// The methods and types below are for internal use
|
|
||||||
/// @cond never
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a subpass parameter to this material.
|
|
||||||
*/
|
|
||||||
MaterialBuilder& parameter(SubpassType subpassType, SamplerFormat format, ParameterPrecision
|
|
||||||
precision, const char* name) noexcept;
|
|
||||||
MaterialBuilder& parameter(SubpassType subpassType, SamplerFormat format, const char* name)
|
|
||||||
noexcept;
|
|
||||||
MaterialBuilder& parameter(SubpassType subpassType, ParameterPrecision precision,
|
|
||||||
const char* name) noexcept;
|
|
||||||
MaterialBuilder& parameter(SubpassType subpassType, const char* name) noexcept;
|
|
||||||
|
|
||||||
struct Parameter {
|
|
||||||
Parameter() noexcept : parameterType(INVALID) {}
|
|
||||||
|
|
||||||
// Sampler
|
|
||||||
Parameter(const char* paramName, SamplerType t, SamplerFormat f, ParameterPrecision p)
|
|
||||||
: name(paramName), size(1), precision(p), samplerType(t), format(f), parameterType(SAMPLER) { }
|
|
||||||
|
|
||||||
// Uniform
|
|
||||||
Parameter(const char* paramName, UniformType t, size_t typeSize, ParameterPrecision p)
|
|
||||||
: name(paramName), size(typeSize), uniformType(t), precision(p), parameterType(UNIFORM) { }
|
|
||||||
|
|
||||||
// Subpass
|
|
||||||
Parameter(const char* paramName, SubpassType t, SamplerFormat f, ParameterPrecision p)
|
|
||||||
: name(paramName), size(1), precision(p), subpassType(t), format(f), parameterType(SUBPASS) { }
|
|
||||||
|
|
||||||
utils::CString name;
|
|
||||||
size_t size;
|
|
||||||
UniformType uniformType;
|
|
||||||
ParameterPrecision precision;
|
|
||||||
SamplerType samplerType;
|
|
||||||
SubpassType subpassType;
|
|
||||||
SamplerFormat format;
|
|
||||||
enum {
|
|
||||||
INVALID,
|
|
||||||
UNIFORM,
|
|
||||||
SAMPLER,
|
|
||||||
SUBPASS
|
|
||||||
} parameterType;
|
|
||||||
|
|
||||||
bool isSampler() const { return parameterType == SAMPLER; }
|
|
||||||
bool isUniform() const { return parameterType == UNIFORM; }
|
|
||||||
bool isSubpass() const { return parameterType == SUBPASS; }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Output {
|
|
||||||
Output() noexcept = default;
|
|
||||||
Output(const char* outputName, VariableQualifier qualifier, OutputTarget target,
|
|
||||||
OutputType type, int location) noexcept
|
|
||||||
: name(outputName), qualifier(qualifier), target(target), type(type),
|
|
||||||
location(location) { }
|
|
||||||
|
|
||||||
utils::CString name;
|
|
||||||
VariableQualifier qualifier;
|
|
||||||
OutputTarget target;
|
|
||||||
OutputType type;
|
|
||||||
int location;
|
|
||||||
};
|
|
||||||
|
|
||||||
static constexpr size_t MATERIAL_PROPERTIES_COUNT = filament::MATERIAL_PROPERTIES_COUNT;
|
|
||||||
using Property = filament::Property;
|
|
||||||
|
|
||||||
using PropertyList = bool[MATERIAL_PROPERTIES_COUNT];
|
|
||||||
using VariableList = utils::CString[MATERIAL_VARIABLES_COUNT];
|
|
||||||
using OutputList = std::vector<Output>;
|
|
||||||
|
|
||||||
static constexpr size_t MAX_COLOR_OUTPUT = filament::backend::MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT;
|
|
||||||
static constexpr size_t MAX_DEPTH_OUTPUT = 1;
|
|
||||||
static_assert(MAX_COLOR_OUTPUT == 8,
|
|
||||||
"When updating MRT::TARGET_COUNT, manually update post_process_inputs.fs"
|
|
||||||
" and post_process.fs");
|
|
||||||
|
|
||||||
// Preview the first shader generated by the given CodeGenParams.
|
|
||||||
// This is used to run Static Code Analysis before generating a package.
|
|
||||||
const std::string peek(filament::backend::ShaderType type,
|
|
||||||
const CodeGenParams& params, const PropertyList& properties) noexcept;
|
|
||||||
|
|
||||||
// Returns true if any of the parameter samplers is of type samplerExternal
|
|
||||||
bool hasExternalSampler() const noexcept;
|
|
||||||
|
|
||||||
static constexpr size_t MAX_PARAMETERS_COUNT = 48;
|
|
||||||
static constexpr size_t MAX_SUBPASS_COUNT = 1;
|
|
||||||
using ParameterList = Parameter[MAX_PARAMETERS_COUNT];
|
|
||||||
|
|
||||||
// returns the number of parameters declared in this material
|
|
||||||
uint8_t getParameterCount() const noexcept { return mParameterCount; }
|
|
||||||
|
|
||||||
// returns a list of at least getParameterCount() parameters
|
|
||||||
const ParameterList& getParameters() const noexcept { return mParameters; }
|
|
||||||
|
|
||||||
uint8_t getVariantFilter() const { return mVariantFilter; }
|
|
||||||
|
|
||||||
/// @endcond
|
|
||||||
|
|
||||||
private:
|
|
||||||
void prepareToBuild(MaterialInfo& info) noexcept;
|
|
||||||
|
|
||||||
// Return true if the shader is syntactically and semantically valid.
|
|
||||||
// This method finds all the properties defined in the fragment and
|
|
||||||
// vertex shaders of the material.
|
|
||||||
bool findAllProperties() noexcept;
|
|
||||||
// Multiple calls to findProperties accumulate the property sets across fragment
|
|
||||||
// and vertex shaders in mProperties.
|
|
||||||
bool findProperties(filament::backend::ShaderType type,
|
|
||||||
MaterialBuilder::PropertyList& p) noexcept;
|
|
||||||
bool runSemanticAnalysis() noexcept;
|
|
||||||
|
|
||||||
bool checkLiteRequirements() noexcept;
|
|
||||||
|
|
||||||
void writeCommonChunks(ChunkContainer& container, MaterialInfo& info) const noexcept;
|
|
||||||
void writeSurfaceChunks(ChunkContainer& container) const noexcept;
|
|
||||||
|
|
||||||
bool generateShaders(
|
|
||||||
utils::JobSystem& jobSystem,
|
|
||||||
const std::vector<Variant>& variants, ChunkContainer& container,
|
|
||||||
const MaterialInfo& info) const noexcept;
|
|
||||||
|
|
||||||
bool isLit() const noexcept { return mShading != filament::Shading::UNLIT; }
|
|
||||||
|
|
||||||
utils::CString mMaterialName;
|
|
||||||
utils::CString mFileName;
|
|
||||||
|
|
||||||
class ShaderCode {
|
|
||||||
public:
|
|
||||||
void setLineOffset(size_t offset) noexcept { mLineOffset = offset; }
|
|
||||||
void setUnresolved(const utils::CString& code) noexcept {
|
|
||||||
mIncludesResolved = false;
|
|
||||||
mCode = code;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resolve all the #include directives, returns true if successful.
|
|
||||||
bool resolveIncludes(IncludeCallback callback, const utils::CString& fileName) noexcept;
|
|
||||||
|
|
||||||
const utils::CString& getResolved() const noexcept {
|
|
||||||
assert(mIncludesResolved);
|
|
||||||
return mCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t getLineOffset() const noexcept { return mLineOffset; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
utils::CString mCode;
|
|
||||||
size_t mLineOffset = 0;
|
|
||||||
bool mIncludesResolved = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
ShaderCode mMaterialCode;
|
|
||||||
ShaderCode mMaterialVertexCode;
|
|
||||||
|
|
||||||
IncludeCallback mIncludeCallback = nullptr;
|
|
||||||
|
|
||||||
PropertyList mProperties;
|
|
||||||
ParameterList mParameters;
|
|
||||||
VariableList mVariables;
|
|
||||||
OutputList mOutputs;
|
|
||||||
|
|
||||||
ShaderQuality mShaderQuality = ShaderQuality::DEFAULT;
|
|
||||||
BlendingMode mBlendingMode = BlendingMode::OPAQUE;
|
|
||||||
BlendingMode mPostLightingBlendingMode = BlendingMode::TRANSPARENT;
|
|
||||||
CullingMode mCullingMode = CullingMode::BACK;
|
|
||||||
Shading mShading = Shading::LIT;
|
|
||||||
MaterialDomain mMaterialDomain = MaterialDomain::SURFACE;
|
|
||||||
RefractionMode mRefractionMode = RefractionMode::NONE;
|
|
||||||
RefractionType mRefractionType = RefractionType::SOLID;
|
|
||||||
Interpolation mInterpolation = Interpolation::SMOOTH;
|
|
||||||
VertexDomain mVertexDomain = VertexDomain::OBJECT;
|
|
||||||
TransparencyMode mTransparencyMode = TransparencyMode::DEFAULT;
|
|
||||||
|
|
||||||
filament::AttributeBitset mRequiredAttributes;
|
|
||||||
|
|
||||||
float mMaskThreshold = 0.4f;
|
|
||||||
float mSpecularAntiAliasingVariance = 0.15f;
|
|
||||||
float mSpecularAntiAliasingThreshold = 0.2f;
|
|
||||||
|
|
||||||
bool mShadowMultiplier = false;
|
|
||||||
bool mTransparentShadow = false;
|
|
||||||
|
|
||||||
uint8_t mParameterCount = 0;
|
|
||||||
|
|
||||||
bool mDoubleSided = false;
|
|
||||||
bool mDoubleSidedCapability = false;
|
|
||||||
bool mColorWrite = true;
|
|
||||||
bool mDepthTest = true;
|
|
||||||
bool mDepthWrite = true;
|
|
||||||
bool mDepthWriteSet = false;
|
|
||||||
|
|
||||||
bool mSpecularAntiAliasing = false;
|
|
||||||
bool mClearCoatIorChange = true;
|
|
||||||
|
|
||||||
bool mFlipUV = true;
|
|
||||||
|
|
||||||
bool mMultiBounceAO = false;
|
|
||||||
bool mMultiBounceAOSet = false;
|
|
||||||
|
|
||||||
SpecularAmbientOcclusion mSpecularAO = SpecularAmbientOcclusion::NONE;
|
|
||||||
bool mSpecularAOSet = false;
|
|
||||||
|
|
||||||
bool mCustomSurfaceShading = false;
|
|
||||||
|
|
||||||
bool mEnableFramebufferFetch = false;
|
|
||||||
|
|
||||||
PreprocessorDefineList mDefines;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace filamat
|
|
||||||
|
|
||||||
template<> struct utils::EnableBitMaskOperators<filamat::MaterialBuilder::TargetApi>
|
|
||||||
: public std::true_type {};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2017 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef TNT_FILAMAT_PACKAGE_H
|
|
||||||
#define TNT_FILAMAT_PACKAGE_H
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
#include <utils/compiler.h>
|
|
||||||
|
|
||||||
namespace filamat {
|
|
||||||
|
|
||||||
class UTILS_PUBLIC Package {
|
|
||||||
public:
|
|
||||||
Package() = default;
|
|
||||||
|
|
||||||
// Regular constructor
|
|
||||||
explicit Package(size_t size) : mSize(size) {
|
|
||||||
mPayload = new uint8_t[size];
|
|
||||||
}
|
|
||||||
|
|
||||||
Package(const void* src, size_t size) : Package(size) {
|
|
||||||
memcpy(mPayload, src, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Move Constructor
|
|
||||||
Package(Package&& other) noexcept : mPayload(other.mPayload), mSize(other.mSize),
|
|
||||||
mValid(other.mValid) {
|
|
||||||
other.mPayload = nullptr;
|
|
||||||
other.mSize = 0;
|
|
||||||
other.mValid = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Move assignment
|
|
||||||
Package& operator=(Package&& other) noexcept {
|
|
||||||
std::swap(mPayload, other.mPayload);
|
|
||||||
std::swap(mSize, other.mSize);
|
|
||||||
std::swap(mValid, other.mValid);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy assignment operator disallowed.
|
|
||||||
Package& operator=(const Package& other) = delete;
|
|
||||||
|
|
||||||
// Copy constructor disallowed.
|
|
||||||
Package(const Package& other) = delete;
|
|
||||||
|
|
||||||
~Package() {
|
|
||||||
delete[] mPayload;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t* getData() const noexcept {
|
|
||||||
return mPayload;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t getSize() const noexcept {
|
|
||||||
return mSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t* getEnd() const noexcept {
|
|
||||||
return mPayload + mSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setValid(bool valid) noexcept {
|
|
||||||
mValid = valid;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isValid() const noexcept {
|
|
||||||
return mValid;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Package invalidPackage() {
|
|
||||||
Package package(0);
|
|
||||||
package.setValid(false);
|
|
||||||
return package;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
uint8_t* mPayload = nullptr;
|
|
||||||
size_t mSize = 0;
|
|
||||||
bool mValid = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace filamat
|
|
||||||
#endif
|
|
||||||
@@ -1,242 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2021 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef TNT_IBL_PREFILTER_IBLPREFILTER_H
|
|
||||||
#define TNT_IBL_PREFILTER_IBLPREFILTER_H
|
|
||||||
|
|
||||||
#include <utils/compiler.h>
|
|
||||||
#include <utils/Entity.h>
|
|
||||||
|
|
||||||
#include <filament/Texture.h>
|
|
||||||
|
|
||||||
namespace filament {
|
|
||||||
class Engine;
|
|
||||||
class View;
|
|
||||||
class Scene;
|
|
||||||
class Renderer;
|
|
||||||
class Material;
|
|
||||||
class MaterialInstance;
|
|
||||||
class VertexBuffer;
|
|
||||||
class IndexBuffer;
|
|
||||||
class Camera;
|
|
||||||
class Texture;
|
|
||||||
} // namespace filament
|
|
||||||
|
|
||||||
/**
|
|
||||||
* IBLPrefilterContext creates and initializes GPU state common to all environment map filters
|
|
||||||
* supported. Typically, only one instance per filament Engine of this object needs to exist.
|
|
||||||
*
|
|
||||||
* Usage Example:
|
|
||||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
* #include <filament/Engine.h>
|
|
||||||
* using namespace filament;
|
|
||||||
*
|
|
||||||
* Engine* engine = Engine::create();
|
|
||||||
*
|
|
||||||
* IBLPrefilterContext context(engine);
|
|
||||||
* IBLPrefilterContext::SpecularFilter filter(context);
|
|
||||||
* Texture* texture = filter(environment_cubemap);
|
|
||||||
*
|
|
||||||
* IndirectLight* indirectLight = IndirectLight::Builder()
|
|
||||||
* .reflections(texture)
|
|
||||||
* .build(engine);
|
|
||||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
*/
|
|
||||||
class UTILS_PUBLIC IBLPrefilterContext {
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates an IBLPrefilter context.
|
|
||||||
* @param engine filament engine to use
|
|
||||||
*/
|
|
||||||
IBLPrefilterContext(filament::Engine& engine);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destroys all GPU resources created during initialization.
|
|
||||||
*/
|
|
||||||
~IBLPrefilterContext() noexcept;
|
|
||||||
|
|
||||||
// not copyable
|
|
||||||
IBLPrefilterContext(IBLPrefilterContext const&) = delete;
|
|
||||||
IBLPrefilterContext& operator=(IBLPrefilterContext const&) = delete;
|
|
||||||
|
|
||||||
// movable
|
|
||||||
IBLPrefilterContext(IBLPrefilterContext&& rhs) noexcept;
|
|
||||||
IBLPrefilterContext& operator=(IBLPrefilterContext&& rhs);
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* EquirectangularToCubemap is use to convert an equirectangluar image to a cubemap.
|
|
||||||
*/
|
|
||||||
class EquirectangularToCubemap {
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Creates a EquirectangularToCubemap processor.
|
|
||||||
* @param context IBLPrefilterContext to use
|
|
||||||
*/
|
|
||||||
explicit EquirectangularToCubemap(IBLPrefilterContext& context);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destroys all GPU resources created during initialization.
|
|
||||||
*/
|
|
||||||
~EquirectangularToCubemap() noexcept;
|
|
||||||
|
|
||||||
EquirectangularToCubemap(EquirectangularToCubemap const&) = delete;
|
|
||||||
EquirectangularToCubemap& operator=(EquirectangularToCubemap const&) = delete;
|
|
||||||
EquirectangularToCubemap(EquirectangularToCubemap&& rhs) noexcept;
|
|
||||||
EquirectangularToCubemap& operator=(EquirectangularToCubemap&& rhs);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts an equirectangular image to a cubemap.
|
|
||||||
* @param equirectangular Texture to convert to a cubemap.
|
|
||||||
* - Can't be null.
|
|
||||||
* - Must be a 2d texture
|
|
||||||
* - Must have equirectangular geometry, that is width == 2*height.
|
|
||||||
* - Must be allocated with all mip levels.
|
|
||||||
* - Must be SAMPLEABLE
|
|
||||||
* @param outCubemap Output cubemap. If null the texture is automatically created
|
|
||||||
* with default parameters (size of 256 with 5 levels).
|
|
||||||
* - Must be a cubemap
|
|
||||||
* - Must have SAMPLEABLE and COLOR_ATTACHMENT usage bits
|
|
||||||
* @return returns outCubemap
|
|
||||||
*/
|
|
||||||
filament::Texture* operator()(
|
|
||||||
filament::Texture const* equirectangular,
|
|
||||||
filament::Texture* outCubemap = nullptr);
|
|
||||||
|
|
||||||
private:
|
|
||||||
IBLPrefilterContext& mContext;
|
|
||||||
filament::Material* mEquirectMaterial = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SpecularFilter is a GPU based implementation of the specular probe pre-integration filter.
|
|
||||||
* An instance of SpecularFilter is needed per filter configuration. A filter configuration
|
|
||||||
* contains the filter's kernel and sample count.
|
|
||||||
*/
|
|
||||||
class SpecularFilter {
|
|
||||||
public:
|
|
||||||
enum class Kernel : uint8_t {
|
|
||||||
D_GGX, // Trowbridge-reitz distribution
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Filter configuration.
|
|
||||||
*/
|
|
||||||
struct Config {
|
|
||||||
uint16_t sampleCount = 1024u; //!< filter sample count (max 2048)
|
|
||||||
uint8_t levelCount = 5u; //!< number of roughness levels
|
|
||||||
Kernel kernel = Kernel::D_GGX; //!< filter kernel
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Filtering options for the current environment.
|
|
||||||
*/
|
|
||||||
struct Options {
|
|
||||||
float hdrLinear = 1024.0f; //!< no HDR compression up to this value
|
|
||||||
float hdrMax = 16384.0f; //!< HDR compression between hdrLinear and hdrMax
|
|
||||||
float lodOffset = 1.0f; //!< Good values are 1.0 or 2.0. Higher values help with heavily HDR inputs.
|
|
||||||
bool generateMipmap = true; //!< set to false if the environment map already has mipmaps
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a SpecularFilter processor.
|
|
||||||
* @param context IBLPrefilterContext to use
|
|
||||||
* @param config Configuration of the filter
|
|
||||||
*/
|
|
||||||
SpecularFilter(IBLPrefilterContext& context, Config config);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a filter with the default configuration.
|
|
||||||
* @param context IBLPrefilterContext to use
|
|
||||||
*/
|
|
||||||
explicit SpecularFilter(IBLPrefilterContext& context);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destroys all GPU resources created during initialization.
|
|
||||||
*/
|
|
||||||
~SpecularFilter() noexcept;
|
|
||||||
|
|
||||||
SpecularFilter(SpecularFilter const&) = delete;
|
|
||||||
SpecularFilter& operator=(SpecularFilter const&) = delete;
|
|
||||||
SpecularFilter(SpecularFilter&& rhs) noexcept;
|
|
||||||
SpecularFilter& operator=(SpecularFilter&& rhs);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates a prefiltered cubemap.
|
|
||||||
* @param options Options for this environment
|
|
||||||
* @param environmentCubemap Environment cubemap (input). Can't be null.
|
|
||||||
* This cubemap must be SAMPLEABLE and must have all its
|
|
||||||
* levels allocated. If Options.generateMipmap is true,
|
|
||||||
* the mipmap levels will be overwritten, otherwise
|
|
||||||
* it is assumed that all levels are correctly initialized.
|
|
||||||
* @param outReflectionsTexture Output prefiltered texture or, if null, it is
|
|
||||||
* automatically created with some default parameters.
|
|
||||||
* outReflectionsTexture must be a cubemap, it must have
|
|
||||||
* at least COLOR_ATTACHMENT and SAMPLEABLE usages and at
|
|
||||||
* least the same number of levels than requested by Config.
|
|
||||||
* @return returns outReflectionsTexture
|
|
||||||
*/
|
|
||||||
filament::Texture* operator()(Options options,
|
|
||||||
filament::Texture const* environmentCubemap,
|
|
||||||
filament::Texture* outReflectionsTexture = nullptr);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates a prefiltered cubemap.
|
|
||||||
* @param environmentCubemap Environment cubemap (input). Can't be null.
|
|
||||||
* This cubemap must be SAMPLEABLE and must have all its
|
|
||||||
* levels allocated. All mipmap levels will be overwritten.
|
|
||||||
* @param outReflectionsTexture Output prefiltered texture or, if null, it is
|
|
||||||
* automatically created with some default parameters.
|
|
||||||
* outReflectionsTexture must be a cubemap, it must have
|
|
||||||
* at least COLOR_ATTACHMENT and SAMPLEABLE usages and at
|
|
||||||
* least the same number of levels than requested by Config.
|
|
||||||
* @return returns outReflectionsTexture
|
|
||||||
*/
|
|
||||||
filament::Texture* operator()(
|
|
||||||
filament::Texture const* environmentCubemap,
|
|
||||||
filament::Texture* outReflectionsTexture = nullptr);
|
|
||||||
|
|
||||||
// TODO: option for progressive filtering
|
|
||||||
|
|
||||||
// TODO: add a callback for when the processing is done?
|
|
||||||
|
|
||||||
private:
|
|
||||||
filament::Texture* createReflectionsTexture();
|
|
||||||
IBLPrefilterContext& mContext;
|
|
||||||
filament::Material* mKernelMaterial = nullptr;
|
|
||||||
filament::Texture* mKernelTexture = nullptr;
|
|
||||||
uint32_t mSampleCount = 0u;
|
|
||||||
uint8_t mLevelCount = 1u;
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
friend class Filter;
|
|
||||||
filament::Engine& mEngine;
|
|
||||||
filament::Renderer* mRenderer{};
|
|
||||||
filament::Scene* mScene{};
|
|
||||||
filament::VertexBuffer* mVertexBuffer{};
|
|
||||||
filament::IndexBuffer* mIndexBuffer{};
|
|
||||||
filament::Camera* mCamera{};
|
|
||||||
utils::Entity mFullScreenQuadEntity{};
|
|
||||||
utils::Entity mCameraEntity{};
|
|
||||||
filament::View* mView{};
|
|
||||||
filament::Material* mIntegrationMaterial{};
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //TNT_IBL_PREFILTER_IBLPREFILTER_H
|
|
||||||
@@ -54,18 +54,6 @@ public:
|
|||||||
Type type; //!< property type
|
Type type; //!< property type
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PropertyArray {
|
|
||||||
Property const* array;
|
|
||||||
size_t size;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Queries the list of all available properties.
|
|
||||||
*
|
|
||||||
* @return A pair containing a pointer to a Property array and the size of this array.
|
|
||||||
*/
|
|
||||||
PropertyArray getProperties() const noexcept;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Queries whether a property exists
|
* Queries whether a property exists
|
||||||
* @param name The name of the property to query
|
* @param name The name of the property to query
|
||||||
@@ -123,6 +111,24 @@ public:
|
|||||||
bool getProperty(const char* name, math::float4* v) const noexcept;
|
bool getProperty(const char* name, math::float4* v) const noexcept;
|
||||||
/** @}*/
|
/** @}*/
|
||||||
|
|
||||||
|
struct DataSource {
|
||||||
|
void const* data;
|
||||||
|
size_t count;
|
||||||
|
};
|
||||||
|
|
||||||
|
DataSource getDataSource(const char* name) const noexcept;
|
||||||
|
|
||||||
|
struct FrameHistory {
|
||||||
|
using duration_ms = float;
|
||||||
|
duration_ms target{};
|
||||||
|
duration_ms targetWithHeadroom{};
|
||||||
|
duration_ms frameTime{};
|
||||||
|
duration_ms frameTimeDenoised{};
|
||||||
|
float scale = 1.0f;
|
||||||
|
float pid_e = 0.0f;
|
||||||
|
float pid_i = 0.0f;
|
||||||
|
float pid_d = 0.0f;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -35,9 +35,11 @@ class ColorGrading;
|
|||||||
class DebugRegistry;
|
class DebugRegistry;
|
||||||
class Fence;
|
class Fence;
|
||||||
class IndexBuffer;
|
class IndexBuffer;
|
||||||
|
class SkinningBuffer;
|
||||||
class IndirectLight;
|
class IndirectLight;
|
||||||
class Material;
|
class Material;
|
||||||
class MaterialInstance;
|
class MaterialInstance;
|
||||||
|
class MorphTargetBuffer;
|
||||||
class Renderer;
|
class Renderer;
|
||||||
class RenderTarget;
|
class RenderTarget;
|
||||||
class Scene;
|
class Scene;
|
||||||
@@ -419,6 +421,8 @@ public:
|
|||||||
bool destroy(const VertexBuffer* p); //!< Destroys an VertexBuffer object.
|
bool destroy(const VertexBuffer* p); //!< Destroys an VertexBuffer object.
|
||||||
bool destroy(const Fence* p); //!< Destroys a Fence object.
|
bool destroy(const Fence* p); //!< Destroys a Fence object.
|
||||||
bool destroy(const IndexBuffer* p); //!< Destroys an IndexBuffer object.
|
bool destroy(const IndexBuffer* p); //!< Destroys an IndexBuffer object.
|
||||||
|
bool destroy(const SkinningBuffer* p); //!< Destroys a SkinningBuffer object.
|
||||||
|
bool destroy(const MorphTargetBuffer* p); //!< Destroys a MorphTargetBuffer object.
|
||||||
bool destroy(const IndirectLight* p); //!< Destroys an IndirectLight object.
|
bool destroy(const IndirectLight* p); //!< Destroys an IndirectLight object.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -273,6 +273,7 @@ public:
|
|||||||
* Constant bias in depth-resolution units by which shadows are moved away from the
|
* Constant bias in depth-resolution units by which shadows are moved away from the
|
||||||
* light. The default value of 0.5 is used to round depth values up.
|
* light. The default value of 0.5 is used to round depth values up.
|
||||||
* Generally this value shouldn't be changed or at least be small and positive.
|
* Generally this value shouldn't be changed or at least be small and positive.
|
||||||
|
* This is ignored when the View's ShadowType is set to VSM.
|
||||||
*/
|
*/
|
||||||
float polygonOffsetConstant = 0.5f;
|
float polygonOffsetConstant = 0.5f;
|
||||||
|
|
||||||
@@ -281,6 +282,7 @@ public:
|
|||||||
* away from the light. The default value of 2.0 works well with SHADOW_SAMPLING_PCF_LOW.
|
* away from the light. The default value of 2.0 works well with SHADOW_SAMPLING_PCF_LOW.
|
||||||
* Generally this value is between 0.5 and the size in texel of the PCF filter.
|
* Generally this value is between 0.5 and the size in texel of the PCF filter.
|
||||||
* Setting this value correctly is essential for LISPSM shadow-maps.
|
* Setting this value correctly is essential for LISPSM shadow-maps.
|
||||||
|
* This is ignored when the View's ShadowType is set to VSM.
|
||||||
*/
|
*/
|
||||||
float polygonOffsetSlope = 2.0f;
|
float polygonOffsetSlope = 2.0f;
|
||||||
|
|
||||||
@@ -332,6 +334,12 @@ public:
|
|||||||
*/
|
*/
|
||||||
float blurWidth = 0.0f;
|
float blurWidth = 0.0f;
|
||||||
} vsm;
|
} vsm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Light bulb radius used for soft shadows. Currently this is only used when DPCF or PCSS is
|
||||||
|
* enabled. (2cm by default).
|
||||||
|
*/
|
||||||
|
float shadowBulbRadius = 0.02f;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ShadowCascades {
|
struct ShadowCascades {
|
||||||
@@ -558,10 +566,11 @@ public:
|
|||||||
* and are defined by the angle from the center axis to where the falloff begins (i.e.
|
* and are defined by the angle from the center axis to where the falloff begins (i.e.
|
||||||
* cones are defined by their half-angle).
|
* cones are defined by their half-angle).
|
||||||
*
|
*
|
||||||
* @param inner inner cone angle in *radians* between 0 and @f$ \pi/2 @f$
|
* Both inner and outer are silently clamped to a minimum value of 0.5 degrees
|
||||||
*
|
* (~0.00873 radians) to avoid floating-point precision issues during rendering.
|
||||||
* @param outer outer cone angle in *radians* between \p inner and @f$ \pi/2 @f$
|
|
||||||
*
|
*
|
||||||
|
* @param inner inner cone angle in *radians* between 0.00873 and \p outer
|
||||||
|
* @param outer outer cone angle in *radians* between 0.00873 inner and @f$ \pi/2 @f$
|
||||||
* @return This Builder, for chaining calls.
|
* @return This Builder, for chaining calls.
|
||||||
*
|
*
|
||||||
* @note
|
* @note
|
||||||
@@ -812,8 +821,8 @@ public:
|
|||||||
* Dynamically updates a spot light's cone as angles
|
* Dynamically updates a spot light's cone as angles
|
||||||
*
|
*
|
||||||
* @param i Instance of the component obtained from getInstance().
|
* @param i Instance of the component obtained from getInstance().
|
||||||
* @param inner inner cone angle in *radians* between 0 and pi/2
|
* @param inner inner cone angle in *radians* between 0.00873 and outer
|
||||||
* @param outer outer cone angle in *radians* between inner and pi/2
|
* @param outer outer cone angle in *radians* between 0.00873 and pi/2
|
||||||
*
|
*
|
||||||
* @see Builder.spotLightCone()
|
* @see Builder.spotLightCone()
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -193,9 +193,12 @@ public:
|
|||||||
//! Returns the refraction mode used by this material.
|
//! Returns the refraction mode used by this material.
|
||||||
RefractionMode getRefractionMode() const noexcept;
|
RefractionMode getRefractionMode() const noexcept;
|
||||||
|
|
||||||
// Return the refraction type used by this material.
|
//! Return the refraction type used by this material.
|
||||||
RefractionType getRefractionType() const noexcept;
|
RefractionType getRefractionType() const noexcept;
|
||||||
|
|
||||||
|
//! Returns the reflection mode used by this material.
|
||||||
|
ReflectionMode getReflectionMode() const noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the number of parameters declared by this material.
|
* Returns the number of parameters declared by this material.
|
||||||
* The returned value can be 0.
|
* The returned value can be 0.
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ enum UTILS_PUBLIC ChunkType : uint64_t {
|
|||||||
MaterialDomain = charTo64bitNum("MAT_DOMN"),
|
MaterialDomain = charTo64bitNum("MAT_DOMN"),
|
||||||
MaterialRefraction = charTo64bitNum("MAT_REFM"),
|
MaterialRefraction = charTo64bitNum("MAT_REFM"),
|
||||||
MaterialRefractionType = charTo64bitNum("MAT_REFT"),
|
MaterialRefractionType = charTo64bitNum("MAT_REFT"),
|
||||||
|
MaterialReflectionMode = charTo64bitNum("MAT_REFL"),
|
||||||
|
|
||||||
MaterialRequiredAttributes = charTo64bitNum("MAT_REQA"),
|
MaterialRequiredAttributes = charTo64bitNum("MAT_REQA"),
|
||||||
MaterialDepthWriteSet = charTo64bitNum("MAT_DEWS"),
|
MaterialDepthWriteSet = charTo64bitNum("MAT_DEWS"),
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
namespace filament {
|
namespace filament {
|
||||||
|
|
||||||
// update this when a new version of filament wouldn't work with older materials
|
// update this when a new version of filament wouldn't work with older materials
|
||||||
static constexpr size_t MATERIAL_VERSION = 12;
|
static constexpr size_t MATERIAL_VERSION = 17;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Supported shading models
|
* Supported shading models
|
||||||
@@ -136,20 +136,10 @@ enum VertexAttribute : uint8_t {
|
|||||||
CUSTOM6 = 14,
|
CUSTOM6 = 14,
|
||||||
CUSTOM7 = 15,
|
CUSTOM7 = 15,
|
||||||
|
|
||||||
// Aliases for vertex morphing.
|
|
||||||
MORPH_POSITION_0 = CUSTOM0,
|
|
||||||
MORPH_POSITION_1 = CUSTOM1,
|
|
||||||
MORPH_POSITION_2 = CUSTOM2,
|
|
||||||
MORPH_POSITION_3 = CUSTOM3,
|
|
||||||
MORPH_TANGENTS_0 = CUSTOM4,
|
|
||||||
MORPH_TANGENTS_1 = CUSTOM5,
|
|
||||||
MORPH_TANGENTS_2 = CUSTOM6,
|
|
||||||
MORPH_TANGENTS_3 = CUSTOM7,
|
|
||||||
|
|
||||||
// this is limited by driver::MAX_VERTEX_ATTRIBUTE_COUNT
|
// this is limited by driver::MAX_VERTEX_ATTRIBUTE_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr size_t MAX_MORPH_TARGETS = 4;
|
static constexpr size_t MAX_MORPH_TARGETS = 128; // this is limited by filament::CONFIG_MAX_MORPH_TARGET_COUNT
|
||||||
static constexpr size_t MAX_CUSTOM_ATTRIBUTES = 8;
|
static constexpr size_t MAX_CUSTOM_ATTRIBUTES = 8;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -186,6 +176,14 @@ enum class RefractionType : uint8_t {
|
|||||||
THIN = 1, //!< refraction through thin objects (e.g. window)
|
THIN = 1, //!< refraction through thin objects (e.g. window)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reflection mode
|
||||||
|
*/
|
||||||
|
enum class ReflectionMode : uint8_t {
|
||||||
|
DEFAULT = 0, //! reflections sample from the scene's IBL only
|
||||||
|
SCREEN_SPACE = 1, //! reflections sample from screen space, and fallback to the scene's IBL
|
||||||
|
};
|
||||||
|
|
||||||
// can't really use std::underlying_type<AttributeIndex>::type because the driver takes a uint32_t
|
// can't really use std::underlying_type<AttributeIndex>::type because the driver takes a uint32_t
|
||||||
using AttributeBitset = utils::bitset32;
|
using AttributeBitset = utils::bitset32;
|
||||||
|
|
||||||
|
|||||||
119
ios/include/filament/MorphTargetBuffer.h
Normal file
119
ios/include/filament/MorphTargetBuffer.h
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TNT_FILAMENT_MORPHTARGETBUFFER_H
|
||||||
|
#define TNT_FILAMENT_MORPHTARGETBUFFER_H
|
||||||
|
|
||||||
|
#include <filament/FilamentAPI.h>
|
||||||
|
|
||||||
|
#include <filament/Engine.h>
|
||||||
|
|
||||||
|
#include <math/mathfwd.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace filament {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MorphTargetBuffer is used to hold morphing data (positions and tangents).
|
||||||
|
*/
|
||||||
|
class UTILS_PUBLIC MorphTargetBuffer : public FilamentAPI {
|
||||||
|
struct BuilderDetails;
|
||||||
|
|
||||||
|
public:
|
||||||
|
class Builder : public BuilderBase<BuilderDetails> {
|
||||||
|
friend struct BuilderDetails;
|
||||||
|
public:
|
||||||
|
Builder() noexcept;
|
||||||
|
Builder(Builder const& rhs) noexcept;
|
||||||
|
Builder(Builder&& rhs) noexcept;
|
||||||
|
~Builder() noexcept;
|
||||||
|
Builder& operator=(Builder const& rhs) noexcept;
|
||||||
|
Builder& operator=(Builder&& rhs) noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Size of the morph targets in vertex counts.
|
||||||
|
* @param vertexCount Number of vertex counts the morph targets can hold.
|
||||||
|
* @return A reference to this Builder for chaining calls.
|
||||||
|
*/
|
||||||
|
Builder& vertexCount(size_t vertexCount) noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Size of the morph targets in targets.
|
||||||
|
* @param count Number of targets the morph targets can hold.
|
||||||
|
* @return A reference to this Builder for chaining calls.
|
||||||
|
*/
|
||||||
|
Builder& count(size_t count) noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the MorphTargetBuffer object and returns a pointer to it.
|
||||||
|
*
|
||||||
|
* @param engine Reference to the filament::Engine to associate this MorphTargetBuffer with.
|
||||||
|
*
|
||||||
|
* @return pointer to the newly created object or nullptr if exceptions are disabled and
|
||||||
|
* an error occurred.
|
||||||
|
*
|
||||||
|
* @exception utils::PostConditionPanic if a runtime error occurred, such as running out of
|
||||||
|
* memory or other resources.
|
||||||
|
* @exception utils::PreConditionPanic if a parameter to a builder function was invalid.
|
||||||
|
*/
|
||||||
|
MorphTargetBuffer* build(Engine& engine);
|
||||||
|
private:
|
||||||
|
friend class FMorphTargetBuffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the position of morph target at the index.
|
||||||
|
* @param engine Reference to the filament::Engine associated with this MorphTargetBuffer.
|
||||||
|
* @param targetIndex the index of morph target to be updated.
|
||||||
|
* @param weights pointer to at least count positions
|
||||||
|
* @param count number of position elements in positions
|
||||||
|
*/
|
||||||
|
void setPositionsAt(Engine& engine, size_t targetIndex, math::float3 const* positions, size_t count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the position of morph target at the index.
|
||||||
|
* @param engine Reference to the filament::Engine associated with this MorphTargetBuffer.
|
||||||
|
* @param targetIndex the index of morph target to be updated.
|
||||||
|
* @param weights pointer to at least count positions
|
||||||
|
* @param count number of position elements in positions
|
||||||
|
*/
|
||||||
|
void setPositionsAt(Engine& engine, size_t targetIndex, math::float4 const* positions, size_t count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the position of morph target at the index.
|
||||||
|
* @param engine Reference to the filament::Engine associated with this MorphTargetBuffer.
|
||||||
|
* @param targetIndex the index of morph target to be updated.
|
||||||
|
* @param tangents pointer to at least count tangents
|
||||||
|
* @param count number of tangent elements in tangents
|
||||||
|
*/
|
||||||
|
void setTangentsAt(Engine& engine, size_t targetIndex, math::short4 const* tangents, size_t count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the vertex count of this MorphTargetBuffer.
|
||||||
|
* @return The number of vertices the MorphTargetBuffer holds.
|
||||||
|
*/
|
||||||
|
size_t getVertexCount() const noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the target count of this MorphTargetBuffer.
|
||||||
|
* @return The number of targets the MorphTargetBuffer holds.
|
||||||
|
*/
|
||||||
|
size_t getCount() const noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace filament
|
||||||
|
|
||||||
|
#endif //TNT_FILAMENT_MORPHTARGETBUFFER_H
|
||||||
@@ -284,6 +284,28 @@ struct AmbientOcclusionOptions {
|
|||||||
} ssct;
|
} ssct;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Options for Temporal Multi-Sample Anti-aliasing (MSAA)
|
||||||
|
* @see setMultiSampleAntiAliasingOptions()
|
||||||
|
*/
|
||||||
|
struct MultiSampleAntiAliasingOptions {
|
||||||
|
bool enabled = false; //!< enables or disables msaa
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sampleCount number of samples to use for multi-sampled anti-aliasing.\n
|
||||||
|
* 0: treated as 1
|
||||||
|
* 1: no anti-aliasing
|
||||||
|
* n: sample count. Effective sample could be different depending on the
|
||||||
|
* GPU capabilities.
|
||||||
|
*/
|
||||||
|
uint8_t sampleCount = 4;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* custom resolve improves quality for HDR scenes, but may impact performance.
|
||||||
|
*/
|
||||||
|
bool customResolve = false;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Options for Temporal Anti-aliasing (TAA)
|
* Options for Temporal Anti-aliasing (TAA)
|
||||||
* @see setTemporalAntiAliasingOptions()
|
* @see setTemporalAntiAliasingOptions()
|
||||||
@@ -294,6 +316,18 @@ struct TemporalAntiAliasingOptions {
|
|||||||
bool enabled = false; //!< enables or disables temporal anti-aliasing
|
bool enabled = false; //!< enables or disables temporal anti-aliasing
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Options for Screen-space Reflections.
|
||||||
|
* @see setScreenSpaceReflectionsOptions()
|
||||||
|
*/
|
||||||
|
struct ScreenSpaceReflectionsOptions {
|
||||||
|
float thickness = 0.5f; //!< ray thickness, in world units
|
||||||
|
float bias = 0.01f; //!< bias, in world units, to prevent self-intersections
|
||||||
|
float maxDistance = 3.0f; //!< maximum distance, in world units, to raycast
|
||||||
|
float stride = 1.0f; //!< stride, in texels, for samples along the ray.
|
||||||
|
bool enabled = false;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of available post-processing anti-aliasing techniques.
|
* List of available post-processing anti-aliasing techniques.
|
||||||
* @see setAntiAliasing, getAntiAliasing, setSampleCount
|
* @see setAntiAliasing, getAntiAliasing, setSampleCount
|
||||||
@@ -317,7 +351,9 @@ enum class Dithering : uint8_t {
|
|||||||
*/
|
*/
|
||||||
enum class ShadowType : uint8_t {
|
enum class ShadowType : uint8_t {
|
||||||
PCF, //!< percentage-closer filtered shadows (default)
|
PCF, //!< percentage-closer filtered shadows (default)
|
||||||
VSM //!< variance shadows
|
VSM, //!< variance shadows
|
||||||
|
DPCF, //!< PCF with contact hardening simulation
|
||||||
|
PCSS //!< PCF with soft shadows and contact hardening
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -339,13 +375,6 @@ struct VsmShadowOptions {
|
|||||||
*/
|
*/
|
||||||
bool mipmapping = false;
|
bool mipmapping = false;
|
||||||
|
|
||||||
/**
|
|
||||||
* EVSM exponent.
|
|
||||||
* The maximum value permissible is 5.54 for a shadow map in fp16, or 42.0 for a
|
|
||||||
* shadow map in fp32. Currently the shadow map bit depth is always fp16.
|
|
||||||
*/
|
|
||||||
float exponent = 5.54f;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* VSM minimum variance scale, must be positive.
|
* VSM minimum variance scale, must be positive.
|
||||||
*/
|
*/
|
||||||
@@ -357,6 +386,27 @@ struct VsmShadowOptions {
|
|||||||
float lightBleedReduction = 0.15f;
|
float lightBleedReduction = 0.15f;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* View-level options for DPCF and PCSS Shadowing.
|
||||||
|
* @see setSoftShadowOptions()
|
||||||
|
* @warning This API is still experimental and subject to change.
|
||||||
|
*/
|
||||||
|
struct SoftShadowOptions {
|
||||||
|
/**
|
||||||
|
* Globally scales the penumbra of all DPCF and PCSS shadows
|
||||||
|
* Acceptable values are greater than 0
|
||||||
|
*/
|
||||||
|
float penumbraScale = 1.0f;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Globally scales the computed penumbra ratio of all DPCF and PCSS shadows.
|
||||||
|
* This effectively controls the strength of contact hardening effect and is useful for
|
||||||
|
* artistic purposes. Higher values make the shadows become softer faster.
|
||||||
|
* Acceptable values are equal to or greater than 1.
|
||||||
|
*/
|
||||||
|
float penumbraRatioScale = 1.0f;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace filament
|
} // namespace filament
|
||||||
|
|
||||||
#endif //TNT_FILAMENT_OPTIONS_H
|
#endif //TNT_FILAMENT_OPTIONS_H
|
||||||
|
|||||||
@@ -37,6 +37,12 @@ class Texture;
|
|||||||
* An offscreen render target that can be associated with a View and contains
|
* An offscreen render target that can be associated with a View and contains
|
||||||
* weak references to a set of attached Texture objects.
|
* weak references to a set of attached Texture objects.
|
||||||
*
|
*
|
||||||
|
* RenderTarget is intended to be used with the View's post-processing disabled for the most part.
|
||||||
|
* especially when a DEPTH attachment is also used (see Builder::texture()).
|
||||||
|
*
|
||||||
|
* Custom RenderTarget are ultimately intended to render into textures that might be used during
|
||||||
|
* the main render pass.
|
||||||
|
*
|
||||||
* Clients are responsible for the lifetime of all associated Texture attachments.
|
* Clients are responsible for the lifetime of all associated Texture attachments.
|
||||||
*
|
*
|
||||||
* @see View
|
* @see View
|
||||||
@@ -87,6 +93,14 @@ public:
|
|||||||
*
|
*
|
||||||
* All RenderTargets must have a non-null COLOR attachment.
|
* All RenderTargets must have a non-null COLOR attachment.
|
||||||
*
|
*
|
||||||
|
* When using a DEPTH attachment, it is important to always disable post-processing
|
||||||
|
* in the View. Failing to do so will cause the DEPTH attachment to be ignored in most
|
||||||
|
* cases.
|
||||||
|
*
|
||||||
|
* When the intention is to keep the content of the DEPTH attachment after rendering,
|
||||||
|
* Usage::SAMPLEABLE must be set on the DEPTH attachment, otherwise the content of the
|
||||||
|
* DEPTH buffer may be discarded.
|
||||||
|
*
|
||||||
* @param attachment The attachment point of the texture.
|
* @param attachment The attachment point of the texture.
|
||||||
* @param texture The associated texture object.
|
* @param texture The associated texture object.
|
||||||
* @return A reference to this Builder for chaining calls.
|
* @return A reference to this Builder for chaining calls.
|
||||||
|
|||||||
@@ -41,9 +41,11 @@ class Engine;
|
|||||||
class IndexBuffer;
|
class IndexBuffer;
|
||||||
class Material;
|
class Material;
|
||||||
class MaterialInstance;
|
class MaterialInstance;
|
||||||
|
class MorphTargetBuffer;
|
||||||
class Renderer;
|
class Renderer;
|
||||||
class SkinningBuffer;
|
class SkinningBuffer;
|
||||||
class VertexBuffer;
|
class VertexBuffer;
|
||||||
|
class Texture;
|
||||||
|
|
||||||
class FEngine;
|
class FEngine;
|
||||||
class FRenderPrimitive;
|
class FRenderPrimitive;
|
||||||
@@ -105,8 +107,8 @@ public:
|
|||||||
* Clients can specify bones either using this quat-vec3 pair, or by using 4x4 matrices.
|
* Clients can specify bones either using this quat-vec3 pair, or by using 4x4 matrices.
|
||||||
*/
|
*/
|
||||||
struct Bone {
|
struct Bone {
|
||||||
math::quatf unitQuaternion = { 1, 0, 0, 0 };
|
math::quatf unitQuaternion = { 1.f, 0.f, 0.f, 0.f };
|
||||||
math::float3 translation = { 0, 0, 0 };
|
math::float3 translation = { 0.f, 0.f, 0.f };
|
||||||
float reserved = 0;
|
float reserved = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -300,9 +302,6 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Controls if the renderable has vertex morphing targets, false by default.
|
* Controls if the renderable has vertex morphing targets, false by default.
|
||||||
*
|
*
|
||||||
* This is required to enable GPU morphing for up to 4 attributes. The attached VertexBuffer
|
|
||||||
* must provide data in the appropriate VertexAttribute slots (\c MORPH_POSITION_0 etc).
|
|
||||||
*
|
|
||||||
* See also RenderableManager::setMorphWeights(), which can be called on a per-frame basis
|
* See also RenderableManager::setMorphWeights(), which can be called on a per-frame basis
|
||||||
* to advance the animation.
|
* to advance the animation.
|
||||||
*/
|
*/
|
||||||
@@ -456,12 +455,16 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Updates the vertex morphing weights on a renderable, all zeroes by default.
|
* Updates the vertex morphing weights on a renderable, all zeroes by default.
|
||||||
*
|
*
|
||||||
* This is specified using a 4-tuple, one float per morph target. If the renderable has fewer
|
|
||||||
* than 4 morph targets, then clients should fill the unused components with zeroes.
|
|
||||||
*
|
|
||||||
* The renderable must be built with morphing enabled, see Builder::morphing().
|
* The renderable must be built with morphing enabled, see Builder::morphing().
|
||||||
*/
|
*/
|
||||||
void setMorphWeights(Instance instance, math::float4 const& weights) noexcept;
|
void setMorphWeights(Instance instance, float const* weights, size_t count) noexcept;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Associates a MorphTargetBuffer to the given primitive.
|
||||||
|
*/
|
||||||
|
void setMorphTargetBufferAt(Instance instance,
|
||||||
|
size_t primitiveIndex, MorphTargetBuffer* morphTargetBuffer) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the bounding box used for frustum culling.
|
* Gets the bounding box used for frustum culling.
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ public:
|
|||||||
* headRoomRatio: additional headroom for the GPU as a ratio of the targetFrameTime.
|
* headRoomRatio: additional headroom for the GPU as a ratio of the targetFrameTime.
|
||||||
* Useful for taking into account constant costs like post-processing or
|
* Useful for taking into account constant costs like post-processing or
|
||||||
* GPU drivers on different platforms.
|
* GPU drivers on different platforms.
|
||||||
* history: History size. higher values, tend to filter more (clamped to 30)
|
* history: History size. higher values, tend to filter more (clamped to 31)
|
||||||
* scaleRate: rate at which the gpu load is adjusted to reach the target frame rate
|
* scaleRate: rate at which the gpu load is adjusted to reach the target frame rate
|
||||||
* This value can be computed as 1 / N, where N is the number of frames
|
* This value can be computed as 1 / N, where N is the number of frames
|
||||||
* needed to reach 64% of the target scale factor.
|
* needed to reach 64% of the target scale factor.
|
||||||
@@ -111,8 +111,8 @@ public:
|
|||||||
*/
|
*/
|
||||||
struct FrameRateOptions {
|
struct FrameRateOptions {
|
||||||
float headRoomRatio = 0.0f; //!< additional headroom for the GPU
|
float headRoomRatio = 0.0f; //!< additional headroom for the GPU
|
||||||
float scaleRate = 0.125f; //!< rate at which the system reacts to load changes
|
float scaleRate = 1.0f / 8.0f; //!< rate at which the system reacts to load changes
|
||||||
uint8_t history = 3; //!< history size
|
uint8_t history = 15; //!< history size
|
||||||
uint8_t interval = 1; //!< desired frame interval in unit of 1.0 / DisplayInfo::refreshRate
|
uint8_t interval = 1; //!< desired frame interval in unit of 1.0 / DisplayInfo::refreshRate
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -252,7 +252,7 @@ public:
|
|||||||
*
|
*
|
||||||
* render() generates commands for each of the following stages:
|
* render() generates commands for each of the following stages:
|
||||||
*
|
*
|
||||||
* 1. Shadow map pass, if needed (currently only a single shadow map is supported).
|
* 1. Shadow map passes, if needed.
|
||||||
* 2. Depth pre-pass.
|
* 2. Depth pre-pass.
|
||||||
* 3. Color pass.
|
* 3. Color pass.
|
||||||
* 4. Post-processing pass.
|
* 4. Post-processing pass.
|
||||||
@@ -359,7 +359,8 @@ public:
|
|||||||
* O------------+-------+
|
* O------------+-------+
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* Typically readPixels() will be called after render() and before endFrame().
|
* readPixels() must be called within a frame, meaning after beginFrame() and before endFrame().
|
||||||
|
* Typically, readPixels() will be called after render().
|
||||||
*
|
*
|
||||||
* After issuing this method, the callback associated with `buffer` will be invoked on the
|
* After issuing this method, the callback associated with `buffer` will be invoked on the
|
||||||
* main thread, indicating that the read-back has completed. Typically, this will happen
|
* main thread, indicating that the read-back has completed. Typically, this will happen
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
#include <backend/DriverEnums.h>
|
#include <backend/DriverEnums.h>
|
||||||
|
|
||||||
#include <backend/PixelBufferDescriptor.h>
|
#include <backend/PixelBufferDescriptor.h>
|
||||||
|
#include <backend/CallbackHandler.h>
|
||||||
|
|
||||||
#include <utils/compiler.h>
|
#include <utils/compiler.h>
|
||||||
|
|
||||||
@@ -199,6 +200,18 @@ public:
|
|||||||
*/
|
*/
|
||||||
void setAcquiredImage(void* image, Callback callback, void* userdata) noexcept;
|
void setAcquiredImage(void* image, Callback callback, void* userdata) noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see setAcquiredImage(void*, Callback, void*)
|
||||||
|
*
|
||||||
|
* @param image Pointer to AHardwareBuffer, casted to void* since this is a public header.
|
||||||
|
* @param handler Handler to dispatch the AcquiredImage or nullptr for the default handler.
|
||||||
|
* @param callback This is triggered by Filament when it wishes to release the image.
|
||||||
|
* It callback tales two arguments: the AHardwareBuffer and the userdata.
|
||||||
|
* @param userdata Optional closure data. Filament will pass this into the callback when it
|
||||||
|
* releases the image.
|
||||||
|
*/
|
||||||
|
void setAcquiredImage(void* image, backend::CallbackHandler* handler, Callback callback, void* userdata) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the size of the incoming stream. Whether this value is used is
|
* Updates the size of the incoming stream. Whether this value is used is
|
||||||
* stream dependent. On Android, it must be set when using
|
* stream dependent. On Android, it must be set when using
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ struct UTILS_PUBLIC LinearToneMapper final : public ToneMapper {
|
|||||||
LinearToneMapper() noexcept;
|
LinearToneMapper() noexcept;
|
||||||
~LinearToneMapper() noexcept final;
|
~LinearToneMapper() noexcept final;
|
||||||
|
|
||||||
math::float3 operator()(math::float3 c) const noexcept;
|
math::float3 operator()(math::float3 c) const noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -86,7 +86,7 @@ struct UTILS_PUBLIC ACESToneMapper final : public ToneMapper {
|
|||||||
ACESToneMapper() noexcept;
|
ACESToneMapper() noexcept;
|
||||||
~ACESToneMapper() noexcept final;
|
~ACESToneMapper() noexcept final;
|
||||||
|
|
||||||
math::float3 operator()(math::float3 c) const noexcept;
|
math::float3 operator()(math::float3 c) const noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -99,7 +99,7 @@ struct UTILS_PUBLIC ACESLegacyToneMapper final : public ToneMapper {
|
|||||||
ACESLegacyToneMapper() noexcept;
|
ACESLegacyToneMapper() noexcept;
|
||||||
~ACESLegacyToneMapper() noexcept final;
|
~ACESLegacyToneMapper() noexcept final;
|
||||||
|
|
||||||
math::float3 operator()(math::float3 c) const noexcept;
|
math::float3 operator()(math::float3 c) const noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -112,7 +112,7 @@ struct UTILS_PUBLIC FilmicToneMapper final : public ToneMapper {
|
|||||||
FilmicToneMapper() noexcept;
|
FilmicToneMapper() noexcept;
|
||||||
~FilmicToneMapper() noexcept final;
|
~FilmicToneMapper() noexcept final;
|
||||||
|
|
||||||
math::float3 operator()(math::float3 x) const noexcept;
|
math::float3 operator()(math::float3 x) const noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -123,8 +123,6 @@ struct UTILS_PUBLIC FilmicToneMapper final : public ToneMapper {
|
|||||||
*
|
*
|
||||||
* The tone mapping curve is defined by 5 parameters:
|
* The tone mapping curve is defined by 5 parameters:
|
||||||
* - contrast: controls the contrast of the curve
|
* - contrast: controls the contrast of the curve
|
||||||
* - shoulder: controls the shoulder of the curve, i.e. how quickly scene
|
|
||||||
* referred values map to output white
|
|
||||||
* - midGrayIn: sets the input middle gray
|
* - midGrayIn: sets the input middle gray
|
||||||
* - midGrayOut: sets the output middle gray
|
* - midGrayOut: sets the output middle gray
|
||||||
* - hdrMax: defines the maximum input value that will be mapped to
|
* - hdrMax: defines the maximum input value that will be mapped to
|
||||||
@@ -138,18 +136,15 @@ struct UTILS_PUBLIC GenericToneMapper final : public ToneMapper {
|
|||||||
*
|
*
|
||||||
* @param contrast: controls the contrast of the curve, must be > 0.0, values
|
* @param contrast: controls the contrast of the curve, must be > 0.0, values
|
||||||
* in the range 0.5..2.0 are recommended.
|
* in the range 0.5..2.0 are recommended.
|
||||||
* @param shoulder: controls the shoulder of the curve, i.e. how quickly scene
|
|
||||||
* referred values map to output white, between 0.0 and 1.0.
|
|
||||||
* @param midGrayIn: sets the input middle gray, between 0.0 and 1.0.
|
* @param midGrayIn: sets the input middle gray, between 0.0 and 1.0.
|
||||||
* @param midGrayOut: sets the output middle gray, between 0.0 and 1.0.
|
* @param midGrayOut: sets the output middle gray, between 0.0 and 1.0.
|
||||||
* @param hdrMax: defines the maximum input value that will be mapped to
|
* @param hdrMax: defines the maximum input value that will be mapped to
|
||||||
* output white. Must be >= 1.0.
|
* output white. Must be >= 1.0.
|
||||||
*/
|
*/
|
||||||
GenericToneMapper(
|
explicit GenericToneMapper(
|
||||||
float contrast = 1.585f,
|
float contrast = 1.55f,
|
||||||
float shoulder = 0.5f,
|
|
||||||
float midGrayIn = 0.18f,
|
float midGrayIn = 0.18f,
|
||||||
float midGrayOut = 0.268f,
|
float midGrayOut = 0.215f,
|
||||||
float hdrMax = 10.0f
|
float hdrMax = 10.0f
|
||||||
) noexcept;
|
) noexcept;
|
||||||
~GenericToneMapper() noexcept final;
|
~GenericToneMapper() noexcept final;
|
||||||
@@ -157,9 +152,9 @@ struct UTILS_PUBLIC GenericToneMapper final : public ToneMapper {
|
|||||||
GenericToneMapper(GenericToneMapper const&) = delete;
|
GenericToneMapper(GenericToneMapper const&) = delete;
|
||||||
GenericToneMapper& operator=(GenericToneMapper const&) = delete;
|
GenericToneMapper& operator=(GenericToneMapper const&) = delete;
|
||||||
GenericToneMapper(GenericToneMapper&& rhs) noexcept;
|
GenericToneMapper(GenericToneMapper&& rhs) noexcept;
|
||||||
GenericToneMapper& operator=(GenericToneMapper& rhs) noexcept;
|
GenericToneMapper& operator=(GenericToneMapper&& rhs) noexcept;
|
||||||
|
|
||||||
math::float3 operator()(math::float3 x) const noexcept;
|
math::float3 operator()(math::float3 x) const noexcept override;
|
||||||
|
|
||||||
/** Returns the contrast of the curve as a strictly positive value. */
|
/** Returns the contrast of the curve as a strictly positive value. */
|
||||||
float getContrast() const noexcept;
|
float getContrast() const noexcept;
|
||||||
@@ -179,9 +174,6 @@ struct UTILS_PUBLIC GenericToneMapper final : public ToneMapper {
|
|||||||
/** Sets the contrast of the curve, must be > 0.0, values in the range 0.5..2.0 are recommended. */
|
/** Sets the contrast of the curve, must be > 0.0, values in the range 0.5..2.0 are recommended. */
|
||||||
void setContrast(float contrast) noexcept;
|
void setContrast(float contrast) noexcept;
|
||||||
|
|
||||||
/** Sets how quickly scene referred values map to output white, between 0.0 and 1.0. */
|
|
||||||
void setShoulder(float shoulder) noexcept;
|
|
||||||
|
|
||||||
/** Sets the input middle gray, between 0.0 and 1.0. */
|
/** Sets the input middle gray, between 0.0 and 1.0. */
|
||||||
void setMidGrayIn(float midGrayIn) noexcept;
|
void setMidGrayIn(float midGrayIn) noexcept;
|
||||||
|
|
||||||
@@ -225,9 +217,9 @@ private:
|
|||||||
*/
|
*/
|
||||||
struct UTILS_PUBLIC DisplayRangeToneMapper final : public ToneMapper {
|
struct UTILS_PUBLIC DisplayRangeToneMapper final : public ToneMapper {
|
||||||
DisplayRangeToneMapper() noexcept;
|
DisplayRangeToneMapper() noexcept;
|
||||||
~DisplayRangeToneMapper() noexcept;
|
~DisplayRangeToneMapper() noexcept override;
|
||||||
|
|
||||||
math::float3 operator()(math::float3 c) const noexcept;
|
math::float3 operator()(math::float3 c) const noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace filament
|
} // namespace filament
|
||||||
|
|||||||
@@ -32,6 +32,10 @@
|
|||||||
|
|
||||||
namespace filament {
|
namespace filament {
|
||||||
|
|
||||||
|
namespace backend {
|
||||||
|
class CallbackHandler;
|
||||||
|
} // namespace backend
|
||||||
|
|
||||||
class Camera;
|
class Camera;
|
||||||
class ColorGrading;
|
class ColorGrading;
|
||||||
class MaterialInstance;
|
class MaterialInstance;
|
||||||
@@ -76,7 +80,10 @@ public:
|
|||||||
using RenderQuality = RenderQuality;
|
using RenderQuality = RenderQuality;
|
||||||
using AmbientOcclusionOptions = AmbientOcclusionOptions;
|
using AmbientOcclusionOptions = AmbientOcclusionOptions;
|
||||||
using TemporalAntiAliasingOptions = TemporalAntiAliasingOptions;
|
using TemporalAntiAliasingOptions = TemporalAntiAliasingOptions;
|
||||||
|
using MultiSampleAntiAliasingOptions = MultiSampleAntiAliasingOptions;
|
||||||
using VsmShadowOptions = VsmShadowOptions;
|
using VsmShadowOptions = VsmShadowOptions;
|
||||||
|
using SoftShadowOptions = SoftShadowOptions;
|
||||||
|
using ScreenSpaceReflectionsOptions = ScreenSpaceReflectionsOptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the View's name. Only useful for debugging.
|
* Sets the View's name. Only useful for debugging.
|
||||||
@@ -275,7 +282,9 @@ public:
|
|||||||
* cost. See setAntialiasing.
|
* cost. See setAntialiasing.
|
||||||
*
|
*
|
||||||
* @see setAntialiasing
|
* @see setAntialiasing
|
||||||
|
* @deprecated use setMultiSampleAntiAliasingOptions instead
|
||||||
*/
|
*/
|
||||||
|
UTILS_DEPRECATED
|
||||||
void setSampleCount(uint8_t count = 1) noexcept;
|
void setSampleCount(uint8_t count = 1) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -283,7 +292,9 @@ public:
|
|||||||
* A value of 0 or 1 means MSAA is disabled.
|
* A value of 0 or 1 means MSAA is disabled.
|
||||||
*
|
*
|
||||||
* @return value set by setSampleCount().
|
* @return value set by setSampleCount().
|
||||||
|
* @deprecated use getMultiSampleAntiAliasingOptions instead
|
||||||
*/
|
*/
|
||||||
|
UTILS_DEPRECATED
|
||||||
uint8_t getSampleCount() const noexcept;
|
uint8_t getSampleCount() const noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -320,6 +331,34 @@ public:
|
|||||||
*/
|
*/
|
||||||
TemporalAntiAliasingOptions const& getTemporalAntiAliasingOptions() const noexcept;
|
TemporalAntiAliasingOptions const& getTemporalAntiAliasingOptions() const noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables or disable screen-space reflections. Disabled by default.
|
||||||
|
*
|
||||||
|
* @param options screen-space reflections options
|
||||||
|
*/
|
||||||
|
void setScreenSpaceReflectionsOptions(ScreenSpaceReflectionsOptions options) noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns screen-space reflections options.
|
||||||
|
*
|
||||||
|
* @return screen-space reflections options
|
||||||
|
*/
|
||||||
|
ScreenSpaceReflectionsOptions const& getScreenSpaceReflectionsOptions() const noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables or disable multi-sample anti-aliasing (MSAA). Disabled by default.
|
||||||
|
*
|
||||||
|
* @param options multi-sample anti-aliasing options
|
||||||
|
*/
|
||||||
|
void setMultiSampleAntiAliasingOptions(MultiSampleAntiAliasingOptions options) noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns multi-sample anti-aliasing options.
|
||||||
|
*
|
||||||
|
* @return multi-sample anti-aliasing options
|
||||||
|
*/
|
||||||
|
MultiSampleAntiAliasingOptions const& getMultiSampleAntiAliasingOptions() const noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets this View's color grading transforms.
|
* Sets this View's color grading transforms.
|
||||||
*
|
*
|
||||||
@@ -514,19 +553,44 @@ public:
|
|||||||
*/
|
*/
|
||||||
VsmShadowOptions getVsmShadowOptions() const noexcept;
|
VsmShadowOptions getVsmShadowOptions() const noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets soft shadowing options that apply across the entire View.
|
||||||
|
*
|
||||||
|
* Additional light-specific soft shadow parameters can be set with LightManager::setShadowOptions.
|
||||||
|
*
|
||||||
|
* Only applicable when shadow type is set to ShadowType::DPCF or ShadowType::PCSS.
|
||||||
|
*
|
||||||
|
* @param options Options for shadowing.
|
||||||
|
*
|
||||||
|
* @see setShadowType
|
||||||
|
*
|
||||||
|
* @warning This API is still experimental and subject to change.
|
||||||
|
*/
|
||||||
|
void setSoftShadowOptions(SoftShadowOptions const& options) noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the soft shadowing options associated with this View.
|
||||||
|
*
|
||||||
|
* @return value set by setSoftShadowOptions().
|
||||||
|
*/
|
||||||
|
SoftShadowOptions getSoftShadowOptions() const noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enables or disables post processing. Enabled by default.
|
* Enables or disables post processing. Enabled by default.
|
||||||
*
|
*
|
||||||
* Post-processing includes:
|
* Post-processing includes:
|
||||||
|
* - Depth-of-field
|
||||||
* - Bloom
|
* - Bloom
|
||||||
* - Tone-mapping & gamma encoding
|
* - Vignetting
|
||||||
|
* - Temporal Anti-aliasing (TAA)
|
||||||
|
* - Color grading & gamma encoding
|
||||||
* - Dithering
|
* - Dithering
|
||||||
* - MSAA
|
|
||||||
* - FXAA
|
* - FXAA
|
||||||
* - Dynamic scaling
|
* - Dynamic scaling
|
||||||
*
|
*
|
||||||
* Disabling post-processing forgoes color correctness as well as anti-aliasing and
|
* Disabling post-processing forgoes color correctness as well as some anti-aliasing techniques
|
||||||
* should only be used experimentally (e.g., for UI overlays).
|
* and should only be used for debugging, UI overlays or when using custom render targets
|
||||||
|
* (see RenderTarget).
|
||||||
*
|
*
|
||||||
* @param enabled true enables post processing, false disables it.
|
* @param enabled true enables post processing, false disables it.
|
||||||
*
|
*
|
||||||
@@ -611,9 +675,10 @@ public:
|
|||||||
* @param x Horizontal coordinate to query in the viewport with origin on the left.
|
* @param x Horizontal coordinate to query in the viewport with origin on the left.
|
||||||
* @param y Vertical coordinate to query on the viewport with origin at the bottom.
|
* @param y Vertical coordinate to query on the viewport with origin at the bottom.
|
||||||
* @param data A pointer to an instance of T
|
* @param data A pointer to an instance of T
|
||||||
|
* @param handler Handler to dispatch the callback or nullptr for the default handler.
|
||||||
*/
|
*/
|
||||||
template<typename T, void(T::*method)(PickingQueryResult const&)>
|
template<typename T, void(T::*method)(PickingQueryResult const&)>
|
||||||
void pick(uint32_t x, uint32_t y, T* instance) noexcept {
|
void pick(uint32_t x, uint32_t y, T* instance, backend::CallbackHandler* handler = nullptr) noexcept {
|
||||||
PickingQuery& query = pick(x, y, [](PickingQueryResult const& result, PickingQuery* pq) {
|
PickingQuery& query = pick(x, y, [](PickingQueryResult const& result, PickingQuery* pq) {
|
||||||
void* user = pq->storage;
|
void* user = pq->storage;
|
||||||
(*static_cast<T**>(user)->*method)(result);
|
(*static_cast<T**>(user)->*method)(result);
|
||||||
@@ -630,9 +695,10 @@ public:
|
|||||||
* @param x Horizontal coordinate to query in the viewport with origin on the left.
|
* @param x Horizontal coordinate to query in the viewport with origin on the left.
|
||||||
* @param y Vertical coordinate to query on the viewport with origin at the bottom.
|
* @param y Vertical coordinate to query on the viewport with origin at the bottom.
|
||||||
* @param data An instance of T
|
* @param data An instance of T
|
||||||
|
* @param handler Handler to dispatch the callback or nullptr for the default handler.
|
||||||
*/
|
*/
|
||||||
template<typename T, void(T::*method)(PickingQueryResult const&)>
|
template<typename T, void(T::*method)(PickingQueryResult const&)>
|
||||||
void pick(uint32_t x, uint32_t y, T instance) noexcept {
|
void pick(uint32_t x, uint32_t y, T instance, backend::CallbackHandler* handler = nullptr) noexcept {
|
||||||
static_assert(sizeof(instance) <= sizeof(PickingQuery::storage), "user data too large");
|
static_assert(sizeof(instance) <= sizeof(PickingQuery::storage), "user data too large");
|
||||||
PickingQuery& query = pick(x, y, [](PickingQueryResult const& result, PickingQuery* pq) {
|
PickingQuery& query = pick(x, y, [](PickingQueryResult const& result, PickingQuery* pq) {
|
||||||
void* user = pq->storage;
|
void* user = pq->storage;
|
||||||
@@ -650,11 +716,12 @@ public:
|
|||||||
* @param x Horizontal coordinate to query in the viewport with origin on the left.
|
* @param x Horizontal coordinate to query in the viewport with origin on the left.
|
||||||
* @param y Vertical coordinate to query on the viewport with origin at the bottom.
|
* @param y Vertical coordinate to query on the viewport with origin at the bottom.
|
||||||
* @param functor A functor, typically a lambda function.
|
* @param functor A functor, typically a lambda function.
|
||||||
|
* @param handler Handler to dispatch the callback or nullptr for the default handler.
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void pick(uint32_t x, uint32_t y, T functor) noexcept {
|
void pick(uint32_t x, uint32_t y, T functor, backend::CallbackHandler* handler = nullptr) noexcept {
|
||||||
static_assert(sizeof(functor) <= sizeof(PickingQuery::storage), "functor too large");
|
static_assert(sizeof(functor) <= sizeof(PickingQuery::storage), "functor too large");
|
||||||
PickingQuery& query = pick(x, y,
|
PickingQuery& query = pick(x, y, handler,
|
||||||
(PickingQueryResultCallback)[](PickingQueryResult const& result, PickingQuery* pq) {
|
(PickingQueryResultCallback)[](PickingQueryResult const& result, PickingQuery* pq) {
|
||||||
void* user = pq->storage;
|
void* user = pq->storage;
|
||||||
T& that = *static_cast<T*>(user);
|
T& that = *static_cast<T*>(user);
|
||||||
@@ -674,11 +741,12 @@ public:
|
|||||||
* @param x Horizontal coordinate to query in the viewport with origin on the left.
|
* @param x Horizontal coordinate to query in the viewport with origin on the left.
|
||||||
* @param y Vertical coordinate to query on the viewport with origin at the bottom.
|
* @param y Vertical coordinate to query on the viewport with origin at the bottom.
|
||||||
* @param callback User callback, called when the picking query result is available.
|
* @param callback User callback, called when the picking query result is available.
|
||||||
|
* @param handler Handler to dispatch the callback or nullptr for the default handler.
|
||||||
* @return A reference to a PickingQuery structure, which can be used to store up to
|
* @return A reference to a PickingQuery structure, which can be used to store up to
|
||||||
* 8*sizeof(void*) bytes of user data. This user data is later accessible
|
* 8*sizeof(void*) bytes of user data. This user data is later accessible
|
||||||
* in the PickingQueryResultCallback callback 3rd parameter.
|
* in the PickingQueryResultCallback callback 3rd parameter.
|
||||||
*/
|
*/
|
||||||
PickingQuery& pick(uint32_t x, uint32_t y,
|
PickingQuery& pick(uint32_t x, uint32_t y, backend::CallbackHandler* handler,
|
||||||
PickingQueryResultCallback callback) noexcept;
|
PickingQueryResultCallback callback) noexcept;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,120 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2016 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef TNT_FILAMENT_FILAMESHIO_MESHREADER_H
|
|
||||||
#define TNT_FILAMENT_FILAMESHIO_MESHREADER_H
|
|
||||||
|
|
||||||
#include <utils/compiler.h>
|
|
||||||
#include <utils/Entity.h>
|
|
||||||
#include <utils/CString.h>
|
|
||||||
|
|
||||||
namespace filament {
|
|
||||||
class Engine;
|
|
||||||
class VertexBuffer;
|
|
||||||
class IndexBuffer;
|
|
||||||
class MaterialInstance;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace utils {
|
|
||||||
class Path;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace filamesh {
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This API can be used to read meshes stored in the "filamesh" format produced
|
|
||||||
* by the command line tool of the same name. This file format is documented in
|
|
||||||
* "docs/filamesh.md" in the Filament distribution.
|
|
||||||
*/
|
|
||||||
class UTILS_PUBLIC MeshReader {
|
|
||||||
public:
|
|
||||||
using Callback = void(*)(void* buffer, size_t size, void* user);
|
|
||||||
|
|
||||||
// Class to track material instances
|
|
||||||
class MaterialRegistry {
|
|
||||||
public:
|
|
||||||
MaterialRegistry();
|
|
||||||
MaterialRegistry(const MaterialRegistry& rhs);
|
|
||||||
MaterialRegistry& operator=(const MaterialRegistry& rhs);
|
|
||||||
~MaterialRegistry();
|
|
||||||
MaterialRegistry(MaterialRegistry&&);
|
|
||||||
MaterialRegistry& operator=(MaterialRegistry&&);
|
|
||||||
|
|
||||||
filament::MaterialInstance* getMaterialInstance(const utils::CString& name);
|
|
||||||
|
|
||||||
void registerMaterialInstance(const utils::CString& name,
|
|
||||||
filament::MaterialInstance* materialInstance);
|
|
||||||
|
|
||||||
void unregisterMaterialInstance(const utils::CString& name);
|
|
||||||
|
|
||||||
void unregisterAll();
|
|
||||||
|
|
||||||
std::size_t numRegistered() const noexcept;
|
|
||||||
|
|
||||||
void getRegisteredMaterials(filament::MaterialInstance** materialList,
|
|
||||||
utils::CString* materialNameList) const;
|
|
||||||
|
|
||||||
void getRegisteredMaterials(filament::MaterialInstance** materialList) const;
|
|
||||||
|
|
||||||
void getRegisteredMaterialNames(utils::CString* materialNameList) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct MaterialRegistryImpl;
|
|
||||||
MaterialRegistryImpl* mImpl;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Mesh {
|
|
||||||
utils::Entity renderable;
|
|
||||||
filament::VertexBuffer* vertexBuffer = nullptr;
|
|
||||||
filament::IndexBuffer* indexBuffer = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads a filamesh renderable from the specified file. The material registry
|
|
||||||
* can be used to provide named materials. If a material found in the filamesh
|
|
||||||
* file cannot be matched to a material in the registry, a default material is
|
|
||||||
* used instead. The default material can be overridden by adding a material
|
|
||||||
* named "DefaultMaterial" to the registry.
|
|
||||||
*/
|
|
||||||
static Mesh loadMeshFromFile(filament::Engine* engine,
|
|
||||||
const utils::Path& path,
|
|
||||||
MaterialRegistry& materials);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads a filamesh renderable from an in-memory buffer. The material registry
|
|
||||||
* can be used to provide named materials. If a material found in the filamesh
|
|
||||||
* file cannot be matched to a material in the registry, a default material is
|
|
||||||
* used instead. The default material can be overridden by adding a material
|
|
||||||
* named "DefaultMaterial" to the registry.
|
|
||||||
*/
|
|
||||||
static Mesh loadMeshFromBuffer(filament::Engine* engine,
|
|
||||||
void const* data, Callback destructor, void* user,
|
|
||||||
MaterialRegistry& materials);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads a filamesh renderable from an in-memory buffer. The material registry
|
|
||||||
* can be used to provide named materials. All the primitives of the decoded
|
|
||||||
* renderable are assigned the specified default material.
|
|
||||||
*/
|
|
||||||
static Mesh loadMeshFromBuffer(filament::Engine* engine,
|
|
||||||
void const* data, Callback destructor, void* user,
|
|
||||||
filament::MaterialInstance* defaultMaterial);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace filamesh
|
|
||||||
|
|
||||||
#endif // TNT_FILAMENT_FILAMESHIO_MESHREADER_H
|
|
||||||
@@ -1,131 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2019 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef TNT_GEOMETRY_SURFACEORIENTATION_H
|
|
||||||
#define TNT_GEOMETRY_SURFACEORIENTATION_H
|
|
||||||
|
|
||||||
#include <math/quat.h>
|
|
||||||
#include <math/vec3.h>
|
|
||||||
#include <math/vec4.h>
|
|
||||||
|
|
||||||
#include <utils/compiler.h>
|
|
||||||
|
|
||||||
namespace filament {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mesh-related utilities.
|
|
||||||
*/
|
|
||||||
namespace geometry {
|
|
||||||
|
|
||||||
struct OrientationBuilderImpl;
|
|
||||||
struct OrientationImpl;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The surface orientation helper can be used to populate Filament-style TANGENTS buffers.
|
|
||||||
*/
|
|
||||||
class UTILS_PUBLIC SurfaceOrientation {
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Builder is used to construct an immutable surface orientation helper.
|
|
||||||
*
|
|
||||||
* Clients provide pointers into their own data, which is synchronously consumed during build().
|
|
||||||
* At a minimum, clients must supply a vertex count. They can supply data in any of the
|
|
||||||
* following combinations:
|
|
||||||
*
|
|
||||||
* 1. normals only ........................... not recommended, selects arbitrary orientation
|
|
||||||
* 2. normals + tangents ..................... sign of W determines bitangent orientation
|
|
||||||
* 3. normals + uvs + positions + indices .... selects Lengyel’s Method
|
|
||||||
* 4. positions + indices .................... generates normals for flat shading only
|
|
||||||
*
|
|
||||||
* Additionally, the client-side data has the following type constraints:
|
|
||||||
*
|
|
||||||
* - Normals must be float3
|
|
||||||
* - Tangents must be float4
|
|
||||||
* - UVs must be float2
|
|
||||||
* - Positions must be float3
|
|
||||||
* - Triangles must be uint3 or ushort3
|
|
||||||
*
|
|
||||||
* Currently, mikktspace is not supported because it requires re-indexing the mesh. Instead
|
|
||||||
* we use the method described by Eric Lengyel in "Foundations of Game Engine Development"
|
|
||||||
* (Volume 2, Chapter 7).
|
|
||||||
*/
|
|
||||||
class Builder {
|
|
||||||
public:
|
|
||||||
Builder() noexcept;
|
|
||||||
~Builder() noexcept;
|
|
||||||
Builder(Builder&& that) noexcept;
|
|
||||||
Builder& operator=(Builder&& that) noexcept;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This attribute is required.
|
|
||||||
*/
|
|
||||||
Builder& vertexCount(size_t vertexCount) noexcept;
|
|
||||||
|
|
||||||
Builder& normals(const filament::math::float3*, size_t stride = 0) noexcept;
|
|
||||||
Builder& tangents(const filament::math::float4*, size_t stride = 0) noexcept;
|
|
||||||
Builder& uvs(const filament::math::float2*, size_t stride = 0) noexcept;
|
|
||||||
Builder& positions(const filament::math::float3*, size_t stride = 0) noexcept;
|
|
||||||
|
|
||||||
Builder& triangleCount(size_t triangleCount) noexcept;
|
|
||||||
Builder& triangles(const filament::math::uint3*) noexcept;
|
|
||||||
Builder& triangles(const filament::math::ushort3*) noexcept;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates quats or returns null if the submitted data is an incomplete combination.
|
|
||||||
*/
|
|
||||||
SurfaceOrientation* build();
|
|
||||||
|
|
||||||
private:
|
|
||||||
OrientationBuilderImpl* mImpl;
|
|
||||||
Builder(const Builder&) = delete;
|
|
||||||
Builder& operator=(const Builder&) = delete;
|
|
||||||
};
|
|
||||||
|
|
||||||
~SurfaceOrientation() noexcept;
|
|
||||||
SurfaceOrientation(SurfaceOrientation&& that) noexcept;
|
|
||||||
SurfaceOrientation& operator=(SurfaceOrientation&& that) noexcept;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the vertex count.
|
|
||||||
*/
|
|
||||||
size_t getVertexCount() const noexcept;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts quaternions into the desired output format and writes up to "quatCount"
|
|
||||||
* to the given output pointer. Normally quatCount should be equal to the vertex count.
|
|
||||||
* The optional stride is the desired quat-to-quat stride in bytes.
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
void getQuats(filament::math::quatf* out, size_t quatCount, size_t stride = 0) const noexcept;
|
|
||||||
void getQuats(filament::math::short4* out, size_t quatCount, size_t stride = 0) const noexcept;
|
|
||||||
void getQuats(filament::math::quath* out, size_t quatCount, size_t stride = 0) const noexcept;
|
|
||||||
/**
|
|
||||||
* @}
|
|
||||||
*/
|
|
||||||
|
|
||||||
private:
|
|
||||||
SurfaceOrientation(OrientationImpl*) noexcept;
|
|
||||||
SurfaceOrientation(const SurfaceOrientation&) = delete;
|
|
||||||
SurfaceOrientation& operator=(const SurfaceOrientation&) = delete;
|
|
||||||
OrientationImpl* mImpl;
|
|
||||||
friend struct OrientationBuilderImpl;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace geometry
|
|
||||||
} // namespace filament
|
|
||||||
|
|
||||||
#endif // TNT_GEOMETRY_SURFACEORIENTATION_H
|
|
||||||
@@ -1,104 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2021 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef TNT_GEOMETRY_TRANSCODER_H
|
|
||||||
#define TNT_GEOMETRY_TRANSCODER_H
|
|
||||||
|
|
||||||
#include <utils/compiler.h>
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
namespace filament {
|
|
||||||
namespace geometry {
|
|
||||||
|
|
||||||
enum class ComponentType {
|
|
||||||
BYTE, //!< If normalization is enabled, this maps from [-127,127] to [-1,+1]
|
|
||||||
UBYTE, //!< If normalization is enabled, this maps from [0,255] to [0, +1]
|
|
||||||
SHORT, //!< If normalization is enabled, this maps from [-32767,32767] to [-1,+1]
|
|
||||||
USHORT, //!< If normalization is enabled, this maps from [0,65535] to [0, +1]
|
|
||||||
HALF, //!< 1 sign bit, 5 exponent bits, and 5 mantissa bits.
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a function object that can convert vertex attribute data into tightly packed floats.
|
|
||||||
*
|
|
||||||
* This is especially useful for 3-component formats which are not supported by all backends.
|
|
||||||
* e.g. The Vulkan minspec includes float3 but not short3.
|
|
||||||
*
|
|
||||||
* Usage Example:
|
|
||||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
* using filament::geometry::Transcoder;
|
|
||||||
* using filament::geometry::ComponentType;
|
|
||||||
*
|
|
||||||
* Transcoder transcode({
|
|
||||||
* .componentType = ComponentType::BYTE,
|
|
||||||
* .normalized = true,
|
|
||||||
* .componentCount = 3,
|
|
||||||
* .inputStrideBytes = 0
|
|
||||||
* });
|
|
||||||
*
|
|
||||||
* transcode(outputPtr, inputPtr, count);
|
|
||||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
*
|
|
||||||
* The interpretation of signed normalized data is consistent with Vulkan and OpenGL ES 3.0+.
|
|
||||||
* Note that this slightly differs from earlier versions of OpenGL ES. For example, a signed byte
|
|
||||||
* value of -127 maps exactly to -1.0f under ES3 and VK rules, but not ES2.
|
|
||||||
*/
|
|
||||||
class UTILS_PUBLIC Transcoder {
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Describes the format of all input data that get passed to this transcoder object.
|
|
||||||
*/
|
|
||||||
struct Config {
|
|
||||||
ComponentType componentType;
|
|
||||||
bool normalized;
|
|
||||||
uint32_t componentCount;
|
|
||||||
uint32_t inputStrideBytes = 0; //!< If stride is 0, the transcoder assumes tight packing.
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates an immutable function object with the specified configuration.
|
|
||||||
*
|
|
||||||
* The config is not passed by const reference to allow for type inference at the call site.
|
|
||||||
*/
|
|
||||||
Transcoder(Config config) noexcept : mConfig(config) {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts arbitrary data into tightly packed 32-bit floating point values.
|
|
||||||
*
|
|
||||||
* If target is non-null, writes up to "count" items into target and returns the number of bytes
|
|
||||||
* actually written.
|
|
||||||
*
|
|
||||||
* If target is null, returns the number of bytes required.
|
|
||||||
*
|
|
||||||
* @param target Client owned area to write into, or null for a size query
|
|
||||||
* @param source Pointer to the data to read from (does not get retained)
|
|
||||||
* @param count The maximum number of items to write (i.e. number of float3 values, not bytes)
|
|
||||||
* @return Number of bytes required to contain "count" items after conversion to packed floats
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
size_t operator()(float* UTILS_RESTRICT target, void const* UTILS_RESTRICT source,
|
|
||||||
size_t count) const noexcept;
|
|
||||||
|
|
||||||
private:
|
|
||||||
const Config mConfig;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace geometry
|
|
||||||
} // namespace filament
|
|
||||||
|
|
||||||
#endif // TNT_GEOMETRY_TRANSCODER_H
|
|
||||||
@@ -203,6 +203,16 @@ public:
|
|||||||
*/
|
*/
|
||||||
Animator* getAnimator() noexcept;
|
Animator* getAnimator() noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the morphing weights in the given entity.
|
||||||
|
*/
|
||||||
|
void setMorphWeights(utils::Entity entity, const float* weights, size_t count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the number of morphing in the given entity.
|
||||||
|
*/
|
||||||
|
int getMorphTargetCount(utils::Entity entity) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lazily creates a single LINES renderable that draws the transformed bounding-box hierarchy
|
* Lazily creates a single LINES renderable that draws the transformed bounding-box hierarchy
|
||||||
* for diagnostic purposes. The wireframe is owned by the asset so clients should not delete it.
|
* for diagnostic purposes. The wireframe is owned by the asset so clients should not delete it.
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
// For emscripten and Android builds, we never load from the file
|
// For emscripten and Android builds, we never load from the file
|
||||||
// system, so we-opt out of the stdio functionality in stb.
|
// system, so we-opt out of the stdio functionality in stb.
|
||||||
#if defined(__EMSCRIPTEN__) || defined(ANDROID)
|
#if defined(__EMSCRIPTEN__) || defined(__ANDROID__)
|
||||||
#define STBI_NO_STDIO
|
#define STBI_NO_STDIO
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -52,6 +52,10 @@ struct ResourceConfiguration {
|
|||||||
//! If true, computes the bounding boxes of all \c POSITION attibutes. Well formed glTF files
|
//! If true, computes the bounding boxes of all \c POSITION attibutes. Well formed glTF files
|
||||||
//! do not need this, but it is useful for robustness.
|
//! do not need this, but it is useful for robustness.
|
||||||
bool recomputeBoundingBoxes;
|
bool recomputeBoundingBoxes;
|
||||||
|
|
||||||
|
//! If true, ignore skinned primitives bind transform when compute bounding box. Implicitly true
|
||||||
|
//! for instanced asset. Only applicable when recomputeBoundingBoxes is set to true
|
||||||
|
bool ignoreBindTransform;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,46 +0,0 @@
|
|||||||
#ifndef GLTFRESOURCES_H_
|
|
||||||
#define GLTFRESOURCES_H_
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
extern const uint8_t GLTFRESOURCES_PACKAGE[];
|
|
||||||
extern int GLTFRESOURCES_LIT_FADE_OFFSET;
|
|
||||||
extern int GLTFRESOURCES_LIT_FADE_SIZE;
|
|
||||||
extern int GLTFRESOURCES_LIT_OPAQUE_OFFSET;
|
|
||||||
extern int GLTFRESOURCES_LIT_OPAQUE_SIZE;
|
|
||||||
extern int GLTFRESOURCES_LIT_MASKED_OFFSET;
|
|
||||||
extern int GLTFRESOURCES_LIT_MASKED_SIZE;
|
|
||||||
extern int GLTFRESOURCES_SPECULARGLOSSINESS_FADE_OFFSET;
|
|
||||||
extern int GLTFRESOURCES_SPECULARGLOSSINESS_FADE_SIZE;
|
|
||||||
extern int GLTFRESOURCES_SPECULARGLOSSINESS_OPAQUE_OFFSET;
|
|
||||||
extern int GLTFRESOURCES_SPECULARGLOSSINESS_OPAQUE_SIZE;
|
|
||||||
extern int GLTFRESOURCES_SPECULARGLOSSINESS_MASKED_OFFSET;
|
|
||||||
extern int GLTFRESOURCES_SPECULARGLOSSINESS_MASKED_SIZE;
|
|
||||||
extern int GLTFRESOURCES_UNLIT_FADE_OFFSET;
|
|
||||||
extern int GLTFRESOURCES_UNLIT_FADE_SIZE;
|
|
||||||
extern int GLTFRESOURCES_UNLIT_OPAQUE_OFFSET;
|
|
||||||
extern int GLTFRESOURCES_UNLIT_OPAQUE_SIZE;
|
|
||||||
extern int GLTFRESOURCES_UNLIT_MASKED_OFFSET;
|
|
||||||
extern int GLTFRESOURCES_UNLIT_MASKED_SIZE;
|
|
||||||
extern int GLTFRESOURCES_LIT_VOLUME_OFFSET;
|
|
||||||
extern int GLTFRESOURCES_LIT_VOLUME_SIZE;
|
|
||||||
extern int GLTFRESOURCES_LIT_TRANSMISSION_OFFSET;
|
|
||||||
extern int GLTFRESOURCES_LIT_TRANSMISSION_SIZE;
|
|
||||||
extern int GLTFRESOURCES_LIT_SHEEN_OFFSET;
|
|
||||||
extern int GLTFRESOURCES_LIT_SHEEN_SIZE;
|
|
||||||
}
|
|
||||||
#define GLTFRESOURCES_LIT_FADE_DATA (GLTFRESOURCES_PACKAGE + GLTFRESOURCES_LIT_FADE_OFFSET)
|
|
||||||
#define GLTFRESOURCES_LIT_OPAQUE_DATA (GLTFRESOURCES_PACKAGE + GLTFRESOURCES_LIT_OPAQUE_OFFSET)
|
|
||||||
#define GLTFRESOURCES_LIT_MASKED_DATA (GLTFRESOURCES_PACKAGE + GLTFRESOURCES_LIT_MASKED_OFFSET)
|
|
||||||
#define GLTFRESOURCES_SPECULARGLOSSINESS_FADE_DATA (GLTFRESOURCES_PACKAGE + GLTFRESOURCES_SPECULARGLOSSINESS_FADE_OFFSET)
|
|
||||||
#define GLTFRESOURCES_SPECULARGLOSSINESS_OPAQUE_DATA (GLTFRESOURCES_PACKAGE + GLTFRESOURCES_SPECULARGLOSSINESS_OPAQUE_OFFSET)
|
|
||||||
#define GLTFRESOURCES_SPECULARGLOSSINESS_MASKED_DATA (GLTFRESOURCES_PACKAGE + GLTFRESOURCES_SPECULARGLOSSINESS_MASKED_OFFSET)
|
|
||||||
#define GLTFRESOURCES_UNLIT_FADE_DATA (GLTFRESOURCES_PACKAGE + GLTFRESOURCES_UNLIT_FADE_OFFSET)
|
|
||||||
#define GLTFRESOURCES_UNLIT_OPAQUE_DATA (GLTFRESOURCES_PACKAGE + GLTFRESOURCES_UNLIT_OPAQUE_OFFSET)
|
|
||||||
#define GLTFRESOURCES_UNLIT_MASKED_DATA (GLTFRESOURCES_PACKAGE + GLTFRESOURCES_UNLIT_MASKED_OFFSET)
|
|
||||||
#define GLTFRESOURCES_LIT_VOLUME_DATA (GLTFRESOURCES_PACKAGE + GLTFRESOURCES_LIT_VOLUME_OFFSET)
|
|
||||||
#define GLTFRESOURCES_LIT_TRANSMISSION_DATA (GLTFRESOURCES_PACKAGE + GLTFRESOURCES_LIT_TRANSMISSION_OFFSET)
|
|
||||||
#define GLTFRESOURCES_LIT_SHEEN_DATA (GLTFRESOURCES_PACKAGE + GLTFRESOURCES_LIT_SHEEN_OFFSET)
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
#ifndef GLTFRESOURCES_LITE_H_
|
|
||||||
#define GLTFRESOURCES_LITE_H_
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
extern const uint8_t GLTFRESOURCES_LITE_PACKAGE[];
|
|
||||||
extern int GLTFRESOURCES_LITE_LIT_OPAQUE_OFFSET;
|
|
||||||
extern int GLTFRESOURCES_LITE_LIT_OPAQUE_SIZE;
|
|
||||||
extern int GLTFRESOURCES_LITE_LIT_FADE_OFFSET;
|
|
||||||
extern int GLTFRESOURCES_LITE_LIT_FADE_SIZE;
|
|
||||||
}
|
|
||||||
#define GLTFRESOURCES_LITE_LIT_OPAQUE_DATA (GLTFRESOURCES_LITE_PACKAGE + GLTFRESOURCES_LITE_LIT_OPAQUE_OFFSET)
|
|
||||||
#define GLTFRESOURCES_LITE_LIT_FADE_DATA (GLTFRESOURCES_LITE_PACKAGE + GLTFRESOURCES_LITE_LIT_FADE_OFFSET)
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,199 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2015 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef IBL_CUBEMAP_H
|
|
||||||
#define IBL_CUBEMAP_H
|
|
||||||
|
|
||||||
#include <ibl/Image.h>
|
|
||||||
|
|
||||||
#include <utils/compiler.h>
|
|
||||||
|
|
||||||
#include <math/vec4.h>
|
|
||||||
#include <math/vec3.h>
|
|
||||||
#include <math/vec2.h>
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
namespace filament {
|
|
||||||
namespace ibl {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generic cubemap class. It handles writing / reading into the 6 faces of a cubemap.
|
|
||||||
*
|
|
||||||
* Seamless trilinear filtering is handled.
|
|
||||||
*
|
|
||||||
* This class doesn't own the face data, it's just a "view" on the 6 images.
|
|
||||||
*
|
|
||||||
* @see CubemapUtils
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class UTILS_PUBLIC Cubemap {
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize the cubemap with a given size, but no face is set and no memory is allocated.
|
|
||||||
*
|
|
||||||
* Usually Cubemaps are created using CubemapUtils.
|
|
||||||
*
|
|
||||||
* @see CubemapUtils
|
|
||||||
*/
|
|
||||||
explicit Cubemap(size_t dim);
|
|
||||||
|
|
||||||
Cubemap(Cubemap&&) = default;
|
|
||||||
Cubemap& operator=(Cubemap&&) = default;
|
|
||||||
|
|
||||||
~Cubemap();
|
|
||||||
|
|
||||||
|
|
||||||
enum class Face : uint8_t {
|
|
||||||
PX = 0, // left +----+
|
|
||||||
NX, // right | PY |
|
|
||||||
PY, // bottom +----+----+----+----+
|
|
||||||
NY, // top | NX | PZ | PX | NZ |
|
|
||||||
PZ, // back +----+----+----+----+
|
|
||||||
NZ // front | NY |
|
|
||||||
// +----+
|
|
||||||
};
|
|
||||||
|
|
||||||
using Texel = filament::math::float3;
|
|
||||||
|
|
||||||
|
|
||||||
//! releases all images and reset the cubemap size
|
|
||||||
void resetDimensions(size_t dim);
|
|
||||||
|
|
||||||
//! assigns an image to a face.
|
|
||||||
void setImageForFace(Face face, const Image& image);
|
|
||||||
|
|
||||||
//! retrieves the image attached to a face
|
|
||||||
inline const Image& getImageForFace(Face face) const;
|
|
||||||
|
|
||||||
//! retrieves the image attached to a face
|
|
||||||
inline Image& getImageForFace(Face face);
|
|
||||||
|
|
||||||
//! computes the center of a pixel at coordinate x, y
|
|
||||||
static inline filament::math::float2 center(size_t x, size_t y);
|
|
||||||
|
|
||||||
//! computes a direction vector from a face and a location of the center of pixel in an Image
|
|
||||||
inline filament::math::float3 getDirectionFor(Face face, size_t x, size_t y) const;
|
|
||||||
|
|
||||||
//! computes a direction vector from a face and a location in pixel in an Image
|
|
||||||
inline filament::math::float3 getDirectionFor(Face face, float x, float y) const;
|
|
||||||
|
|
||||||
//! samples the cubemap at the given direction using nearest neighbor filtering
|
|
||||||
inline Texel const& sampleAt(const filament::math::float3& direction) const;
|
|
||||||
|
|
||||||
//! samples the cubemap at the given direction using bilinear filtering
|
|
||||||
inline Texel filterAt(const filament::math::float3& direction) const;
|
|
||||||
|
|
||||||
//! samples an image at the given location in pixel using bilinear filtering
|
|
||||||
static Texel filterAt(const Image& image, float x, float y);
|
|
||||||
static Texel filterAtCenter(const Image& image, size_t x, size_t y);
|
|
||||||
|
|
||||||
//! samples two cubemaps in a given direction and lerps the result by a given lerp factor
|
|
||||||
static Texel trilinearFilterAt(const Cubemap& c0, const Cubemap& c1, float lerp,
|
|
||||||
const filament::math::float3& direction);
|
|
||||||
|
|
||||||
//! reads a texel at a given address
|
|
||||||
inline static const Texel& sampleAt(void const* data) {
|
|
||||||
return *static_cast<Texel const*>(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! writes a texel at a given address
|
|
||||||
inline static void writeAt(void* data, const Texel& texel) {
|
|
||||||
*static_cast<Texel*>(data) = texel;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! returns the size of the cubemap in pixels
|
|
||||||
size_t getDimensions() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prepares a cubemap for seamless access to its faces.
|
|
||||||
*
|
|
||||||
* @warning All faces of the cubemap must be backed-up by the same Image, and must already
|
|
||||||
* be spaced by 2 lines/rows.
|
|
||||||
*/
|
|
||||||
void makeSeamless();
|
|
||||||
|
|
||||||
struct Address {
|
|
||||||
Face face;
|
|
||||||
float s = 0;
|
|
||||||
float t = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! returns the face and texture coordinates of the given direction
|
|
||||||
static Address getAddressFor(const filament::math::float3& direction);
|
|
||||||
|
|
||||||
private:
|
|
||||||
size_t mDimensions = 0;
|
|
||||||
float mScale = 1;
|
|
||||||
float mUpperBound = 0;
|
|
||||||
Image mFaces[6];
|
|
||||||
};
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
inline const Image& Cubemap::getImageForFace(Face face) const {
|
|
||||||
return mFaces[int(face)];
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Image& Cubemap::getImageForFace(Face face) {
|
|
||||||
return mFaces[int(face)];
|
|
||||||
}
|
|
||||||
|
|
||||||
inline filament::math::float2 Cubemap::center(size_t x, size_t y) {
|
|
||||||
return { x + 0.5f, y + 0.5f };
|
|
||||||
}
|
|
||||||
|
|
||||||
inline filament::math::float3 Cubemap::getDirectionFor(Face face, size_t x, size_t y) const {
|
|
||||||
return getDirectionFor(face, x + 0.5f, y + 0.5f);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline filament::math::float3 Cubemap::getDirectionFor(Face face, float x, float y) const {
|
|
||||||
// map [0, dim] to [-1,1] with (-1,-1) at bottom left
|
|
||||||
float cx = (x * mScale) - 1;
|
|
||||||
float cy = 1 - (y * mScale);
|
|
||||||
|
|
||||||
filament::math::float3 dir;
|
|
||||||
const float l = std::sqrt(cx * cx + cy * cy + 1);
|
|
||||||
switch (face) {
|
|
||||||
case Face::PX: dir = { 1, cy, -cx }; break;
|
|
||||||
case Face::NX: dir = { -1, cy, cx }; break;
|
|
||||||
case Face::PY: dir = { cx, 1, -cy }; break;
|
|
||||||
case Face::NY: dir = { cx, -1, cy }; break;
|
|
||||||
case Face::PZ: dir = { cx, cy, 1 }; break;
|
|
||||||
case Face::NZ: dir = { -cx, cy, -1 }; break;
|
|
||||||
}
|
|
||||||
return dir * (1 / l);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Cubemap::Texel const& Cubemap::sampleAt(const filament::math::float3& direction) const {
|
|
||||||
Cubemap::Address addr(getAddressFor(direction));
|
|
||||||
const size_t x = std::min(size_t(addr.s * mDimensions), mDimensions - 1);
|
|
||||||
const size_t y = std::min(size_t(addr.t * mDimensions), mDimensions - 1);
|
|
||||||
return sampleAt(getImageForFace(addr.face).getPixelRef(x, y));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Cubemap::Texel Cubemap::filterAt(const filament::math::float3& direction) const {
|
|
||||||
Cubemap::Address addr(getAddressFor(direction));
|
|
||||||
addr.s = std::min(addr.s * mDimensions, mUpperBound);
|
|
||||||
addr.t = std::min(addr.t * mDimensions, mUpperBound);
|
|
||||||
return filterAt(getImageForFace(addr.face), addr.s, addr.t);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace ibl
|
|
||||||
} // namespace filament
|
|
||||||
|
|
||||||
#endif /* IBL_CUBEMAP_H */
|
|
||||||
@@ -1,91 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2015 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef IBL_CUBEMAPIBL_H
|
|
||||||
#define IBL_CUBEMAPIBL_H
|
|
||||||
|
|
||||||
#include <math/vec3.h>
|
|
||||||
|
|
||||||
#include <utils/Slice.h>
|
|
||||||
#include <utils/compiler.h>
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
namespace utils {
|
|
||||||
class JobSystem;
|
|
||||||
} // namespace utils
|
|
||||||
|
|
||||||
namespace filament {
|
|
||||||
namespace ibl {
|
|
||||||
|
|
||||||
class Cubemap;
|
|
||||||
class Image;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates cubemaps for the IBL.
|
|
||||||
*/
|
|
||||||
class UTILS_PUBLIC CubemapIBL {
|
|
||||||
public:
|
|
||||||
typedef void (*Progress)(size_t, float, void*);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Computes a roughness LOD using prefiltered importance sampling GGX
|
|
||||||
*
|
|
||||||
* @param dst the destination cubemap
|
|
||||||
* @param levels a list of prefiltered lods of the source environment
|
|
||||||
* @param linearRoughness roughness
|
|
||||||
* @param maxNumSamples number of samples for importance sampling
|
|
||||||
* @param updater a callback for the caller to track progress
|
|
||||||
*/
|
|
||||||
static void roughnessFilter(
|
|
||||||
utils::JobSystem& js, Cubemap& dst, const utils::Slice<Cubemap>& levels,
|
|
||||||
float linearRoughness, size_t maxNumSamples, math::float3 mirror, bool prefilter,
|
|
||||||
Progress updater = nullptr, void* userdata = nullptr);
|
|
||||||
|
|
||||||
static void roughnessFilter(
|
|
||||||
utils::JobSystem& js, Cubemap& dst, const std::vector<Cubemap>& levels,
|
|
||||||
float linearRoughness, size_t maxNumSamples, math::float3 mirror, bool prefilter,
|
|
||||||
Progress updater = nullptr, void* userdata = nullptr);
|
|
||||||
|
|
||||||
//! Computes the "DFG" term of the "split-sum" approximation and stores it in a 2D image
|
|
||||||
static void DFG(utils::JobSystem& js, Image& dst, bool multiscatter, bool cloth);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Computes the diffuse irradiance using prefiltered importance sampling GGX
|
|
||||||
*
|
|
||||||
* @note Usually this is done using spherical harmonics instead.
|
|
||||||
*
|
|
||||||
* @param dst the destination cubemap
|
|
||||||
* @param levels a list of prefiltered lods of the source environment
|
|
||||||
* @param maxNumSamples number of samples for importance sampling
|
|
||||||
* @param updater a callback for the caller to track progress
|
|
||||||
*
|
|
||||||
* @see CubemapSH
|
|
||||||
*/
|
|
||||||
static void diffuseIrradiance(utils::JobSystem& js, Cubemap& dst, const std::vector<Cubemap>& levels,
|
|
||||||
size_t maxNumSamples = 1024, Progress updater = nullptr, void* userdata = nullptr);
|
|
||||||
|
|
||||||
// for debugging. ignore.
|
|
||||||
static void brdf(utils::JobSystem& js, Cubemap& dst, float linearRoughness);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace ibl
|
|
||||||
} // namespace filament
|
|
||||||
|
|
||||||
#endif /* IBL_CUBEMAPIBL_H */
|
|
||||||
@@ -1,125 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2015 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef IBL_CUBEMAPSH_H
|
|
||||||
#define IBL_CUBEMAPSH_H
|
|
||||||
|
|
||||||
|
|
||||||
#include <utils/compiler.h>
|
|
||||||
|
|
||||||
#include <math/mat3.h>
|
|
||||||
#include <math/vec3.h>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace utils {
|
|
||||||
class JobSystem;
|
|
||||||
} // namespace utils
|
|
||||||
|
|
||||||
namespace filament {
|
|
||||||
namespace ibl {
|
|
||||||
|
|
||||||
class Cubemap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Computes spherical harmonics
|
|
||||||
*/
|
|
||||||
class UTILS_PUBLIC CubemapSH {
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Spherical Harmonics decomposition of the given cubemap
|
|
||||||
* Optionally calculates irradiance by convolving with truncated cos.
|
|
||||||
*/
|
|
||||||
static std::unique_ptr<math::float3[]> computeSH(
|
|
||||||
utils::JobSystem& js, const Cubemap& cm, size_t numBands, bool irradiance);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Render given spherical harmonics into a cubemap
|
|
||||||
*/
|
|
||||||
static void renderSH(utils::JobSystem& js, Cubemap& cm,
|
|
||||||
const std::unique_ptr<math::float3[]>& sh, size_t numBands);
|
|
||||||
|
|
||||||
static void windowSH(std::unique_ptr<math::float3[]>& sh, size_t numBands, float cutoff);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compute spherical harmonics of the irradiance of the given cubemap.
|
|
||||||
* The SH basis are pre-scaled for easier rendering by the shader. The resulting coefficients
|
|
||||||
* are not spherical harmonics (as they're scalled by various factors). In particular they
|
|
||||||
* cannot be rendered with renderSH() above. Instead use renderPreScaledSH3Bands() which
|
|
||||||
* is exactly the code ran by our shader.
|
|
||||||
*/
|
|
||||||
static void preprocessSHForShader(std::unique_ptr<math::float3[]>& sh);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Render pre-scaled irrandiance SH
|
|
||||||
*/
|
|
||||||
static void renderPreScaledSH3Bands(utils::JobSystem& js, Cubemap& cm,
|
|
||||||
const std::unique_ptr<math::float3[]>& sh);
|
|
||||||
|
|
||||||
static constexpr size_t getShIndex(ssize_t m, size_t l) {
|
|
||||||
return SHindex(m, l);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
class float5 {
|
|
||||||
float v[5];
|
|
||||||
public:
|
|
||||||
float5() = default;
|
|
||||||
constexpr float5(float a, float b, float c, float d, float e) : v{ a, b, c, d, e } {}
|
|
||||||
constexpr float operator[](size_t i) const { return v[i]; }
|
|
||||||
float& operator[](size_t i) { return v[i]; }
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline const float5 multiply(const float5 M[5], float5 x) noexcept {
|
|
||||||
return float5{
|
|
||||||
M[0][0] * x[0] + M[1][0] * x[1] + M[2][0] * x[2] + M[3][0] * x[3] + M[4][0] * x[4],
|
|
||||||
M[0][1] * x[0] + M[1][1] * x[1] + M[2][1] * x[2] + M[3][1] * x[3] + M[4][1] * x[4],
|
|
||||||
M[0][2] * x[0] + M[1][2] * x[1] + M[2][2] * x[2] + M[3][2] * x[3] + M[4][2] * x[4],
|
|
||||||
M[0][3] * x[0] + M[1][3] * x[1] + M[2][3] * x[2] + M[3][3] * x[3] + M[4][3] * x[4],
|
|
||||||
M[0][4] * x[0] + M[1][4] * x[1] + M[2][4] * x[2] + M[3][4] * x[3] + M[4][4] * x[4]
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static inline constexpr size_t SHindex(ssize_t m, size_t l) {
|
|
||||||
return l * (l + 1) + m;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void computeShBasis(float* SHb, size_t numBands, const math::float3& s);
|
|
||||||
|
|
||||||
static float Kml(ssize_t m, size_t l);
|
|
||||||
|
|
||||||
static std::vector<float> Ki(size_t numBands);
|
|
||||||
|
|
||||||
static constexpr float computeTruncatedCosSh(size_t l);
|
|
||||||
|
|
||||||
static float sincWindow(size_t l, float w);
|
|
||||||
|
|
||||||
static math::float3 rotateShericalHarmonicBand1(math::float3 band1, math::mat3f const& M);
|
|
||||||
|
|
||||||
static float5 rotateShericalHarmonicBand2(float5 const& band2, math::mat3f const& M);
|
|
||||||
|
|
||||||
// debugging only...
|
|
||||||
static float Legendre(ssize_t l, ssize_t m, float x);
|
|
||||||
static float TSH(int l, int m, const math::float3& d);
|
|
||||||
static void printShBase(std::ostream& out, int l, int m);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace ibl
|
|
||||||
} // namespace filament
|
|
||||||
|
|
||||||
#endif /* IBL_CUBEMAPSH_H */
|
|
||||||
@@ -1,124 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2015 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef IBL_CUBEMAP_UTILS_H
|
|
||||||
#define IBL_CUBEMAP_UTILS_H
|
|
||||||
|
|
||||||
#include <ibl/Cubemap.h>
|
|
||||||
#include <ibl/Image.h>
|
|
||||||
|
|
||||||
#include <utils/compiler.h>
|
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
namespace utils {
|
|
||||||
class JobSystem;
|
|
||||||
} // namespace utils
|
|
||||||
|
|
||||||
namespace filament {
|
|
||||||
namespace ibl {
|
|
||||||
|
|
||||||
class CubemapIBL;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create and convert Cubemap formats
|
|
||||||
*/
|
|
||||||
class UTILS_PUBLIC CubemapUtils {
|
|
||||||
public:
|
|
||||||
//! Creates a cubemap object and its backing Image
|
|
||||||
static Cubemap create(Image& image, size_t dim, bool horizontal = true);
|
|
||||||
|
|
||||||
struct EmptyState {
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename STATE>
|
|
||||||
using ScanlineProc = std::function<
|
|
||||||
void(STATE& state, size_t y, Cubemap::Face f, Cubemap::Texel* data, size_t width)>;
|
|
||||||
|
|
||||||
template<typename STATE>
|
|
||||||
using ReduceProc = std::function<void(STATE& state)>;
|
|
||||||
|
|
||||||
//! process the cubemap using multithreading
|
|
||||||
template<typename STATE>
|
|
||||||
static void process(Cubemap& cm,
|
|
||||||
utils::JobSystem& js,
|
|
||||||
ScanlineProc<STATE> proc,
|
|
||||||
ReduceProc<STATE> reduce = [](STATE&) {},
|
|
||||||
const STATE& prototype = STATE());
|
|
||||||
|
|
||||||
//! process the cubemap
|
|
||||||
template<typename STATE>
|
|
||||||
static void processSingleThreaded(Cubemap& cm,
|
|
||||||
utils::JobSystem& js,
|
|
||||||
ScanlineProc<STATE> proc,
|
|
||||||
ReduceProc<STATE> reduce = [](STATE&) {},
|
|
||||||
const STATE& prototype = STATE());
|
|
||||||
|
|
||||||
//! clamps image to acceptable range
|
|
||||||
static void clamp(Image& src);
|
|
||||||
|
|
||||||
static void highlight(Image& src);
|
|
||||||
|
|
||||||
//! Downsamples a cubemap by helf in x and y using a box filter
|
|
||||||
static void downsampleCubemapLevelBoxFilter(utils::JobSystem& js, Cubemap& dst, const Cubemap& src);
|
|
||||||
|
|
||||||
//! Return the name of a face (suitable for a file name)
|
|
||||||
static const char* getFaceName(Cubemap::Face face);
|
|
||||||
|
|
||||||
//! computes the solid angle of a pixel of a face of a cubemap
|
|
||||||
static float solidAngle(size_t dim, size_t u, size_t v);
|
|
||||||
|
|
||||||
//! Sets a Cubemap faces from a cross image
|
|
||||||
static void setAllFacesFromCross(Cubemap& cm, const Image& image);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
//move these into cmgen?
|
|
||||||
static void setFaceFromCross(Cubemap& cm, Cubemap::Face face, const Image& image);
|
|
||||||
static Image createCubemapImage(size_t dim, bool horizontal = true);
|
|
||||||
|
|
||||||
#ifndef FILAMENT_IBL_LITE
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
//! Converts horizontal or vertical cross Image to a Cubemap
|
|
||||||
static void crossToCubemap(utils::JobSystem& js, Cubemap& dst, const Image& src);
|
|
||||||
|
|
||||||
//! Converts equirectangular Image to a Cubemap
|
|
||||||
static void equirectangularToCubemap(utils::JobSystem& js, Cubemap& dst, const Image& src);
|
|
||||||
|
|
||||||
//! Converts a Cubemap to an equirectangular Image
|
|
||||||
static void cubemapToEquirectangular(utils::JobSystem& js, Image& dst, const Cubemap& src);
|
|
||||||
|
|
||||||
//! Converts a Cubemap to an octahedron
|
|
||||||
static void cubemapToOctahedron(utils::JobSystem& js, Image& dst, const Cubemap& src);
|
|
||||||
|
|
||||||
//! mirror the cubemap in the horizontal direction
|
|
||||||
static void mirrorCubemap(utils::JobSystem& js, Cubemap& dst, const Cubemap& src);
|
|
||||||
|
|
||||||
//! generates a UV grid in the cubemap -- useful for debugging.
|
|
||||||
static void generateUVGrid(utils::JobSystem& js, Cubemap& cml, size_t gridFrequencyX, size_t gridFrequencyY);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
friend class CubemapIBL;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace ibl
|
|
||||||
} // namespace filament
|
|
||||||
|
|
||||||
#endif /* IBL_CUBEMAP_UTILS_H */
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2015 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef IBL_IMAGE_H
|
|
||||||
#define IBL_IMAGE_H
|
|
||||||
|
|
||||||
#include <math/scalar.h>
|
|
||||||
#include <math/vec3.h>
|
|
||||||
#include <math/vec4.h>
|
|
||||||
|
|
||||||
#include <utils/compiler.h>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
namespace filament {
|
|
||||||
namespace ibl {
|
|
||||||
|
|
||||||
class UTILS_PUBLIC Image {
|
|
||||||
public:
|
|
||||||
Image();
|
|
||||||
Image(size_t w, size_t h, size_t stride = 0);
|
|
||||||
|
|
||||||
void reset();
|
|
||||||
|
|
||||||
void set(Image const& image);
|
|
||||||
|
|
||||||
void subset(Image const& image, size_t x, size_t y, size_t w, size_t h);
|
|
||||||
|
|
||||||
bool isValid() const { return mData != nullptr; }
|
|
||||||
|
|
||||||
size_t getWidth() const { return mWidth; }
|
|
||||||
|
|
||||||
size_t getStride() const { return mBpr / getBytesPerPixel(); }
|
|
||||||
|
|
||||||
size_t getHeight() const { return mHeight; }
|
|
||||||
|
|
||||||
size_t getBytesPerRow() const { return mBpr; }
|
|
||||||
|
|
||||||
size_t getBytesPerPixel() const { return sizeof(math::float3); }
|
|
||||||
|
|
||||||
void* getData() const { return mData; }
|
|
||||||
|
|
||||||
size_t getSize() const { return mBpr * mHeight; }
|
|
||||||
|
|
||||||
void* getPixelRef(size_t x, size_t y) const;
|
|
||||||
|
|
||||||
std::unique_ptr<uint8_t[]> detach() { return std::move(mOwnedData); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
size_t mBpr = 0;
|
|
||||||
size_t mWidth = 0;
|
|
||||||
size_t mHeight = 0;
|
|
||||||
std::unique_ptr<uint8_t[]> mOwnedData;
|
|
||||||
void* mData = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline void* Image::getPixelRef(size_t x, size_t y) const {
|
|
||||||
return static_cast<uint8_t*>(mData) + y * getBytesPerRow() + x * getBytesPerPixel();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace ibl
|
|
||||||
} // namespace filament
|
|
||||||
|
|
||||||
#endif /* IBL_IMAGE_H */
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2015 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef IBL_UTILITIES_H
|
|
||||||
#define IBL_UTILITIES_H
|
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
#include <math/vec2.h>
|
|
||||||
#include <math/vec3.h>
|
|
||||||
|
|
||||||
namespace filament {
|
|
||||||
namespace ibl {
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
static inline constexpr T sq(T x) {
|
|
||||||
return x * x;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
static inline constexpr T log4(T x) {
|
|
||||||
// log2(x)/log2(4)
|
|
||||||
// log2(x)/2
|
|
||||||
return std::log2(x) * T(0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool isPOT(size_t x) {
|
|
||||||
return !(x & (x - 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline filament::math::float2 hammersley(uint32_t i, float iN) {
|
|
||||||
constexpr float tof = 0.5f / 0x80000000U;
|
|
||||||
uint32_t bits = i;
|
|
||||||
bits = (bits << 16u) | (bits >> 16u);
|
|
||||||
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
|
|
||||||
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
|
|
||||||
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
|
|
||||||
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
|
|
||||||
return { i * iN, bits * tof };
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace ibl
|
|
||||||
} // namespace filament
|
|
||||||
#endif /* IBL_UTILITIES_H */
|
|
||||||
194
ios/include/imageio/BlockCompression.h
Normal file
194
ios/include/imageio/BlockCompression.h
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//! \file Functions and types related to block-compressed texture formats.
|
||||||
|
|
||||||
|
#ifndef IMAGEIO_BLOCKCOMPRESSION_H_
|
||||||
|
#define IMAGEIO_BLOCKCOMPRESSION_H_
|
||||||
|
|
||||||
|
#include <image/LinearImage.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <math/vec2.h>
|
||||||
|
|
||||||
|
#include <utils/compiler.h>
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
namespace image {
|
||||||
|
|
||||||
|
enum class CompressedFormat {
|
||||||
|
INVALID = 0,
|
||||||
|
|
||||||
|
R11_EAC = 0x9270,
|
||||||
|
SIGNED_R11_EAC = 0x9271,
|
||||||
|
RG11_EAC = 0x9272,
|
||||||
|
SIGNED_RG11_EAC = 0x9273,
|
||||||
|
RGB8_ETC2 = 0x9274,
|
||||||
|
SRGB8_ETC2 = 0x9275,
|
||||||
|
RGB8_ALPHA1_ETC2 = 0x9276,
|
||||||
|
SRGB8_ALPHA1_ETC = 0x9277,
|
||||||
|
RGBA8_ETC2_EAC = 0x9278,
|
||||||
|
SRGB8_ALPHA8_ETC2_EAC = 0x9279,
|
||||||
|
|
||||||
|
RGB_S3TC_DXT1 = 0x83F0,
|
||||||
|
RGBA_S3TC_DXT1 = 0x83F1,
|
||||||
|
RGBA_S3TC_DXT3 = 0x83F2,
|
||||||
|
RGBA_S3TC_DXT5 = 0x83F3,
|
||||||
|
SRGB_S3TC_DXT1 = 0x8C4C,
|
||||||
|
SRGB_ALPHA_S3TC_DXT1 = 0x8C4D,
|
||||||
|
SRGB_ALPHA_S3TC_DXT3 = 0x8C4E,
|
||||||
|
SRGB_ALPHA_S3TC_DXT5 = 0x8C4F,
|
||||||
|
|
||||||
|
RGBA_ASTC_4x4 = 0x93B0,
|
||||||
|
RGBA_ASTC_5x4 = 0x93B1,
|
||||||
|
RGBA_ASTC_5x5 = 0x93B2,
|
||||||
|
RGBA_ASTC_6x5 = 0x93B3,
|
||||||
|
RGBA_ASTC_6x6 = 0x93B4,
|
||||||
|
RGBA_ASTC_8x5 = 0x93B5,
|
||||||
|
RGBA_ASTC_8x6 = 0x93B6,
|
||||||
|
RGBA_ASTC_8x8 = 0x93B7,
|
||||||
|
RGBA_ASTC_10x5 = 0x93B8,
|
||||||
|
RGBA_ASTC_10x6 = 0x93B9,
|
||||||
|
RGBA_ASTC_10x8 = 0x93BA,
|
||||||
|
RGBA_ASTC_10x10 = 0x93BB,
|
||||||
|
RGBA_ASTC_12x10 = 0x93BC,
|
||||||
|
RGBA_ASTC_12x12 = 0x93BD,
|
||||||
|
SRGB8_ALPHA8_ASTC_4x4 = 0x93D0,
|
||||||
|
SRGB8_ALPHA8_ASTC_5x4 = 0x93D1,
|
||||||
|
SRGB8_ALPHA8_ASTC_5x5 = 0x93D2,
|
||||||
|
SRGB8_ALPHA8_ASTC_6x5 = 0x93D3,
|
||||||
|
SRGB8_ALPHA8_ASTC_6x6 = 0x93D4,
|
||||||
|
SRGB8_ALPHA8_ASTC_8x5 = 0x93D5,
|
||||||
|
SRGB8_ALPHA8_ASTC_8x6 = 0x93D6,
|
||||||
|
SRGB8_ALPHA8_ASTC_8x8 = 0x93D7,
|
||||||
|
SRGB8_ALPHA8_ASTC_10x5 = 0x93D8,
|
||||||
|
SRGB8_ALPHA8_ASTC_10x6 = 0x93D9,
|
||||||
|
SRGB8_ALPHA8_ASTC_10x8 = 0x93DA,
|
||||||
|
SRGB8_ALPHA8_ASTC_10x10 = 0x93DB,
|
||||||
|
SRGB8_ALPHA8_ASTC_12x10 = 0x93DC,
|
||||||
|
SRGB8_ALPHA8_ASTC_12x12 = 0x93DD,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Represents the opaque result of compression and the chosen texture format.
|
||||||
|
struct CompressedTexture {
|
||||||
|
const CompressedFormat format;
|
||||||
|
const uint32_t size;
|
||||||
|
std::unique_ptr<uint8_t[]> data;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ASTC ////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Controls how fast compression occurs at the cost of quality in the resulting image.
|
||||||
|
enum class AstcPreset {
|
||||||
|
VERYFAST,
|
||||||
|
FAST,
|
||||||
|
MEDIUM,
|
||||||
|
THOROUGH,
|
||||||
|
EXHAUSTIVE,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Informs the encoder what texels represent; this is especially crucial for normal maps.
|
||||||
|
enum class AstcSemantic {
|
||||||
|
COLORS_LDR,
|
||||||
|
COLORS_HDR,
|
||||||
|
NORMALS,
|
||||||
|
};
|
||||||
|
|
||||||
|
// The encoder configuration controls the quality and speed of compression, as well as the resulting
|
||||||
|
// format. The specified block size must be one of the 14 block sizes that can be consumed by ES 3.2
|
||||||
|
// as per https://www.khronos.org/registry/OpenGL-Refpages/es3/html/glCompressedTexImage2D.xhtml
|
||||||
|
struct AstcConfig {
|
||||||
|
AstcPreset quality;
|
||||||
|
AstcSemantic semantic;
|
||||||
|
filament::math::ushort2 blocksize;
|
||||||
|
bool srgb;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Uses the CPU to compress a linear image (1 to 4 channels) into an ASTC texture. The 16-byte
|
||||||
|
// header block that ARM uses in their file format is not included.
|
||||||
|
CompressedTexture astcCompress(const LinearImage& source, AstcConfig config);
|
||||||
|
|
||||||
|
// Parses a simple underscore-delimited string to produce an ASTC compression configuration. This
|
||||||
|
// makes it easy to incorporate the compression API into command-line tools. If the string is
|
||||||
|
// malformed, this returns a config with a 0x0 blocksize. Example strings: fast_ldr_4x4,
|
||||||
|
// thorough_normals_6x6, veryfast_hdr_12x10
|
||||||
|
AstcConfig astcParseOptionString(const std::string& options);
|
||||||
|
|
||||||
|
// ETC /////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
enum class EtcErrorMetric {
|
||||||
|
RGBA,
|
||||||
|
RGBX,
|
||||||
|
REC709,
|
||||||
|
NUMERIC,
|
||||||
|
NORMALXYZ,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Informs the ETC encoder of the desired output. Effort sets the quality / speed tradeoff with
|
||||||
|
// a number between 0 and 100.
|
||||||
|
struct EtcConfig {
|
||||||
|
CompressedFormat format;
|
||||||
|
EtcErrorMetric metric;
|
||||||
|
int effort;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Uses the CPU to compress a linear image (1 to 4 channels) into an ETC texture.
|
||||||
|
CompressedTexture etcCompress(const LinearImage& source, EtcConfig config);
|
||||||
|
|
||||||
|
// Converts a string into an ETC compression configuration where the string has the form
|
||||||
|
// FORMAT_METRIC_EFFORT where:
|
||||||
|
// - FORMAT is one of: r11, signed_r11, rg11, signed_rg11, rgb8, srgb8, rgb8_alpha,
|
||||||
|
// srgb8_alpha, rgba8, and srgb8_alpha8
|
||||||
|
// - METRIC is one of: rgba, rgbx, rec709, numeric, and normalxyz
|
||||||
|
// - EFFORT is an integer between 0 and 100
|
||||||
|
EtcConfig etcParseOptionString(const std::string& options);
|
||||||
|
|
||||||
|
// S3TC ////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Informs the S3TC encoder of the desired output.
|
||||||
|
struct S3tcConfig {
|
||||||
|
CompressedFormat format;
|
||||||
|
bool srgb;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Uses the CPU to compress a linear image (1 to 4 channels) into an S3TC texture.
|
||||||
|
CompressedTexture s3tcCompress(const LinearImage& source, S3tcConfig config);
|
||||||
|
|
||||||
|
// Parses an underscore-delimited string to produce an S3TC compression configuration. Currently
|
||||||
|
// this only accepts "rgb_dxt1" and "rgba_dxt5". If the string is malformed, this returns a config
|
||||||
|
// with an invalid format.
|
||||||
|
S3tcConfig s3tcParseOptionString(const std::string& options);
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
struct CompressionConfig {
|
||||||
|
enum { INVALID, ASTC, S3TC, ETC } type;
|
||||||
|
AstcConfig astc;
|
||||||
|
S3tcConfig s3tc;
|
||||||
|
EtcConfig etc;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool parseOptionString(const std::string& options, CompressionConfig* config);
|
||||||
|
|
||||||
|
UTILS_PUBLIC
|
||||||
|
CompressedTexture compressTexture(const CompressionConfig& config, const LinearImage& image);
|
||||||
|
|
||||||
|
} // namespace image
|
||||||
|
|
||||||
|
#endif /* IMAGEIO_BLOCKCOMPRESSION_H_ */
|
||||||
47
ios/include/imageio/HDRDecoder.h
Normal file
47
ios/include/imageio/HDRDecoder.h
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef IMAGE_HDRDECODER_H_
|
||||||
|
#define IMAGE_HDRDECODER_H_
|
||||||
|
|
||||||
|
#include <imageio/ImageDecoder.h>
|
||||||
|
|
||||||
|
namespace image {
|
||||||
|
|
||||||
|
class HDRDecoder : public ImageDecoder::Decoder {
|
||||||
|
public:
|
||||||
|
static HDRDecoder* create(std::istream& stream);
|
||||||
|
static bool checkSignature(char const* buf);
|
||||||
|
|
||||||
|
HDRDecoder(const HDRDecoder&) = delete;
|
||||||
|
HDRDecoder& operator=(const HDRDecoder&) = delete;
|
||||||
|
|
||||||
|
private:
|
||||||
|
explicit HDRDecoder(std::istream& stream);
|
||||||
|
~HDRDecoder() override;
|
||||||
|
|
||||||
|
// ImageDecoder::Decoder interface
|
||||||
|
LinearImage decode() override;
|
||||||
|
|
||||||
|
static const char sigRadiance[];
|
||||||
|
static const char sigRGBE[];
|
||||||
|
std::istream& mStream;
|
||||||
|
std::streampos mStreamStartPos;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace image
|
||||||
|
|
||||||
|
#endif /* IMAGE_IMAGEDECODER_H_ */
|
||||||
69
ios/include/imageio/ImageDecoder.h
Normal file
69
ios/include/imageio/ImageDecoder.h
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2015 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef IMAGE_IMAGEDECODER_H_
|
||||||
|
#define IMAGE_IMAGEDECODER_H_
|
||||||
|
|
||||||
|
#include <iosfwd>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <image/LinearImage.h>
|
||||||
|
|
||||||
|
#include <utils/compiler.h>
|
||||||
|
|
||||||
|
namespace image {
|
||||||
|
|
||||||
|
class UTILS_PUBLIC ImageDecoder {
|
||||||
|
public:
|
||||||
|
enum class ColorSpace {
|
||||||
|
LINEAR,
|
||||||
|
SRGB
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns linear floating-point data, or a non-valid image if an error occured.
|
||||||
|
static LinearImage decode(std::istream& stream, const std::string& sourceName,
|
||||||
|
ColorSpace sourceSpace = ColorSpace::SRGB);
|
||||||
|
|
||||||
|
class Decoder {
|
||||||
|
public:
|
||||||
|
virtual LinearImage decode() = 0;
|
||||||
|
virtual ~Decoder() = default;
|
||||||
|
|
||||||
|
ColorSpace getColorSpace() const noexcept {
|
||||||
|
return mColorSpace;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setColorSpace(ColorSpace colorSpace) noexcept {
|
||||||
|
mColorSpace = colorSpace;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
ColorSpace mColorSpace = ColorSpace::SRGB;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum class Format {
|
||||||
|
NONE,
|
||||||
|
PNG,
|
||||||
|
HDR,
|
||||||
|
PSD,
|
||||||
|
EXR
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace image
|
||||||
|
|
||||||
|
#endif /* IMAGE_IMAGEDECODER_H_ */
|
||||||
34
ios/include/imageio/ImageDiffer.h
Normal file
34
ios/include/imageio/ImageDiffer.h
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <image/LinearImage.h>
|
||||||
|
|
||||||
|
#include <utils/Path.h>
|
||||||
|
|
||||||
|
namespace image {
|
||||||
|
|
||||||
|
enum class ComparisonMode {
|
||||||
|
SKIP,
|
||||||
|
COMPARE,
|
||||||
|
UPDATE,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Saves an image to disk or does a load-and-compare, depending on comparison mode.
|
||||||
|
// This makes it easy for unit tests to have compare / update commands.
|
||||||
|
// The passed-in image is the "result image" and the expected image is the "golden image".
|
||||||
|
void updateOrCompare(LinearImage result, const utils::Path& golden, ComparisonMode, float epsilon);
|
||||||
|
|
||||||
|
} // namespace image
|
||||||
64
ios/include/imageio/ImageEncoder.h
Normal file
64
ios/include/imageio/ImageEncoder.h
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2015 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef IMAGE_IMAGEENCODER_H_
|
||||||
|
#define IMAGE_IMAGEENCODER_H_
|
||||||
|
|
||||||
|
#include <iosfwd>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <image/LinearImage.h>
|
||||||
|
|
||||||
|
#include <utils/compiler.h>
|
||||||
|
|
||||||
|
namespace image {
|
||||||
|
|
||||||
|
class UTILS_PUBLIC ImageEncoder {
|
||||||
|
public:
|
||||||
|
enum class Format {
|
||||||
|
PNG, // 8-bit sRGB, 1 or 3 channels
|
||||||
|
PNG_LINEAR, // 8-bit linear RGB, 1 or 3 channels
|
||||||
|
HDR, // 8-bit linear RGBE, 3 channels only
|
||||||
|
RGBM, // 8-bit RGBM, as PNG, 3 channels only
|
||||||
|
PSD, // 16-bit sRGB or 32-bit linear RGB, 3 channels only
|
||||||
|
// Default: 16 bit
|
||||||
|
EXR, // 16-bit linear RGB (half-float), 3 channels only
|
||||||
|
// Default: PIZ compression
|
||||||
|
DDS, // 8-bit sRGB, 1, 2 or 3 channels;
|
||||||
|
// 16-bit or 32-bit linear RGB, 1, 2 or 3 channels
|
||||||
|
// Default: 16 bit
|
||||||
|
DDS_LINEAR, // 8-bit, 16-bit or 32-bit linear RGB, 1, 2 or 3 channels
|
||||||
|
// Default: 16 bit
|
||||||
|
RGB_10_11_11_REV, // RGBA PNG file, but containing 11_11_10 data
|
||||||
|
};
|
||||||
|
|
||||||
|
// Consumes linear floating-point data, returns false if unable to encode.
|
||||||
|
static bool encode(std::ostream& stream, Format format, const LinearImage& image,
|
||||||
|
const std::string& compression, const std::string& destName);
|
||||||
|
|
||||||
|
static Format chooseFormat(const std::string& name, bool forceLinear = false);
|
||||||
|
static std::string chooseExtension(Format format);
|
||||||
|
|
||||||
|
class Encoder {
|
||||||
|
public:
|
||||||
|
virtual bool encode(const LinearImage& image) = 0;
|
||||||
|
virtual ~Encoder() = default;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace image
|
||||||
|
|
||||||
|
#endif /* IMAGE_IMAGEENCODER_H_ */
|
||||||
@@ -14,8 +14,8 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef MATH_TMATHELPERS_H_
|
#ifndef TNT_MATH_TMATHELPERS_H
|
||||||
#define MATH_TMATHELPERS_H_
|
#define TNT_MATH_TMATHELPERS_H
|
||||||
|
|
||||||
#include <math/compiler.h>
|
#include <math/compiler.h>
|
||||||
#include <math/quat.h>
|
#include <math/quat.h>
|
||||||
@@ -804,4 +804,4 @@ public:
|
|||||||
} // namespace math
|
} // namespace math
|
||||||
} // namespace filament
|
} // namespace filament
|
||||||
|
|
||||||
#endif // MATH_TMATHELPERS_H_
|
#endif // TNT_MATH_TMATHELPERS_H
|
||||||
|
|||||||
@@ -14,18 +14,17 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef TNT_MATH_TQUATHELPERS_H
|
||||||
#ifndef MATH_TQUATHELPERS_H_
|
#define TNT_MATH_TQUATHELPERS_H
|
||||||
#define MATH_TQUATHELPERS_H_
|
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#include <math/compiler.h>
|
#include <math/compiler.h>
|
||||||
#include <math/scalar.h>
|
#include <math/scalar.h>
|
||||||
#include <math/vec3.h>
|
#include <math/vec3.h>
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
namespace filament {
|
namespace filament {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace details {
|
namespace details {
|
||||||
@@ -289,4 +288,4 @@ public:
|
|||||||
} // namespace math
|
} // namespace math
|
||||||
} // namespace filament
|
} // namespace filament
|
||||||
|
|
||||||
#endif // MATH_TQUATHELPERS_H_
|
#endif // TNT_MATH_TQUATHELPERS_H
|
||||||
|
|||||||
@@ -14,8 +14,8 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef MATH_TVECHELPERS_H_
|
#ifndef TNT_MATH_TVECHELPERS_H
|
||||||
#define MATH_TVECHELPERS_H_
|
#define TNT_MATH_TVECHELPERS_H
|
||||||
|
|
||||||
#include <math/compiler.h>
|
#include <math/compiler.h>
|
||||||
|
|
||||||
@@ -477,6 +477,13 @@ private:
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
friend inline VECTOR<T> MATH_PURE sign(VECTOR<T> v) {
|
||||||
|
for (size_t i = 0; i < v.size(); i++) {
|
||||||
|
v[i] = std::copysign(T(1), v[i]);
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
friend inline VECTOR<T> MATH_PURE pow(VECTOR<T> v, T p) {
|
friend inline VECTOR<T> MATH_PURE pow(VECTOR<T> v, T p) {
|
||||||
for (size_t i = 0; i < v.size(); i++) {
|
for (size_t i = 0; i < v.size(); i++) {
|
||||||
v[i] = std::pow(v[i], p);
|
v[i] = std::pow(v[i], p);
|
||||||
@@ -622,4 +629,4 @@ private:
|
|||||||
} // namespace math
|
} // namespace math
|
||||||
} // namespace filament
|
} // namespace filament
|
||||||
|
|
||||||
#endif // MATH_TVECHELPERS_H_
|
#endif // TNT_MATH_TVECHELPERS_H
|
||||||
|
|||||||
@@ -14,7 +14,8 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#ifndef TNT_MATH_COMPILER_H
|
||||||
|
#define TNT_MATH_COMPILER_H
|
||||||
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
@@ -111,8 +112,7 @@
|
|||||||
|
|
||||||
#endif // _MSC_VER
|
#endif // _MSC_VER
|
||||||
|
|
||||||
namespace filament {
|
namespace filament::math {
|
||||||
namespace math {
|
|
||||||
|
|
||||||
// MSVC 2019 16.4 doesn't seem to like it when we specialize std::is_arithmetic for
|
// MSVC 2019 16.4 doesn't seem to like it when we specialize std::is_arithmetic for
|
||||||
// filament::math::half, so we're forced to create our own is_arithmetic here and specialize it
|
// filament::math::half, so we're forced to create our own is_arithmetic here and specialize it
|
||||||
@@ -122,5 +122,6 @@ struct is_arithmetic : std::integral_constant<bool,
|
|||||||
std::is_integral<T>::value || std::is_floating_point<T>::value> {
|
std::is_integral<T>::value || std::is_floating_point<T>::value> {
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // filament::math
|
||||||
}
|
|
||||||
|
#endif // TNT_MATH_COMPILER_H
|
||||||
|
|||||||
@@ -17,13 +17,14 @@
|
|||||||
#ifndef TNT_MATH_FAST_H
|
#ifndef TNT_MATH_FAST_H
|
||||||
#define TNT_MATH_FAST_H
|
#define TNT_MATH_FAST_H
|
||||||
|
|
||||||
#include <cmath>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <type_traits>
|
|
||||||
|
|
||||||
#include <math/compiler.h>
|
#include <math/compiler.h>
|
||||||
#include <math/scalar.h>
|
#include <math/scalar.h>
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#ifdef __ARM_NEON
|
#ifdef __ARM_NEON
|
||||||
#include <arm_neon.h>
|
#include <arm_neon.h>
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -17,14 +17,14 @@
|
|||||||
#ifndef TNT_MATH_HALF_H
|
#ifndef TNT_MATH_HALF_H
|
||||||
#define TNT_MATH_HALF_H
|
#define TNT_MATH_HALF_H
|
||||||
|
|
||||||
|
#include <math/compiler.h>
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <math/compiler.h>
|
|
||||||
|
|
||||||
namespace filament {
|
namespace filament {
|
||||||
namespace math {
|
namespace math {
|
||||||
|
|
||||||
|
|||||||
@@ -14,12 +14,13 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef MATH_MAT2_H_
|
#ifndef TNT_MATH_MAT2_H
|
||||||
#define MATH_MAT2_H_
|
#define TNT_MATH_MAT2_H
|
||||||
|
|
||||||
#include <math/TMatHelpers.h>
|
#include <math/TMatHelpers.h>
|
||||||
#include <math/vec2.h>
|
|
||||||
#include <math/compiler.h>
|
#include <math/compiler.h>
|
||||||
|
#include <math/vec2.h>
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
@@ -358,4 +359,4 @@ constexpr void swap(filament::math::details::TMat22<T>& lhs,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // MATH_MAT2_H_
|
#endif // TNT_MATH_MAT2_H
|
||||||
|
|||||||
@@ -14,13 +14,13 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef MATH_MAT3_H_
|
#ifndef TNT_MATH_MAT3_H
|
||||||
#define MATH_MAT3_H_
|
#define TNT_MATH_MAT3_H
|
||||||
|
|
||||||
#include <math/quat.h>
|
|
||||||
#include <math/TMatHelpers.h>
|
#include <math/TMatHelpers.h>
|
||||||
#include <math/vec3.h>
|
|
||||||
#include <math/compiler.h>
|
#include <math/compiler.h>
|
||||||
|
#include <math/quat.h>
|
||||||
|
#include <math/vec3.h>
|
||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@@ -487,4 +487,4 @@ constexpr void swap(filament::math::details::TMat33<T>& lhs,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // MATH_MAT3_H_
|
#endif // TNT_MATH_MAT3_H
|
||||||
|
|||||||
@@ -14,14 +14,14 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef MATH_MAT4_H_
|
#ifndef TNT_MATH_MAT4_H
|
||||||
#define MATH_MAT4_H_
|
#define TNT_MATH_MAT4_H
|
||||||
|
|
||||||
|
#include <math/TMatHelpers.h>
|
||||||
#include <math/compiler.h>
|
#include <math/compiler.h>
|
||||||
#include <math/mat3.h>
|
#include <math/mat3.h>
|
||||||
#include <math/quat.h>
|
#include <math/quat.h>
|
||||||
#include <math/scalar.h>
|
#include <math/scalar.h>
|
||||||
#include <math/TMatHelpers.h>
|
|
||||||
#include <math/vec3.h>
|
#include <math/vec3.h>
|
||||||
#include <math/vec4.h>
|
#include <math/vec4.h>
|
||||||
|
|
||||||
@@ -557,6 +557,26 @@ constexpr typename TMat44<T>::col_type MATH_PURE operator*(const TMat44<T>& lhs,
|
|||||||
typedef details::TMat44<double> mat4;
|
typedef details::TMat44<double> mat4;
|
||||||
typedef details::TMat44<float> mat4f;
|
typedef details::TMat44<float> mat4f;
|
||||||
|
|
||||||
|
// mat4 * float4, with double precision intermediates
|
||||||
|
constexpr float4 highPrecisionMultiply(mat4f const& lhs, float4 const& rhs) noexcept {
|
||||||
|
double4 result{};
|
||||||
|
result += lhs[0] * rhs[0];
|
||||||
|
result += lhs[1] * rhs[1];
|
||||||
|
result += lhs[2] * rhs[2];
|
||||||
|
result += lhs[3] * rhs[3];
|
||||||
|
return float4{ result };
|
||||||
|
}
|
||||||
|
|
||||||
|
// mat4 * mat4, with double precision intermediates
|
||||||
|
constexpr mat4f highPrecisionMultiply(mat4f const& lhs, mat4f const& rhs) noexcept {
|
||||||
|
return {
|
||||||
|
highPrecisionMultiply(lhs, rhs[0]),
|
||||||
|
highPrecisionMultiply(lhs, rhs[1]),
|
||||||
|
highPrecisionMultiply(lhs, rhs[2]),
|
||||||
|
highPrecisionMultiply(lhs, rhs[3])
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------------------
|
||||||
} // namespace math
|
} // namespace math
|
||||||
} // namespace filament
|
} // namespace filament
|
||||||
@@ -628,4 +648,4 @@ constexpr void swap(filament::math::details::TMat44<T>& lhs,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // MATH_MAT4_H_
|
#endif // TNT_MATH_MAT4_H
|
||||||
|
|||||||
@@ -14,8 +14,8 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef MATH_MATHFWD_H_
|
#ifndef TNT_MATH_MATHFWD_H
|
||||||
#define MATH_MATHFWD_H_
|
#define TNT_MATH_MATHFWD_H
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
|
||||||
@@ -91,4 +91,4 @@ using mat4f = details::TMat44<float>;
|
|||||||
|
|
||||||
#endif // _MSC_VER
|
#endif // _MSC_VER
|
||||||
|
|
||||||
#endif // MATH_MATHFWD_H_
|
#endif // TNT_MATH_MATHFWD_H
|
||||||
|
|||||||
@@ -14,14 +14,14 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef MATH_QUAT_H_
|
#ifndef TNT_MATH_QUAT_H
|
||||||
#define MATH_QUAT_H_
|
#define TNT_MATH_QUAT_H
|
||||||
|
|
||||||
#include <math/half.h>
|
|
||||||
#include <math/TQuatHelpers.h>
|
#include <math/TQuatHelpers.h>
|
||||||
|
#include <math/compiler.h>
|
||||||
|
#include <math/half.h>
|
||||||
#include <math/vec3.h>
|
#include <math/vec3.h>
|
||||||
#include <math/vec4.h>
|
#include <math/vec4.h>
|
||||||
#include <math/compiler.h>
|
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
@@ -164,4 +164,4 @@ constexpr inline quat operator "" _k(unsigned long long v) {
|
|||||||
} // namespace math
|
} // namespace math
|
||||||
} // namespace filament
|
} // namespace filament
|
||||||
|
|
||||||
#endif // MATH_QUAT_H_
|
#endif // TNT_MATH_QUAT_H
|
||||||
|
|||||||
@@ -14,16 +14,17 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef MATH_VEC2_H_
|
#ifndef TNT_MATH_VEC2_H
|
||||||
#define MATH_VEC2_H_
|
#define TNT_MATH_VEC2_H
|
||||||
|
|
||||||
#include <math/TVecHelpers.h>
|
#include <math/TVecHelpers.h>
|
||||||
#include <math/half.h>
|
#include <math/half.h>
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <type_traits>
|
|
||||||
|
|
||||||
|
|
||||||
namespace filament {
|
namespace filament {
|
||||||
namespace math {
|
namespace math {
|
||||||
@@ -110,4 +111,4 @@ using bool2 = vec2<bool>;
|
|||||||
} // namespace math
|
} // namespace math
|
||||||
} // namespace filament
|
} // namespace filament
|
||||||
|
|
||||||
#endif // MATH_VEC2_H_
|
#endif // TNT_MATH_VEC2_H
|
||||||
|
|||||||
@@ -14,15 +14,15 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef MATH_VEC3_H_
|
#ifndef TNT_MATH_VEC3_H
|
||||||
#define MATH_VEC3_H_
|
#define TNT_MATH_VEC3_H
|
||||||
|
|
||||||
#include <math/vec2.h>
|
|
||||||
#include <math/half.h>
|
#include <math/half.h>
|
||||||
|
#include <math/vec2.h>
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
|
||||||
namespace filament {
|
namespace filament {
|
||||||
namespace math {
|
namespace math {
|
||||||
// -------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------
|
||||||
@@ -130,4 +130,4 @@ using bool3 = vec3<bool>;
|
|||||||
} // namespace math
|
} // namespace math
|
||||||
} // namespace filament
|
} // namespace filament
|
||||||
|
|
||||||
#endif // MATH_VEC3_H_
|
#endif // TNT_MATH_VEC3_H
|
||||||
|
|||||||
@@ -14,11 +14,12 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef MATH_VEC4_H_
|
#ifndef TNT_MATH_VEC4_H
|
||||||
#define MATH_VEC4_H_
|
#define TNT_MATH_VEC4_H
|
||||||
|
|
||||||
#include <math/vec3.h>
|
|
||||||
#include <math/half.h>
|
#include <math/half.h>
|
||||||
|
#include <math/vec3.h>
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
@@ -129,4 +130,4 @@ using bool4 = vec4<bool>;
|
|||||||
} // namespace math
|
} // namespace math
|
||||||
} // namespace filament
|
} // namespace filament
|
||||||
|
|
||||||
#endif // MATH_VEC4_H_
|
#endif // TNT_MATH_VEC4_H
|
||||||
|
|||||||
@@ -1,60 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2020 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <iosfwd>
|
|
||||||
#include <math/mathfwd.h>
|
|
||||||
|
|
||||||
#if __has_attribute(visibility)
|
|
||||||
# define MATHIO_PUBLIC __attribute__((visibility("default")))
|
|
||||||
#else
|
|
||||||
# define MATHIO_PUBLIC
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace filament {
|
|
||||||
namespace math {
|
|
||||||
|
|
||||||
namespace details { template<typename T> class TQuaternion; }
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
MATHIO_PUBLIC
|
|
||||||
std::ostream& operator<<(std::ostream& out, const details::TVec2<T>& v) noexcept;
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
MATHIO_PUBLIC
|
|
||||||
std::ostream& operator<<(std::ostream& out, const details::TVec3<T>& v) noexcept;
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
MATHIO_PUBLIC
|
|
||||||
std::ostream& operator<<(std::ostream& out, const details::TVec4<T>& v) noexcept;
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
MATHIO_PUBLIC
|
|
||||||
std::ostream& operator<<(std::ostream& out, const details::TMat22<T>& v) noexcept;
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
MATHIO_PUBLIC
|
|
||||||
std::ostream& operator<<(std::ostream& out, const details::TMat33<T>& v) noexcept;
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
MATHIO_PUBLIC
|
|
||||||
std::ostream& operator<<(std::ostream& out, const details::TMat44<T>& v) noexcept;
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
MATHIO_PUBLIC
|
|
||||||
std::ostream& operator<<(std::ostream& out, const details::TQuaternion<T>& v) noexcept;
|
|
||||||
|
|
||||||
} // namespace math
|
|
||||||
} // namespace filament
|
|
||||||
98
ios/include/src/Bookmark.cpp
Normal file
98
ios/include/src/Bookmark.cpp
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <camutils/Bookmark.h>
|
||||||
|
#include <camutils/Manipulator.h>
|
||||||
|
|
||||||
|
#include <math/scalar.h>
|
||||||
|
#include <math/vec3.h>
|
||||||
|
|
||||||
|
using namespace filament::math;
|
||||||
|
|
||||||
|
namespace filament {
|
||||||
|
namespace camutils {
|
||||||
|
|
||||||
|
template <typename FLOAT>
|
||||||
|
Bookmark<FLOAT> Bookmark<FLOAT>::interpolate(Bookmark<FLOAT> a, Bookmark<FLOAT> b, double t) {
|
||||||
|
Bookmark<FLOAT> result;
|
||||||
|
using float3 = filament::math::vec3<FLOAT>;
|
||||||
|
|
||||||
|
if (a.mode == Mode::MAP) {
|
||||||
|
assert(b.mode == Mode::MAP);
|
||||||
|
const double rho = sqrt(2.0);
|
||||||
|
const double rho2 = 2, rho4 = 4;
|
||||||
|
const double ux0 = a.map.center.x, uy0 = a.map.center.y, w0 = a.map.extent;
|
||||||
|
const double ux1 = b.map.center.x, uy1 = b.map.center.y, w1 = b.map.extent;
|
||||||
|
const double dx = ux1 - ux0, dy = uy1 - uy0, d2 = dx * dx + dy * dy, d1 = sqrt(d2);
|
||||||
|
const double b0 = (w1 * w1 - w0 * w0 + rho4 * d2) / (2.0 * w0 * rho2 * d1);
|
||||||
|
const double b1 = (w1 * w1 - w0 * w0 - rho4 * d2) / (2.0 * w1 * rho2 * d1);
|
||||||
|
const double r0 = log(sqrt(b0 * b0 + 1.0) - b0);
|
||||||
|
const double r1 = log(sqrt(b1 * b1 + 1) - b1);
|
||||||
|
const double dr = r1 - r0;
|
||||||
|
const int valid = !std::isnan(dr) && dr != 0;
|
||||||
|
const double S = (valid ? dr : log(w1 / w0)) / rho;
|
||||||
|
const double s = t * S;
|
||||||
|
|
||||||
|
// This performs Van Wijk interpolation to animate between two waypoints on a map.
|
||||||
|
if (valid) {
|
||||||
|
const double coshr0 = cosh(r0);
|
||||||
|
const double u = w0 / (rho2 * d1) * (coshr0 * tanh(rho * s + r0) - sinh(r0));
|
||||||
|
Bookmark<FLOAT> result;
|
||||||
|
result.map.center.x = ux0 + u * dx;
|
||||||
|
result.map.center.y = uy0 + u * dy;
|
||||||
|
result.map.extent = w0 * coshr0 / cosh(rho * s + r0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For degenerate cases, fall back to a simplified interpolation method.
|
||||||
|
result.map.center.x = ux0 + t * dx;
|
||||||
|
result.map.center.y = uy0 + t * dy;
|
||||||
|
result.map.extent = w0 * exp(rho * s);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(b.mode == Mode::ORBIT);
|
||||||
|
result.orbit.phi = lerp(a.orbit.phi, b.orbit.phi, FLOAT(t));
|
||||||
|
result.orbit.theta = lerp(a.orbit.theta, b.orbit.theta, FLOAT(t));
|
||||||
|
result.orbit.distance = lerp(a.orbit.distance, b.orbit.distance, FLOAT(t));
|
||||||
|
result.orbit.pivot = lerp(a.orbit.pivot, b.orbit.pivot, float3(t));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uses the Van Wijk method to suggest a duration for animating between two waypoints on a map.
|
||||||
|
// This does not have units, so just use it as a multiplier.
|
||||||
|
template <typename FLOAT>
|
||||||
|
double Bookmark<FLOAT>::duration(Bookmark<FLOAT> a, Bookmark<FLOAT> b) {
|
||||||
|
assert(a.mode == Mode::ORBIT && b.mode == Mode::ORBIT);
|
||||||
|
const double rho = sqrt(2.0);
|
||||||
|
const double rho2 = 2, rho4 = 4;
|
||||||
|
const double ux0 = a.map.center.x, uy0 = a.map.center.y, w0 = a.map.extent;
|
||||||
|
const double ux1 = b.map.center.x, uy1 = b.map.center.y, w1 = b.map.extent;
|
||||||
|
const double dx = ux1 - ux0, dy = uy1 - uy0, d2 = dx * dx + dy * dy, d1 = sqrt(d2);
|
||||||
|
const double b0 = (w1 * w1 - w0 * w0 + rho4 * d2) / (2.0 * w0 * rho2 * d1);
|
||||||
|
const double b1 = (w1 * w1 - w0 * w0 - rho4 * d2) / (2.0 * w1 * rho2 * d1);
|
||||||
|
const double r0 = log(sqrt(b0 * b0 + 1.0) - b0);
|
||||||
|
const double r1 = log(sqrt(b1 * b1 + 1) - b1);
|
||||||
|
const double dr = r1 - r0;
|
||||||
|
const int valid = !std::isnan(dr) && dr != 0;
|
||||||
|
const double S = (valid ? dr : log(w1 / w0)) / rho;
|
||||||
|
return fabs(S);
|
||||||
|
}
|
||||||
|
|
||||||
|
template class Bookmark<float>;
|
||||||
|
|
||||||
|
} // namespace camutils
|
||||||
|
} // namespace filament
|
||||||
206
ios/include/src/FreeFlightManipulator.h
Normal file
206
ios/include/src/FreeFlightManipulator.h
Normal file
@@ -0,0 +1,206 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CAMUTILS_FREEFLIGHT_MANIPULATOR_H
|
||||||
|
#define CAMUTILS_FREEFLIGHT_MANIPULATOR_H
|
||||||
|
|
||||||
|
#include <camutils/Manipulator.h>
|
||||||
|
|
||||||
|
#include <math/scalar.h>
|
||||||
|
#include <math/mat3.h>
|
||||||
|
#include <math/mat4.h>
|
||||||
|
#include <math/quat.h>
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
namespace filament {
|
||||||
|
namespace camutils {
|
||||||
|
|
||||||
|
using namespace filament::math;
|
||||||
|
|
||||||
|
template<typename FLOAT>
|
||||||
|
class FreeFlightManipulator : public Manipulator<FLOAT> {
|
||||||
|
public:
|
||||||
|
using vec2 = filament::math::vec2<FLOAT>;
|
||||||
|
using vec3 = filament::math::vec3<FLOAT>;
|
||||||
|
using vec4 = filament::math::vec4<FLOAT>;
|
||||||
|
using Bookmark = filament::camutils::Bookmark<FLOAT>;
|
||||||
|
using Base = Manipulator<FLOAT>;
|
||||||
|
using Config = typename Base::Config;
|
||||||
|
|
||||||
|
FreeFlightManipulator(Mode mode, const Config& props) : Base(mode, props) {
|
||||||
|
setProperties(props);
|
||||||
|
Base::mEye = Base::mProps.flightStartPosition;
|
||||||
|
const auto pitch = Base::mProps.flightStartPitch;
|
||||||
|
const auto yaw = Base::mProps.flightStartYaw;
|
||||||
|
mTargetEuler = {pitch, yaw};
|
||||||
|
updateTarget(pitch, yaw);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setProperties(const Config& props) override {
|
||||||
|
Config resolved = props;
|
||||||
|
|
||||||
|
if (resolved.flightPanSpeed == vec2(0, 0)) {
|
||||||
|
resolved.flightPanSpeed = vec2(0.01, 0.01);
|
||||||
|
}
|
||||||
|
if (resolved.flightMaxSpeed == 0.0) {
|
||||||
|
resolved.flightMaxSpeed = 10.0;
|
||||||
|
}
|
||||||
|
if (resolved.flightSpeedSteps == 0) {
|
||||||
|
resolved.flightSpeedSteps = 80;
|
||||||
|
}
|
||||||
|
|
||||||
|
Base::setProperties(resolved);
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateTarget(FLOAT pitch, FLOAT yaw) {
|
||||||
|
Base::mTarget = Base::mEye + (mat3::eulerZYX(0, yaw, pitch) * vec3(0.0, 0.0, -1.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void grabBegin(int x, int y, bool strafe) override {
|
||||||
|
mGrabWin = {x, y};
|
||||||
|
mGrabbing = true;
|
||||||
|
mGrabEuler = mTargetEuler;
|
||||||
|
}
|
||||||
|
|
||||||
|
void grabUpdate(int x, int y) override {
|
||||||
|
if (!mGrabbing) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const vec2 del = mGrabWin - vec2{x, y};
|
||||||
|
|
||||||
|
const auto& grabPitch = mGrabEuler.x;
|
||||||
|
const auto& grabYaw = mGrabEuler.y;
|
||||||
|
auto& pitch = mTargetEuler.x;
|
||||||
|
auto& yaw = mTargetEuler.y;
|
||||||
|
|
||||||
|
constexpr double EPSILON = 0.001;
|
||||||
|
|
||||||
|
auto panSpeed = Base::mProps.flightPanSpeed;
|
||||||
|
constexpr FLOAT minPitch = (-F_PI_2 + EPSILON);
|
||||||
|
constexpr FLOAT maxPitch = ( F_PI_2 - EPSILON);
|
||||||
|
pitch = clamp(grabPitch + del.y * -panSpeed.y, minPitch, maxPitch);
|
||||||
|
yaw = fmod(grabYaw + del.x * panSpeed.x, 2.0 * F_PI);
|
||||||
|
|
||||||
|
updateTarget(pitch, yaw);
|
||||||
|
}
|
||||||
|
|
||||||
|
void grabEnd() override {
|
||||||
|
mGrabbing = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void keyDown(typename Base::Key key) override {
|
||||||
|
mKeyDown[(int) key] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void keyUp(typename Base::Key key) override {
|
||||||
|
mKeyDown[(int) key] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void scroll(int x, int y, FLOAT scrolldelta) override {
|
||||||
|
const FLOAT halfSpeedSteps = Base::mProps.flightSpeedSteps / 2;
|
||||||
|
mScrollWheel = clamp(mScrollWheel + scrolldelta, -halfSpeedSteps, halfSpeedSteps);
|
||||||
|
// Normalize the scroll position from -1 to 1 and calculate the move speed, in world
|
||||||
|
// units per second.
|
||||||
|
mScrollPositionNormalized = (mScrollWheel + halfSpeedSteps) / halfSpeedSteps - 1.0;
|
||||||
|
mMoveSpeed = pow(Base::mProps.flightMaxSpeed, mScrollPositionNormalized);
|
||||||
|
}
|
||||||
|
|
||||||
|
void update(FLOAT deltaTime) override {
|
||||||
|
vec3 forceLocal { 0.0, 0.0, 0.0 };
|
||||||
|
|
||||||
|
if (mKeyDown[(int) Base::Key::FORWARD]) {
|
||||||
|
forceLocal += vec3{ 0.0, 0.0, -1.0 };
|
||||||
|
}
|
||||||
|
if (mKeyDown[(int) Base::Key::LEFT]) {
|
||||||
|
forceLocal += vec3{ -1.0, 0.0, 0.0 };
|
||||||
|
}
|
||||||
|
if (mKeyDown[(int) Base::Key::BACKWARD]) {
|
||||||
|
forceLocal += vec3{ 0.0, 0.0, 1.0 };
|
||||||
|
}
|
||||||
|
if (mKeyDown[(int) Base::Key::RIGHT]) {
|
||||||
|
forceLocal += vec3{ 1.0, 0.0, 0.0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
const mat4 orientation = mat4::lookAt(Base::mEye, Base::mTarget, Base::mProps.upVector);
|
||||||
|
vec3 forceWorld = (orientation * vec4{ forceLocal, 0.0f }).xyz;
|
||||||
|
|
||||||
|
if (mKeyDown[(int) Base::Key::UP]) {
|
||||||
|
forceWorld += vec3{ 0.0, 1.0, 0.0 };
|
||||||
|
}
|
||||||
|
if (mKeyDown[(int) Base::Key::DOWN]) {
|
||||||
|
forceWorld += vec3{ 0.0, -1.0, 0.0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
forceWorld *= mMoveSpeed;
|
||||||
|
|
||||||
|
const auto dampingFactor = Base::mProps.flightMoveDamping;
|
||||||
|
if (dampingFactor == 0.0) {
|
||||||
|
// Without damping, we simply treat the force as our velocity.
|
||||||
|
mEyeVelocity = forceWorld;
|
||||||
|
} else {
|
||||||
|
// The dampingFactor acts as "friction", which acts upon the camera in the direction
|
||||||
|
// opposite its velocity.
|
||||||
|
// Force is also multiplied by the dampingFactor, to "make up" for the friction.
|
||||||
|
// This ensures that the max velocity still approaches mMoveSpeed;
|
||||||
|
vec3 velocityDelta = (forceWorld - mEyeVelocity) * dampingFactor;
|
||||||
|
mEyeVelocity += velocityDelta * deltaTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
const vec3 positionDelta = mEyeVelocity * deltaTime;
|
||||||
|
|
||||||
|
Base::mEye += positionDelta;
|
||||||
|
Base::mTarget += positionDelta;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bookmark getCurrentBookmark() const override {
|
||||||
|
Bookmark bookmark;
|
||||||
|
bookmark.flight.position = Base::mEye;
|
||||||
|
bookmark.flight.pitch = mTargetEuler.x;
|
||||||
|
bookmark.flight.yaw = mTargetEuler.y;
|
||||||
|
return bookmark;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bookmark getHomeBookmark() const override {
|
||||||
|
Bookmark bookmark;
|
||||||
|
bookmark.flight.position = Base::mProps.flightStartPosition;;
|
||||||
|
bookmark.flight.pitch = Base::mProps.flightStartPitch;
|
||||||
|
bookmark.flight.yaw = Base::mProps.flightStartYaw;
|
||||||
|
return bookmark;
|
||||||
|
}
|
||||||
|
|
||||||
|
void jumpToBookmark(const Bookmark& bookmark) override {
|
||||||
|
Base::mEye = bookmark.flight.position;
|
||||||
|
updateTarget(bookmark.flight.pitch, bookmark.flight.yaw);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
vec2 mGrabWin;
|
||||||
|
vec2 mTargetEuler; // (pitch, yaw)
|
||||||
|
vec2 mGrabEuler; // (pitch, yaw)
|
||||||
|
bool mKeyDown[(int) Base::Key::COUNT] = {false};
|
||||||
|
bool mGrabbing = false;
|
||||||
|
FLOAT mScrollWheel = 0.0f;
|
||||||
|
FLOAT mScrollPositionNormalized = 0.0f;
|
||||||
|
FLOAT mMoveSpeed = 1.0f;
|
||||||
|
vec3 mEyeVelocity;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace camutils
|
||||||
|
} // namespace filament
|
||||||
|
|
||||||
|
#endif /* CAMUTILS_FREEFLIGHT_MANIPULATOR_H */
|
||||||
323
ios/include/src/Manipulator.cpp
Normal file
323
ios/include/src/Manipulator.cpp
Normal file
@@ -0,0 +1,323 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <camutils/Manipulator.h>
|
||||||
|
|
||||||
|
#include <math/scalar.h>
|
||||||
|
|
||||||
|
#include "FreeFlightManipulator.h"
|
||||||
|
#include "MapManipulator.h"
|
||||||
|
#include "OrbitManipulator.h"
|
||||||
|
|
||||||
|
using namespace filament::math;
|
||||||
|
|
||||||
|
namespace filament {
|
||||||
|
namespace camutils {
|
||||||
|
|
||||||
|
template <typename FLOAT> typename
|
||||||
|
Manipulator<FLOAT>::Builder& Manipulator<FLOAT>::Builder::viewport(int width, int height) {
|
||||||
|
details.viewport[0] = width;
|
||||||
|
details.viewport[1] = height;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename FLOAT> typename
|
||||||
|
Manipulator<FLOAT>::Builder& Manipulator<FLOAT>::Builder::targetPosition(FLOAT x, FLOAT y, FLOAT z) {
|
||||||
|
details.targetPosition = {x, y, z};
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename FLOAT> typename
|
||||||
|
Manipulator<FLOAT>::Builder& Manipulator<FLOAT>::Builder::upVector(FLOAT x, FLOAT y, FLOAT z) {
|
||||||
|
details.upVector = {x, y, z};
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename FLOAT> typename
|
||||||
|
Manipulator<FLOAT>::Builder& Manipulator<FLOAT>::Builder::zoomSpeed(FLOAT val) {
|
||||||
|
details.zoomSpeed = val;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename FLOAT> typename
|
||||||
|
Manipulator<FLOAT>::Builder& Manipulator<FLOAT>::Builder::orbitHomePosition(FLOAT x, FLOAT y, FLOAT z) {
|
||||||
|
details.orbitHomePosition = {x, y, z};
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename FLOAT> typename
|
||||||
|
Manipulator<FLOAT>::Builder& Manipulator<FLOAT>::Builder::orbitSpeed(FLOAT x, FLOAT y) {
|
||||||
|
details.orbitSpeed = {x, y};
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename FLOAT> typename
|
||||||
|
Manipulator<FLOAT>::Builder& Manipulator<FLOAT>::Builder::fovDirection(Fov fov) {
|
||||||
|
details.fovDirection = fov;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename FLOAT> typename
|
||||||
|
Manipulator<FLOAT>::Builder& Manipulator<FLOAT>::Builder::fovDegrees(FLOAT degrees) {
|
||||||
|
details.fovDegrees = degrees;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename FLOAT> typename
|
||||||
|
Manipulator<FLOAT>::Builder& Manipulator<FLOAT>::Builder::farPlane(FLOAT distance) {
|
||||||
|
details.farPlane = distance;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename FLOAT> typename
|
||||||
|
Manipulator<FLOAT>::Builder& Manipulator<FLOAT>::Builder::mapExtent(FLOAT worldWidth, FLOAT worldHeight) {
|
||||||
|
details.mapExtent = {worldWidth, worldHeight};
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename FLOAT> typename
|
||||||
|
Manipulator<FLOAT>::Builder& Manipulator<FLOAT>::Builder::mapMinDistance(FLOAT mindist) {
|
||||||
|
details.mapMinDistance = mindist;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename FLOAT> typename
|
||||||
|
Manipulator<FLOAT>::Builder& Manipulator<FLOAT>::Builder::flightStartPosition(FLOAT x, FLOAT y, FLOAT z) {
|
||||||
|
details.flightStartPosition = {x, y, z};
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename FLOAT> typename
|
||||||
|
Manipulator<FLOAT>::Builder& Manipulator<FLOAT>::Builder::flightStartOrientation(FLOAT pitch, FLOAT yaw) {
|
||||||
|
details.flightStartPitch = pitch;
|
||||||
|
details.flightStartYaw = yaw;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename FLOAT> typename
|
||||||
|
Manipulator<FLOAT>::Builder& Manipulator<FLOAT>::Builder::flightMaxMoveSpeed(FLOAT maxSpeed) {
|
||||||
|
details.flightMaxSpeed = maxSpeed;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename FLOAT> typename
|
||||||
|
Manipulator<FLOAT>::Builder& Manipulator<FLOAT>::Builder::flightSpeedSteps(int steps) {
|
||||||
|
details.flightSpeedSteps = steps;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename FLOAT> typename
|
||||||
|
Manipulator<FLOAT>::Builder& Manipulator<FLOAT>::Builder::flightPanSpeed(FLOAT x, FLOAT y) {
|
||||||
|
details.flightPanSpeed = {x, y};
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename FLOAT> typename
|
||||||
|
Manipulator<FLOAT>::Builder& Manipulator<FLOAT>::Builder::flightMoveDamping(FLOAT damping) {
|
||||||
|
details.flightMoveDamping = damping;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename FLOAT> typename
|
||||||
|
Manipulator<FLOAT>::Builder& Manipulator<FLOAT>::Builder::groundPlane(FLOAT a, FLOAT b, FLOAT c, FLOAT d) {
|
||||||
|
details.groundPlane = {a, b, c, d};
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename FLOAT> typename
|
||||||
|
Manipulator<FLOAT>::Builder& Manipulator<FLOAT>::Builder::raycastCallback(RayCallback cb, void* userdata) {
|
||||||
|
details.raycastCallback = cb;
|
||||||
|
details.raycastUserdata = userdata;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename FLOAT>
|
||||||
|
Manipulator<FLOAT>* Manipulator<FLOAT>::Builder::build(Mode mode) {
|
||||||
|
switch (mode) {
|
||||||
|
case Mode::FREE_FLIGHT:
|
||||||
|
return new FreeFlightManipulator<FLOAT>(mode, details);
|
||||||
|
case Mode::MAP:
|
||||||
|
return new MapManipulator<FLOAT>(mode, details);
|
||||||
|
case Mode::ORBIT:
|
||||||
|
return new OrbitManipulator<FLOAT>(mode, details);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename FLOAT>
|
||||||
|
Manipulator<FLOAT>::Manipulator(Mode mode, const Config& props) : mMode(mode) {
|
||||||
|
setProperties(props);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename FLOAT>
|
||||||
|
void Manipulator<FLOAT>::setProperties(const Config& props) {
|
||||||
|
mProps = props;
|
||||||
|
|
||||||
|
if (mProps.zoomSpeed == FLOAT(0)) {
|
||||||
|
mProps.zoomSpeed = 0.01;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mProps.upVector == vec3(0)) {
|
||||||
|
mProps.upVector = vec3(0, 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mProps.fovDegrees == FLOAT(0)) {
|
||||||
|
mProps.fovDegrees = 33;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mProps.farPlane == FLOAT(0)) {
|
||||||
|
mProps.farPlane = 5000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mProps.mapExtent == vec2(0)) {
|
||||||
|
mProps.mapExtent = vec2(512);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename FLOAT>
|
||||||
|
void Manipulator<FLOAT>::setViewport(int width, int height) {
|
||||||
|
Config props = mProps;
|
||||||
|
props.viewport[0] = width;
|
||||||
|
props.viewport[1] = height;
|
||||||
|
setProperties(props);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename FLOAT>
|
||||||
|
void Manipulator<FLOAT>::getLookAt(vec3* eyePosition, vec3* targetPosition, vec3* upward) const {
|
||||||
|
*targetPosition = mTarget;
|
||||||
|
*eyePosition = mEye;
|
||||||
|
const vec3 gaze = normalize(mTarget - mEye);
|
||||||
|
const vec3 right = cross(gaze, mProps.upVector);
|
||||||
|
*upward = cross(right, gaze);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename FLOAT>
|
||||||
|
static bool raycastPlane(const filament::math::vec3<FLOAT>& origin,
|
||||||
|
const filament::math::vec3<FLOAT>& dir, FLOAT* t, void* userdata) {
|
||||||
|
using vec3 = filament::math::vec3<FLOAT>;
|
||||||
|
using vec4 = filament::math::vec4<FLOAT>;
|
||||||
|
auto props = (const typename Manipulator<FLOAT>::Config*) userdata;
|
||||||
|
const vec4 plane = props->groundPlane;
|
||||||
|
const vec3 n = vec3(plane[0], plane[1], plane[2]);
|
||||||
|
const vec3 p0 = n * plane[3];
|
||||||
|
const FLOAT denom = -dot(n, dir);
|
||||||
|
if (denom > 1e-6) {
|
||||||
|
const vec3 p0l0 = p0 - origin;
|
||||||
|
*t = dot(p0l0, n) / -denom;
|
||||||
|
return *t >= 0;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename FLOAT>
|
||||||
|
void Manipulator<FLOAT>::getRay(int x, int y, vec3* porigin, vec3* pdir) const {
|
||||||
|
const vec3 gaze = normalize(mTarget - mEye);
|
||||||
|
const vec3 right = normalize(cross(gaze, mProps.upVector));
|
||||||
|
const vec3 upward = cross(right, gaze);
|
||||||
|
const FLOAT width = mProps.viewport[0];
|
||||||
|
const FLOAT height = mProps.viewport[1];
|
||||||
|
const FLOAT fov = mProps.fovDegrees * F_PI / 180.0;
|
||||||
|
|
||||||
|
// Remap the grid coordinate into [-1, +1] and shift it to the pixel center.
|
||||||
|
const FLOAT u = 2.0 * (0.5 + x) / width - 1.0;
|
||||||
|
const FLOAT v = 2.0 * (0.5 + y) / height - 1.0;
|
||||||
|
|
||||||
|
// Compute the tangent of the field-of-view angle as well as the aspect ratio.
|
||||||
|
const FLOAT tangent = tan(fov / 2.0);
|
||||||
|
const FLOAT aspect = width / height;
|
||||||
|
|
||||||
|
// Adjust the gaze so it goes through the pixel of interest rather than the grid center.
|
||||||
|
vec3 dir = gaze;
|
||||||
|
if (mProps.fovDirection == Fov::VERTICAL) {
|
||||||
|
dir += right * tangent * u * aspect;
|
||||||
|
dir += upward * tangent * v;
|
||||||
|
} else {
|
||||||
|
dir += right * tangent * u;
|
||||||
|
dir += upward * tangent * v / aspect;
|
||||||
|
}
|
||||||
|
dir = normalize(dir);
|
||||||
|
|
||||||
|
*porigin = mEye;
|
||||||
|
*pdir = dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename FLOAT>
|
||||||
|
bool Manipulator<FLOAT>::raycast(int x, int y, vec3* result) const {
|
||||||
|
vec3 origin, dir;
|
||||||
|
getRay(x, y, &origin, &dir);
|
||||||
|
|
||||||
|
// Choose either the user's callback function or the plane intersector.
|
||||||
|
auto callback = mProps.raycastCallback;
|
||||||
|
auto fallback = raycastPlane<FLOAT>;
|
||||||
|
void* userdata = mProps.raycastUserdata;
|
||||||
|
if (!callback) {
|
||||||
|
callback = fallback;
|
||||||
|
userdata = (void*) &mProps;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the ray misses, then try the fallback function.
|
||||||
|
FLOAT t;
|
||||||
|
if (!callback(mEye, dir, &t, userdata)) {
|
||||||
|
if (callback == fallback || !fallback(mEye, dir, &t, (void*) &mProps)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*result = mEye + dir * t;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename FLOAT>
|
||||||
|
filament::math::vec3<FLOAT> Manipulator<FLOAT>::raycastFarPlane(int x, int y) const {
|
||||||
|
const filament::math::vec3<FLOAT> gaze = normalize(mTarget - mEye);
|
||||||
|
const vec3 right = cross(gaze, mProps.upVector);
|
||||||
|
const vec3 upward = cross(right, gaze);
|
||||||
|
const FLOAT width = mProps.viewport[0];
|
||||||
|
const FLOAT height = mProps.viewport[1];
|
||||||
|
const FLOAT fov = mProps.fovDegrees * math::F_PI / 180.0;
|
||||||
|
|
||||||
|
// Remap the grid coordinate into [-1, +1] and shift it to the pixel center.
|
||||||
|
const FLOAT u = 2.0 * (0.5 + x) / width - 1.0;
|
||||||
|
const FLOAT v = 2.0 * (0.5 + y) / height - 1.0;
|
||||||
|
|
||||||
|
// Compute the tangent of the field-of-view angle as well as the aspect ratio.
|
||||||
|
const FLOAT tangent = tan(fov / 2.0);
|
||||||
|
const FLOAT aspect = width / height;
|
||||||
|
|
||||||
|
// Adjust the gaze so it goes through the pixel of interest rather than the grid center.
|
||||||
|
vec3 dir = gaze;
|
||||||
|
if (mProps.fovDirection == Fov::VERTICAL) {
|
||||||
|
dir += right * tangent * u * aspect;
|
||||||
|
dir += upward * tangent * v;
|
||||||
|
} else {
|
||||||
|
dir += right * tangent * u;
|
||||||
|
dir += upward * tangent * v / aspect;
|
||||||
|
}
|
||||||
|
return mEye + dir * mProps.farPlane;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename FLOAT>
|
||||||
|
void Manipulator<FLOAT>::keyDown(Manipulator<FLOAT>::Key key) { }
|
||||||
|
|
||||||
|
template <typename FLOAT>
|
||||||
|
void Manipulator<FLOAT>::keyUp(Manipulator<FLOAT>::Key key) { }
|
||||||
|
|
||||||
|
template <typename FLOAT>
|
||||||
|
void Manipulator<FLOAT>::update(FLOAT deltaTime) { }
|
||||||
|
|
||||||
|
template class Manipulator<float>;
|
||||||
|
|
||||||
|
} // namespace camutils
|
||||||
|
} // namespace filament
|
||||||
197
ios/include/src/MapManipulator.h
Normal file
197
ios/include/src/MapManipulator.h
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CAMUTILS_MAP_MANIPULATOR_H
|
||||||
|
#define CAMUTILS_MAP_MANIPULATOR_H
|
||||||
|
|
||||||
|
#include <camutils/Manipulator.h>
|
||||||
|
|
||||||
|
#include <math/vec3.h>
|
||||||
|
|
||||||
|
namespace filament {
|
||||||
|
namespace camutils {
|
||||||
|
|
||||||
|
template<typename FLOAT>
|
||||||
|
class MapManipulator : public Manipulator<FLOAT> {
|
||||||
|
public:
|
||||||
|
using vec2 = math::vec2<FLOAT>;
|
||||||
|
using vec3 = math::vec3<FLOAT>;
|
||||||
|
using vec4 = math::vec4<FLOAT>;
|
||||||
|
using Bookmark = filament::camutils::Bookmark<FLOAT>;
|
||||||
|
using Base = Manipulator<FLOAT>;
|
||||||
|
using Config = typename Manipulator<FLOAT>::Config;
|
||||||
|
|
||||||
|
MapManipulator(Mode mode, const Config& props) : Manipulator<FLOAT>(mode, props) {
|
||||||
|
const FLOAT width = Base::mProps.mapExtent.x;
|
||||||
|
const FLOAT height = Base::mProps.mapExtent.y;
|
||||||
|
const bool horiz = Base::mProps.fovDirection == Fov::HORIZONTAL;
|
||||||
|
const vec3 targetToEye = Base::mProps.groundPlane.xyz;
|
||||||
|
const FLOAT halfExtent = (horiz ? width : height) / 2.0;
|
||||||
|
const FLOAT fov = Base::mProps.fovDegrees * math::F_PI / 180.0;
|
||||||
|
const FLOAT distance = halfExtent / tan(fov / 2.0);
|
||||||
|
Base::mTarget = Base::mProps.targetPosition;
|
||||||
|
Base::mEye = Base::mTarget + distance * targetToEye;
|
||||||
|
}
|
||||||
|
|
||||||
|
void grabBegin(int x, int y, bool strafe) override {
|
||||||
|
if (strafe || !Base::raycast(x, y, &mGrabScene)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mGrabFar = Base::raycastFarPlane(x, y);
|
||||||
|
mGrabEye = Base::mEye;
|
||||||
|
mGrabTarget = Base::mTarget;
|
||||||
|
mGrabbing = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void grabUpdate(int x, int y) override {
|
||||||
|
if (mGrabbing) {
|
||||||
|
const FLOAT ulen = distance(mGrabScene, mGrabEye);
|
||||||
|
const FLOAT vlen = distance(mGrabFar, mGrabScene);
|
||||||
|
const vec3 translation = (mGrabFar - Base::raycastFarPlane(x, y)) * ulen / vlen;
|
||||||
|
const vec3 eyePosition = mGrabEye + translation;
|
||||||
|
const vec3 targetPosition = mGrabTarget + translation;
|
||||||
|
moveWithConstraints(eyePosition, targetPosition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void grabEnd() override {
|
||||||
|
mGrabbing = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void scroll(int x, int y, FLOAT scrolldelta) override {
|
||||||
|
vec3 grabScene;
|
||||||
|
if (!Base::raycast(x, y, &grabScene)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the direction of travel for the dolly. We do not normalize since it
|
||||||
|
// is desirable to move faster when further away from the targetPosition.
|
||||||
|
vec3 u = grabScene - Base::mEye;
|
||||||
|
|
||||||
|
// Prevent getting stuck when zooming in.
|
||||||
|
if (scrolldelta < 0) {
|
||||||
|
const FLOAT distanceToSurface = length(u);
|
||||||
|
if (distanceToSurface < Base::mProps.zoomSpeed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u *= -scrolldelta * Base::mProps.zoomSpeed;
|
||||||
|
|
||||||
|
const vec3 eyePosition = Base::mEye + u;
|
||||||
|
const vec3 targetPosition = Base::mTarget + u;
|
||||||
|
moveWithConstraints(eyePosition, targetPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
Bookmark getCurrentBookmark() const override {
|
||||||
|
const vec3 dir = normalize(Base::mTarget - Base::mEye);
|
||||||
|
|
||||||
|
FLOAT distance;
|
||||||
|
raycastPlane(Base::mEye, dir, &distance);
|
||||||
|
|
||||||
|
const FLOAT fov = Base::mProps.fovDegrees * math::F_PI / 180.0;
|
||||||
|
const FLOAT halfExtent = distance * tan(fov / 2.0);
|
||||||
|
|
||||||
|
vec3 targetPosition = Base::mEye + dir * distance;
|
||||||
|
|
||||||
|
const vec3 targetToEye = Base::mProps.groundPlane.xyz;
|
||||||
|
const vec3 uvec = cross(Base::mProps.upVector, targetToEye);
|
||||||
|
const vec3 vvec = cross(targetToEye, uvec);
|
||||||
|
const vec3 centerToTarget = targetPosition - Base::mProps.targetPosition;
|
||||||
|
|
||||||
|
Bookmark bookmark;
|
||||||
|
bookmark.mode = Mode::MAP;
|
||||||
|
bookmark.map.extent = halfExtent * 2.0;
|
||||||
|
bookmark.map.center.x = dot(uvec, centerToTarget);
|
||||||
|
bookmark.map.center.y = dot(vvec, centerToTarget);
|
||||||
|
|
||||||
|
bookmark.orbit.theta = 0;
|
||||||
|
bookmark.orbit.phi = 0;
|
||||||
|
bookmark.orbit.pivot = Base::mProps.targetPosition +
|
||||||
|
uvec * bookmark.map.center.x +
|
||||||
|
vvec * bookmark.map.center.y;
|
||||||
|
bookmark.orbit.distance = halfExtent / tan(fov / 2.0);
|
||||||
|
|
||||||
|
return bookmark;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bookmark getHomeBookmark() const override {
|
||||||
|
const FLOAT fov = Base::mProps.fovDegrees * math::F_PI / 180.0;
|
||||||
|
const FLOAT width = Base::mProps.mapExtent.x;
|
||||||
|
const FLOAT height = Base::mProps.mapExtent.y;
|
||||||
|
const bool horiz = Base::mProps.fovDirection == Fov::HORIZONTAL;
|
||||||
|
|
||||||
|
Bookmark bookmark;
|
||||||
|
bookmark.mode = Mode::MAP;
|
||||||
|
bookmark.map.extent = horiz ? width : height;
|
||||||
|
bookmark.map.center.x = 0;
|
||||||
|
bookmark.map.center.y = 0;
|
||||||
|
|
||||||
|
bookmark.orbit.theta = 0;
|
||||||
|
bookmark.orbit.phi = 0;
|
||||||
|
bookmark.orbit.pivot = Base::mTarget;
|
||||||
|
bookmark.orbit.distance = 0.5 * bookmark.map.extent / tan(fov / 2.0);
|
||||||
|
|
||||||
|
// TODO: Add optional boundary constraints here.
|
||||||
|
|
||||||
|
return bookmark;
|
||||||
|
}
|
||||||
|
|
||||||
|
void jumpToBookmark(const Bookmark& bookmark) override {
|
||||||
|
const vec3 targetToEye = Base::mProps.groundPlane.xyz;
|
||||||
|
const FLOAT halfExtent = bookmark.map.extent / 2.0;
|
||||||
|
const FLOAT fov = Base::mProps.fovDegrees * math::F_PI / 180.0;
|
||||||
|
const FLOAT distance = halfExtent / tan(fov / 2.0);
|
||||||
|
vec3 uvec = cross(Base::mProps.upVector, targetToEye);
|
||||||
|
vec3 vvec = cross(targetToEye, uvec);
|
||||||
|
uvec = normalize(uvec) * bookmark.map.center.x;
|
||||||
|
vvec = normalize(vvec) * bookmark.map.center.y;
|
||||||
|
Base::mTarget = Base::mProps.targetPosition + uvec + vvec;
|
||||||
|
Base::mEye = Base::mTarget + distance * targetToEye;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool raycastPlane(const vec3& origin, const vec3& dir, FLOAT* t) const {
|
||||||
|
const vec4 plane = Base::mProps.groundPlane;
|
||||||
|
const vec3 n = vec3(plane[0], plane[1], plane[2]);
|
||||||
|
const vec3 p0 = n * plane[3];
|
||||||
|
const FLOAT denom = -dot(n, dir);
|
||||||
|
if (denom > 1e-6) {
|
||||||
|
const vec3 p0l0 = p0 - origin;
|
||||||
|
*t = dot(p0l0, n) / -denom;
|
||||||
|
return *t >= 0;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void moveWithConstraints(vec3 eye, vec3 targetPosition) {
|
||||||
|
Base::mEye = eye;
|
||||||
|
Base::mTarget = targetPosition;
|
||||||
|
// TODO: Add optional boundary constraints here.
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool mGrabbing = false;
|
||||||
|
vec3 mGrabScene;
|
||||||
|
vec3 mGrabFar;
|
||||||
|
vec3 mGrabEye;
|
||||||
|
vec3 mGrabTarget;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace camutils
|
||||||
|
} // namespace filament
|
||||||
|
|
||||||
|
#endif /* CAMUTILS_MAP_MANIPULATOR_H */
|
||||||
201
ios/include/src/OrbitManipulator.h
Normal file
201
ios/include/src/OrbitManipulator.h
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CAMUTILS_ORBIT_MANIPULATOR_H
|
||||||
|
#define CAMUTILS_ORBIT_MANIPULATOR_H
|
||||||
|
|
||||||
|
#include <camutils/Manipulator.h>
|
||||||
|
|
||||||
|
#include <math/scalar.h>
|
||||||
|
|
||||||
|
#define MAX_PHI (F_PI / 2.0 - 0.001)
|
||||||
|
|
||||||
|
namespace filament {
|
||||||
|
namespace camutils {
|
||||||
|
|
||||||
|
using namespace filament::math;
|
||||||
|
|
||||||
|
template<typename FLOAT>
|
||||||
|
class OrbitManipulator : public Manipulator<FLOAT> {
|
||||||
|
public:
|
||||||
|
using vec2 = filament::math::vec2<FLOAT>;
|
||||||
|
using vec3 = filament::math::vec3<FLOAT>;
|
||||||
|
using vec4 = filament::math::vec4<FLOAT>;
|
||||||
|
using Bookmark = filament::camutils::Bookmark<FLOAT>;
|
||||||
|
using Base = Manipulator<FLOAT>;
|
||||||
|
using Config = typename Base::Config;
|
||||||
|
|
||||||
|
enum GrabState { INACTIVE, ORBITING, PANNING };
|
||||||
|
|
||||||
|
OrbitManipulator(Mode mode, const Config& props) : Base(mode, props) {
|
||||||
|
setProperties(props);
|
||||||
|
Base::mEye = Base::mProps.orbitHomePosition;
|
||||||
|
mPivot = Base::mTarget = Base::mProps.targetPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setProperties(const Config& props) override {
|
||||||
|
Config resolved = props;
|
||||||
|
|
||||||
|
if (resolved.orbitHomePosition == vec3(0)) {
|
||||||
|
resolved.orbitHomePosition = vec3(0, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resolved.orbitSpeed == vec2(0)) {
|
||||||
|
resolved.orbitSpeed = vec2(0.01);
|
||||||
|
}
|
||||||
|
|
||||||
|
// By default, place the ground plane so that it aligns with the targetPosition position.
|
||||||
|
// This is used only when PANNING.
|
||||||
|
if (resolved.groundPlane == vec4(0)) {
|
||||||
|
const FLOAT d = length(resolved.targetPosition);
|
||||||
|
const vec3 n = normalize(resolved.orbitHomePosition - resolved.targetPosition);
|
||||||
|
resolved.groundPlane = vec4(n, -d);
|
||||||
|
}
|
||||||
|
|
||||||
|
Base::setProperties(resolved);
|
||||||
|
}
|
||||||
|
|
||||||
|
void grabBegin(int x, int y, bool strafe) override {
|
||||||
|
mGrabState = strafe ? PANNING : ORBITING;
|
||||||
|
mGrabPivot = mPivot;
|
||||||
|
mGrabEye = Base::mEye;
|
||||||
|
mGrabTarget = Base::mTarget;
|
||||||
|
mGrabBookmark = getCurrentBookmark();
|
||||||
|
mGrabWinX = x;
|
||||||
|
mGrabWinY = y;
|
||||||
|
mGrabFar = Base::raycastFarPlane(x, y);
|
||||||
|
Base::raycast(x, y, &mGrabScene);
|
||||||
|
}
|
||||||
|
|
||||||
|
void grabUpdate(int x, int y) override {
|
||||||
|
const int delx = mGrabWinX - x;
|
||||||
|
const int dely = mGrabWinY - y;
|
||||||
|
|
||||||
|
if (mGrabState == ORBITING) {
|
||||||
|
Bookmark bookmark = getCurrentBookmark();
|
||||||
|
|
||||||
|
const FLOAT theta = delx * Base::mProps.orbitSpeed.x;
|
||||||
|
const FLOAT phi = dely * Base::mProps.orbitSpeed.y;
|
||||||
|
const FLOAT maxPhi = MAX_PHI;
|
||||||
|
|
||||||
|
bookmark.orbit.phi = clamp(mGrabBookmark.orbit.phi + phi, -maxPhi, +maxPhi);
|
||||||
|
bookmark.orbit.theta = mGrabBookmark.orbit.theta + theta;
|
||||||
|
|
||||||
|
jumpToBookmark(bookmark);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mGrabState == PANNING) {
|
||||||
|
const FLOAT ulen = distance(mGrabScene, mGrabEye);
|
||||||
|
const FLOAT vlen = distance(mGrabFar, mGrabScene);
|
||||||
|
const vec3 translation = (mGrabFar - Base::raycastFarPlane(x, y)) * ulen / vlen;
|
||||||
|
mPivot = mGrabPivot + translation;
|
||||||
|
Base::mEye = mGrabEye + translation;
|
||||||
|
Base::mTarget = mGrabTarget + translation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void grabEnd() override {
|
||||||
|
mGrabState = INACTIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void scroll(int x, int y, FLOAT scrolldelta) override {
|
||||||
|
const vec3 gaze = normalize(Base::mTarget - Base::mEye);
|
||||||
|
const vec3 movement = gaze * Base::mProps.zoomSpeed * -scrolldelta;
|
||||||
|
const vec3 v0 = mPivot - Base::mEye;
|
||||||
|
Base::mEye += movement;
|
||||||
|
Base::mTarget += movement;
|
||||||
|
const vec3 v1 = mPivot - Base::mEye;
|
||||||
|
|
||||||
|
// Check if the camera has moved past the point of interest.
|
||||||
|
if (dot(v0, v1) < 0) {
|
||||||
|
mFlipped = !mFlipped;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Bookmark getCurrentBookmark() const override {
|
||||||
|
Bookmark bookmark;
|
||||||
|
bookmark.mode = Mode::ORBIT;
|
||||||
|
const vec3 pivotToEye = Base::mEye - mPivot;
|
||||||
|
const FLOAT d = length(pivotToEye);
|
||||||
|
const FLOAT x = pivotToEye.x / d;
|
||||||
|
const FLOAT y = pivotToEye.y / d;
|
||||||
|
const FLOAT z = pivotToEye.z / d;
|
||||||
|
|
||||||
|
bookmark.orbit.phi = asin(y);
|
||||||
|
bookmark.orbit.theta = atan2(x, z);
|
||||||
|
bookmark.orbit.distance = mFlipped ? -d : d;
|
||||||
|
bookmark.orbit.pivot = mPivot;
|
||||||
|
|
||||||
|
const FLOAT fov = Base::mProps.fovDegrees * math::F_PI / 180.0;
|
||||||
|
const FLOAT halfExtent = d * tan(fov / 2.0);
|
||||||
|
const vec3 targetToEye = Base::mProps.groundPlane.xyz;
|
||||||
|
const vec3 uvec = cross(Base::mProps.upVector, targetToEye);
|
||||||
|
const vec3 vvec = cross(targetToEye, uvec);
|
||||||
|
const vec3 centerToTarget = mPivot - Base::mProps.targetPosition;
|
||||||
|
|
||||||
|
bookmark.map.extent = halfExtent * 2;
|
||||||
|
bookmark.map.center.x = dot(uvec, centerToTarget);
|
||||||
|
bookmark.map.center.y = dot(vvec, centerToTarget);
|
||||||
|
|
||||||
|
return bookmark;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bookmark getHomeBookmark() const override {
|
||||||
|
Bookmark bookmark;
|
||||||
|
bookmark.mode = Mode::ORBIT;
|
||||||
|
bookmark.orbit.phi = FLOAT(0);
|
||||||
|
bookmark.orbit.theta = FLOAT(0);
|
||||||
|
bookmark.orbit.pivot = Base::mProps.targetPosition;
|
||||||
|
bookmark.orbit.distance = distance(Base::mProps.targetPosition, Base::mProps.orbitHomePosition);
|
||||||
|
|
||||||
|
const FLOAT fov = Base::mProps.fovDegrees * math::F_PI / 180.0;
|
||||||
|
const FLOAT halfExtent = bookmark.orbit.distance * tan(fov / 2.0);
|
||||||
|
|
||||||
|
bookmark.map.extent = halfExtent * 2;
|
||||||
|
bookmark.map.center.x = 0;
|
||||||
|
bookmark.map.center.y = 0;
|
||||||
|
|
||||||
|
return bookmark;
|
||||||
|
}
|
||||||
|
|
||||||
|
void jumpToBookmark(const Bookmark& bookmark) override {
|
||||||
|
mPivot = bookmark.orbit.pivot;
|
||||||
|
const FLOAT x = sin(bookmark.orbit.theta) * cos(bookmark.orbit.phi);
|
||||||
|
const FLOAT y = sin(bookmark.orbit.phi);
|
||||||
|
const FLOAT z = cos(bookmark.orbit.theta) * cos(bookmark.orbit.phi);
|
||||||
|
Base::mEye = mPivot + vec3(x, y, z) * abs(bookmark.orbit.distance);
|
||||||
|
mFlipped = bookmark.orbit.distance < 0;
|
||||||
|
Base::mTarget = Base::mEye + vec3(x, y, z) * (mFlipped ? 1.0 : -1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
GrabState mGrabState = INACTIVE;
|
||||||
|
bool mFlipped = false;
|
||||||
|
vec3 mGrabPivot;
|
||||||
|
vec3 mGrabScene;
|
||||||
|
vec3 mGrabFar;
|
||||||
|
vec3 mGrabEye;
|
||||||
|
vec3 mGrabTarget;
|
||||||
|
Bookmark mGrabBookmark;
|
||||||
|
int mGrabWinX;
|
||||||
|
int mGrabWinY;
|
||||||
|
vec3 mPivot;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace camutils
|
||||||
|
} // namespace filament
|
||||||
|
|
||||||
|
#endif /* CAMUTILS_ORBIT_MANIPULATOR_H */
|
||||||
85
ios/include/tests/test_camutils.cpp
Normal file
85
ios/include/tests/test_camutils.cpp
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <camutils/Bookmark.h>
|
||||||
|
#include <camutils/Manipulator.h>
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
using namespace filament::math;
|
||||||
|
|
||||||
|
namespace camutils = filament::camutils;
|
||||||
|
|
||||||
|
using CamManipulator = camutils::Manipulator<float>;
|
||||||
|
|
||||||
|
class CamUtilsTest : public testing::Test {};
|
||||||
|
|
||||||
|
#define EXPECT_VEC_EQ(a, x, y, z) expectVecEq(a, {x, y, z}, __LINE__)
|
||||||
|
|
||||||
|
static void expectVecEq(float3 a, float3 b, int line) {
|
||||||
|
EXPECT_FLOAT_EQ(a.x, b.x);
|
||||||
|
EXPECT_FLOAT_EQ(a.y, b.y);
|
||||||
|
EXPECT_FLOAT_EQ(a.z, b.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(CamUtilsTest, Orbit) {
|
||||||
|
|
||||||
|
float3 eye, targetPosition, up;
|
||||||
|
|
||||||
|
CamManipulator* orbit = CamManipulator::Builder()
|
||||||
|
.viewport(256, 256)
|
||||||
|
.targetPosition(0, 0, 0)
|
||||||
|
.upVector(0, 1, 0)
|
||||||
|
.zoomSpeed(0.01)
|
||||||
|
.orbitHomePosition(0, 0, 4)
|
||||||
|
.orbitSpeed(1, 1)
|
||||||
|
.build(camutils::Mode::ORBIT);
|
||||||
|
|
||||||
|
orbit->getLookAt(&eye, &targetPosition, &up);
|
||||||
|
EXPECT_VEC_EQ(eye, 0, 0, 4);
|
||||||
|
EXPECT_VEC_EQ(targetPosition, 0, 0, 0);
|
||||||
|
EXPECT_VEC_EQ(up, 0, 1, 0);
|
||||||
|
|
||||||
|
orbit->grabBegin(100, 100, false);
|
||||||
|
orbit->grabUpdate(200, 100);
|
||||||
|
orbit->grabEnd();
|
||||||
|
|
||||||
|
orbit->getLookAt(&eye, &targetPosition, &up);
|
||||||
|
EXPECT_VEC_EQ(eye, 2.0254626, 0, 3.4492755);
|
||||||
|
EXPECT_VEC_EQ(targetPosition, 1.519097, 0, 2.5869565);
|
||||||
|
EXPECT_VEC_EQ(up, 0, 1, 0);
|
||||||
|
|
||||||
|
delete orbit;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(CamUtilsTest, Map) {
|
||||||
|
|
||||||
|
float3 eye, targetPosition, up;
|
||||||
|
|
||||||
|
CamManipulator* map = CamManipulator::Builder()
|
||||||
|
.viewport(256, 256)
|
||||||
|
.targetPosition(0, 0, 0)
|
||||||
|
.zoomSpeed(0.01)
|
||||||
|
.orbitHomePosition(0, 0, 4)
|
||||||
|
.build(camutils::Mode::MAP);
|
||||||
|
|
||||||
|
delete map;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
::testing::InitGoogleTest(&argc, argv);
|
||||||
|
return RUN_ALL_TESTS();
|
||||||
|
}
|
||||||
307
ios/include/tsl/array-hash/array_growth_policy.h
Normal file
307
ios/include/tsl/array-hash/array_growth_policy.h
Normal file
@@ -0,0 +1,307 @@
|
|||||||
|
/**
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017 Thibaut Goetghebuer-Planchon <tessil@gmx.com>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
#ifndef TSL_ARRAY_GROWTH_POLICY_H
|
||||||
|
#define TSL_ARRAY_GROWTH_POLICY_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <array>
|
||||||
|
#include <climits>
|
||||||
|
#include <cmath>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <iterator>
|
||||||
|
#include <limits>
|
||||||
|
#include <ratio>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __EXCEPTIONS
|
||||||
|
# define THROW(_e, _m) throw _e(_m)
|
||||||
|
#else
|
||||||
|
# include <stdio.h>
|
||||||
|
# ifndef NDEBUG
|
||||||
|
# define THROW(_e, _m) do { fprintf(stderr, _m); std::terminate(); } while(0)
|
||||||
|
# else
|
||||||
|
# define THROW(_e, _m) std::terminate()
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
namespace tsl {
|
||||||
|
namespace ah {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Grow the hash table by a factor of GrowthFactor keeping the bucket count to a power of two. It allows
|
||||||
|
* the table to use a mask operation instead of a modulo operation to map a hash to a bucket.
|
||||||
|
*
|
||||||
|
* GrowthFactor must be a power of two >= 2.
|
||||||
|
*/
|
||||||
|
template<std::size_t GrowthFactor>
|
||||||
|
class power_of_two_growth_policy {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Called on the hash table creation and on rehash. The number of buckets for the table is passed in parameter.
|
||||||
|
* This number is a minimum, the policy may update this value with a higher value if needed (but not lower).
|
||||||
|
*
|
||||||
|
* If 0 is given, min_bucket_count_in_out must still be 0 after the policy creation and
|
||||||
|
* bucket_for_hash must always return 0 in this case.
|
||||||
|
*/
|
||||||
|
explicit power_of_two_growth_policy(std::size_t& min_bucket_count_in_out) {
|
||||||
|
if(min_bucket_count_in_out > max_bucket_count()) {
|
||||||
|
THROW(std::length_error, "The hash table exceeds its maximum size.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(min_bucket_count_in_out > 0) {
|
||||||
|
min_bucket_count_in_out = round_up_to_power_of_two(min_bucket_count_in_out);
|
||||||
|
m_mask = min_bucket_count_in_out - 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_mask = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the bucket [0, bucket_count()) to which the hash belongs.
|
||||||
|
* If bucket_count() is 0, it must always return 0.
|
||||||
|
*/
|
||||||
|
std::size_t bucket_for_hash(std::size_t hash) const noexcept {
|
||||||
|
return hash & m_mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the number of buckets that should be used on next growth.
|
||||||
|
*/
|
||||||
|
std::size_t next_bucket_count() const {
|
||||||
|
if((m_mask + 1) > max_bucket_count() / GrowthFactor) {
|
||||||
|
THROW(std::length_error, "The hash table exceeds its maximum size.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return (m_mask + 1) * GrowthFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the maximum number of buckets supported by the policy.
|
||||||
|
*/
|
||||||
|
std::size_t max_bucket_count() const {
|
||||||
|
// Largest power of two.
|
||||||
|
return (std::numeric_limits<std::size_t>::max() / 2) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the growth policy as if it was created with a bucket count of 0.
|
||||||
|
* After a clear, the policy must always return 0 when bucket_for_hash is called.
|
||||||
|
*/
|
||||||
|
void clear() noexcept {
|
||||||
|
m_mask = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static std::size_t round_up_to_power_of_two(std::size_t value) {
|
||||||
|
if(is_power_of_two(value)) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(value == 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
--value;
|
||||||
|
for(std::size_t i = 1; i < sizeof(std::size_t) * CHAR_BIT; i *= 2) {
|
||||||
|
value |= value >> i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr bool is_power_of_two(std::size_t value) {
|
||||||
|
return value != 0 && (value & (value - 1)) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static_assert(is_power_of_two(GrowthFactor) && GrowthFactor >= 2, "GrowthFactor must be a power of two >= 2.");
|
||||||
|
|
||||||
|
std::size_t m_mask;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Grow the hash table by GrowthFactor::num / GrowthFactor::den and use a modulo to map a hash
|
||||||
|
* to a bucket. Slower but it can be useful if you want a slower growth.
|
||||||
|
*/
|
||||||
|
template<class GrowthFactor = std::ratio<3, 2>>
|
||||||
|
class mod_growth_policy {
|
||||||
|
public:
|
||||||
|
explicit mod_growth_policy(std::size_t& min_bucket_count_in_out) {
|
||||||
|
if(min_bucket_count_in_out > max_bucket_count()) {
|
||||||
|
THROW(std::length_error, "The hash table exceeds its maximum size.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(min_bucket_count_in_out > 0) {
|
||||||
|
m_mod = min_bucket_count_in_out;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_mod = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t bucket_for_hash(std::size_t hash) const noexcept {
|
||||||
|
return hash % m_mod;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t next_bucket_count() const {
|
||||||
|
if(m_mod == max_bucket_count()) {
|
||||||
|
THROW(std::length_error, "The hash table exceeds its maximum size.");
|
||||||
|
}
|
||||||
|
|
||||||
|
const double next_bucket_count = std::ceil(double(m_mod) * REHASH_SIZE_MULTIPLICATION_FACTOR);
|
||||||
|
if(!std::isnormal(next_bucket_count)) {
|
||||||
|
THROW(std::length_error, "The hash table exceeds its maximum size.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(next_bucket_count > double(max_bucket_count())) {
|
||||||
|
return max_bucket_count();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return std::size_t(next_bucket_count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t max_bucket_count() const {
|
||||||
|
return MAX_BUCKET_COUNT;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear() noexcept {
|
||||||
|
m_mod = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static constexpr double REHASH_SIZE_MULTIPLICATION_FACTOR = 1.0 * GrowthFactor::num / GrowthFactor::den;
|
||||||
|
static const std::size_t MAX_BUCKET_COUNT =
|
||||||
|
std::size_t(double(
|
||||||
|
std::numeric_limits<std::size_t>::max() / REHASH_SIZE_MULTIPLICATION_FACTOR
|
||||||
|
));
|
||||||
|
|
||||||
|
static_assert(REHASH_SIZE_MULTIPLICATION_FACTOR >= 1.1, "Growth factor should be >= 1.1.");
|
||||||
|
|
||||||
|
std::size_t m_mod;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
static constexpr const std::array<std::size_t, 40> PRIMES = {{
|
||||||
|
1ul, 5ul, 17ul, 29ul, 37ul, 53ul, 67ul, 79ul, 97ul, 131ul, 193ul, 257ul, 389ul, 521ul, 769ul, 1031ul,
|
||||||
|
1543ul, 2053ul, 3079ul, 6151ul, 12289ul, 24593ul, 49157ul, 98317ul, 196613ul, 393241ul, 786433ul,
|
||||||
|
1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul, 50331653ul, 100663319ul, 201326611ul,
|
||||||
|
402653189ul, 805306457ul, 1610612741ul, 3221225473ul, 4294967291ul
|
||||||
|
}};
|
||||||
|
|
||||||
|
template<unsigned int IPrime>
|
||||||
|
static constexpr std::size_t mod(std::size_t hash) { return hash % PRIMES[IPrime]; }
|
||||||
|
|
||||||
|
// MOD_PRIME[iprime](hash) returns hash % PRIMES[iprime]. This table allows for faster modulo as the
|
||||||
|
// compiler can optimize the modulo code better with a constant known at the compilation.
|
||||||
|
static constexpr const std::array<std::size_t(*)(std::size_t), 40> MOD_PRIME = {{
|
||||||
|
&mod<0>, &mod<1>, &mod<2>, &mod<3>, &mod<4>, &mod<5>, &mod<6>, &mod<7>, &mod<8>, &mod<9>, &mod<10>,
|
||||||
|
&mod<11>, &mod<12>, &mod<13>, &mod<14>, &mod<15>, &mod<16>, &mod<17>, &mod<18>, &mod<19>, &mod<20>,
|
||||||
|
&mod<21>, &mod<22>, &mod<23>, &mod<24>, &mod<25>, &mod<26>, &mod<27>, &mod<28>, &mod<29>, &mod<30>,
|
||||||
|
&mod<31>, &mod<32>, &mod<33>, &mod<34>, &mod<35>, &mod<36>, &mod<37> , &mod<38>, &mod<39>
|
||||||
|
}};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Grow the hash table by using prime numbers as bucket count. Slower than tsl::ah::power_of_two_growth_policy in
|
||||||
|
* general but will probably distribute the values around better in the buckets with a poor hash function.
|
||||||
|
*
|
||||||
|
* To allow the compiler to optimize the modulo operation, a lookup table is used with constant primes numbers.
|
||||||
|
*
|
||||||
|
* With a switch the code would look like:
|
||||||
|
* \code
|
||||||
|
* switch(iprime) { // iprime is the current prime of the hash table
|
||||||
|
* case 0: hash % 5ul;
|
||||||
|
* break;
|
||||||
|
* case 1: hash % 17ul;
|
||||||
|
* break;
|
||||||
|
* case 2: hash % 29ul;
|
||||||
|
* break;
|
||||||
|
* ...
|
||||||
|
* }
|
||||||
|
* \endcode
|
||||||
|
*
|
||||||
|
* Due to the constant variable in the modulo the compiler is able to optimize the operation
|
||||||
|
* by a series of multiplications, substractions and shifts.
|
||||||
|
*
|
||||||
|
* The 'hash % 5' could become something like 'hash - (hash * 0xCCCCCCCD) >> 34) * 5' in a 64 bits environment.
|
||||||
|
*/
|
||||||
|
class prime_growth_policy {
|
||||||
|
public:
|
||||||
|
explicit prime_growth_policy(std::size_t& min_bucket_count_in_out) {
|
||||||
|
auto it_prime = std::lower_bound(detail::PRIMES.begin(),
|
||||||
|
detail::PRIMES.end(), min_bucket_count_in_out);
|
||||||
|
if(it_prime == detail::PRIMES.end()) {
|
||||||
|
THROW(std::length_error, "The hash table exceeds its maximum size.");
|
||||||
|
}
|
||||||
|
|
||||||
|
m_iprime = static_cast<unsigned int>(std::distance(detail::PRIMES.begin(), it_prime));
|
||||||
|
if(min_bucket_count_in_out > 0) {
|
||||||
|
min_bucket_count_in_out = *it_prime;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
min_bucket_count_in_out = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t bucket_for_hash(std::size_t hash) const noexcept {
|
||||||
|
return detail::MOD_PRIME[m_iprime](hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t next_bucket_count() const {
|
||||||
|
if(m_iprime + 1 >= detail::PRIMES.size()) {
|
||||||
|
THROW(std::length_error, "The hash table exceeds its maximum size.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return detail::PRIMES[m_iprime + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t max_bucket_count() const {
|
||||||
|
return detail::PRIMES.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear() noexcept {
|
||||||
|
m_iprime = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
unsigned int m_iprime;
|
||||||
|
|
||||||
|
static_assert(std::numeric_limits<decltype(m_iprime)>::max() >= detail::PRIMES.size(),
|
||||||
|
"The type of m_iprime is not big enough.");
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
1766
ios/include/tsl/array-hash/array_hash.h
Normal file
1766
ios/include/tsl/array-hash/array_hash.h
Normal file
File diff suppressed because it is too large
Load Diff
863
ios/include/tsl/array-hash/array_map.h
Normal file
863
ios/include/tsl/array-hash/array_map.h
Normal file
@@ -0,0 +1,863 @@
|
|||||||
|
/**
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017 Thibaut Goetghebuer-Planchon <tessil@gmx.com>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
#ifndef TSL_ARRAY_MAP_H
|
||||||
|
#define TSL_ARRAY_MAP_H
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <initializer_list>
|
||||||
|
#include <iterator>
|
||||||
|
#include <string>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <utility>
|
||||||
|
#include "array_hash.h"
|
||||||
|
|
||||||
|
namespace tsl {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of a cache-conscious string hash map.
|
||||||
|
*
|
||||||
|
* The map stores the strings as `const CharT*`. If `StoreNullTerminator` is true,
|
||||||
|
* the strings are stored with the a null-terminator (the `key()` method of the iterators
|
||||||
|
* will return a pointer to this null-terminated string). Otherwise the null character
|
||||||
|
* is not stored (which allow an economy of 1 byte per string).
|
||||||
|
*
|
||||||
|
* The value `T` must be either nothrow move-constructible, copy-constructible or both.
|
||||||
|
*
|
||||||
|
* The size of a key string is limited to `std::numeric_limits<KeySizeT>::max() - 1`.
|
||||||
|
* That is 65 535 characters by default, but can be raised with the `KeySizeT` template parameter.
|
||||||
|
* See `max_key_size()` for an easy access to this limit.
|
||||||
|
*
|
||||||
|
* The number of elements in the map is limited to `std::numeric_limits<IndexSizeT>::max()`.
|
||||||
|
* That is 4 294 967 296 elements, but can be raised with the `IndexSizeT` template parameter.
|
||||||
|
* See `max_size()` for an easy access to this limit.
|
||||||
|
*
|
||||||
|
* Iterators invalidation:
|
||||||
|
* - clear, operator=: always invalidate the iterators.
|
||||||
|
* - insert, emplace, operator[]: always invalidate the iterators.
|
||||||
|
* - erase: always invalidate the iterators.
|
||||||
|
* - shrink_to_fit: always invalidate the iterators.
|
||||||
|
*/
|
||||||
|
template<class CharT,
|
||||||
|
class T,
|
||||||
|
class Hash = tsl::ah::str_hash<CharT>,
|
||||||
|
class KeyEqual = tsl::ah::str_equal<CharT>,
|
||||||
|
bool StoreNullTerminator = true,
|
||||||
|
class KeySizeT = std::uint16_t,
|
||||||
|
class IndexSizeT = std::uint32_t,
|
||||||
|
class GrowthPolicy = tsl::ah::power_of_two_growth_policy<2>>
|
||||||
|
class array_map {
|
||||||
|
private:
|
||||||
|
template<typename U>
|
||||||
|
using is_iterator = tsl::detail_array_hash::is_iterator<U>;
|
||||||
|
|
||||||
|
using ht = tsl::detail_array_hash::array_hash<CharT, T, Hash, KeyEqual, StoreNullTerminator,
|
||||||
|
KeySizeT, IndexSizeT, GrowthPolicy>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using char_type = typename ht::char_type;
|
||||||
|
using mapped_type = T;
|
||||||
|
using key_size_type = typename ht::key_size_type;
|
||||||
|
using index_size_type = typename ht::index_size_type;
|
||||||
|
using size_type = typename ht::size_type;
|
||||||
|
using hasher = typename ht::hasher;
|
||||||
|
using key_equal = typename ht::key_equal;
|
||||||
|
using iterator = typename ht::iterator;
|
||||||
|
using const_iterator = typename ht::const_iterator;
|
||||||
|
|
||||||
|
public:
|
||||||
|
array_map(): array_map(ht::DEFAULT_INIT_BUCKET_COUNT) {
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit array_map(size_type bucket_count,
|
||||||
|
const Hash& hash = Hash()): m_ht(bucket_count, hash, ht::DEFAULT_MAX_LOAD_FACTOR)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class InputIt, typename std::enable_if<is_iterator<InputIt>::value>::type* = nullptr>
|
||||||
|
array_map(InputIt first, InputIt last,
|
||||||
|
size_type bucket_count = ht::DEFAULT_INIT_BUCKET_COUNT,
|
||||||
|
const Hash& hash = Hash()): array_map(bucket_count, hash)
|
||||||
|
{
|
||||||
|
insert(first, last);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TSL_AH_HAS_STRING_VIEW
|
||||||
|
array_map(std::initializer_list<std::pair<std::basic_string_view<CharT>, T>> init,
|
||||||
|
size_type bucket_count = ht::DEFAULT_INIT_BUCKET_COUNT,
|
||||||
|
const Hash& hash = Hash()): array_map(bucket_count, hash)
|
||||||
|
{
|
||||||
|
insert(init);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
array_map(std::initializer_list<std::pair<const CharT*, T>> init,
|
||||||
|
size_type bucket_count = ht::DEFAULT_INIT_BUCKET_COUNT,
|
||||||
|
const Hash& hash = Hash()): array_map(bucket_count, hash)
|
||||||
|
{
|
||||||
|
insert(init);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TSL_AH_HAS_STRING_VIEW
|
||||||
|
array_map& operator=(std::initializer_list<std::pair<std::basic_string_view<CharT>, T>> ilist) {
|
||||||
|
clear();
|
||||||
|
|
||||||
|
reserve(ilist.size());
|
||||||
|
insert(ilist);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
array_map& operator=(std::initializer_list<std::pair<const CharT*, T>> ilist) {
|
||||||
|
clear();
|
||||||
|
|
||||||
|
reserve(ilist.size());
|
||||||
|
insert(ilist);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Iterators
|
||||||
|
*/
|
||||||
|
iterator begin() noexcept { return m_ht.begin(); }
|
||||||
|
const_iterator begin() const noexcept { return m_ht.begin(); }
|
||||||
|
const_iterator cbegin() const noexcept { return m_ht.cbegin(); }
|
||||||
|
|
||||||
|
iterator end() noexcept { return m_ht.end(); }
|
||||||
|
const_iterator end() const noexcept { return m_ht.end(); }
|
||||||
|
const_iterator cend() const noexcept { return m_ht.cend(); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Capacity
|
||||||
|
*/
|
||||||
|
bool empty() const noexcept { return m_ht.empty(); }
|
||||||
|
size_type size() const noexcept { return m_ht.size(); }
|
||||||
|
size_type max_size() const noexcept { return m_ht.max_size(); }
|
||||||
|
size_type max_key_size() const noexcept { return m_ht.max_key_size(); }
|
||||||
|
void shrink_to_fit() { m_ht.shrink_to_fit(); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Modifiers
|
||||||
|
*/
|
||||||
|
void clear() noexcept { m_ht.clear(); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TSL_AH_HAS_STRING_VIEW
|
||||||
|
std::pair<iterator, bool> insert(const std::basic_string_view<CharT>& key, const T& value) {
|
||||||
|
return m_ht.emplace(key.data(), key.size(), value);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
std::pair<iterator, bool> insert(const CharT* key, const T& value) {
|
||||||
|
return m_ht.emplace(key, std::char_traits<CharT>::length(key), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<iterator, bool> insert(const std::basic_string<CharT>& key, const T& value) {
|
||||||
|
return m_ht.emplace(key.data(), key.size(), value);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
std::pair<iterator, bool> insert_ks(const CharT* key, size_type key_size, const T& value) {
|
||||||
|
return m_ht.emplace(key, key_size, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TSL_AH_HAS_STRING_VIEW
|
||||||
|
std::pair<iterator, bool> insert(const std::basic_string_view<CharT>& key, T&& value) {
|
||||||
|
return m_ht.emplace(key.data(), key.size(), std::move(value));
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
std::pair<iterator, bool> insert(const CharT* key, T&& value) {
|
||||||
|
return m_ht.emplace(key, std::char_traits<CharT>::length(key), std::move(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<iterator, bool> insert(const std::basic_string<CharT>& key, T&& value) {
|
||||||
|
return m_ht.emplace(key.data(), key.size(), std::move(value));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
std::pair<iterator, bool> insert_ks(const CharT* key, size_type key_size, T&& value) {
|
||||||
|
return m_ht.emplace(key, key_size, std::move(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template<class InputIt, typename std::enable_if<is_iterator<InputIt>::value>::type* = nullptr>
|
||||||
|
void insert(InputIt first, InputIt last) {
|
||||||
|
if(std::is_base_of<std::forward_iterator_tag,
|
||||||
|
typename std::iterator_traits<InputIt>::iterator_category>::value)
|
||||||
|
{
|
||||||
|
const auto nb_elements_insert = std::distance(first, last);
|
||||||
|
const std::size_t nb_free_buckets = std::size_t(float(bucket_count())*max_load_factor()) - size();
|
||||||
|
|
||||||
|
if(nb_elements_insert > 0 && nb_free_buckets < std::size_t(nb_elements_insert)) {
|
||||||
|
reserve(size() + std::size_t(nb_elements_insert));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto it = first; it != last; ++it) {
|
||||||
|
insert_pair(*it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TSL_AH_HAS_STRING_VIEW
|
||||||
|
void insert(std::initializer_list<std::pair<std::basic_string_view<CharT>, T>> ilist) {
|
||||||
|
insert(ilist.begin(), ilist.end());
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void insert(std::initializer_list<std::pair<const CharT*, T>> ilist) {
|
||||||
|
insert(ilist.begin(), ilist.end());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TSL_AH_HAS_STRING_VIEW
|
||||||
|
template<class M>
|
||||||
|
std::pair<iterator, bool> insert_or_assign(const std::basic_string_view<CharT>& key, M&& obj) {
|
||||||
|
return m_ht.insert_or_assign(key.data(), key.size(), std::forward<M>(obj));
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
template<class M>
|
||||||
|
std::pair<iterator, bool> insert_or_assign(const CharT* key, M&& obj) {
|
||||||
|
return m_ht.insert_or_assign(key, std::char_traits<CharT>::length(key), std::forward<M>(obj));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class M>
|
||||||
|
std::pair<iterator, bool> insert_or_assign(const std::basic_string<CharT>& key, M&& obj) {
|
||||||
|
return m_ht.insert_or_assign(key.data(), key.size(), std::forward<M>(obj));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
template<class M>
|
||||||
|
std::pair<iterator, bool> insert_or_assign_ks(const CharT* key, size_type key_size, M&& obj) {
|
||||||
|
return m_ht.insert_or_assign(key, key_size, std::forward<M>(obj));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TSL_AH_HAS_STRING_VIEW
|
||||||
|
template<class... Args>
|
||||||
|
std::pair<iterator, bool> emplace(const std::basic_string_view<CharT>& key, Args&&... args) {
|
||||||
|
return m_ht.emplace(key.data(), key.size(), std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
template<class... Args>
|
||||||
|
std::pair<iterator, bool> emplace(const CharT* key, Args&&... args) {
|
||||||
|
return m_ht.emplace(key, std::char_traits<CharT>::length(key), std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class... Args>
|
||||||
|
std::pair<iterator, bool> emplace(const std::basic_string<CharT>& key, Args&&... args) {
|
||||||
|
return m_ht.emplace(key.data(), key.size(), std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
template<class... Args>
|
||||||
|
std::pair<iterator, bool> emplace_ks(const CharT* key, size_type key_size, Args&&... args) {
|
||||||
|
return m_ht.emplace(key, key_size, std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Erase has an amortized O(1) runtime complexity, but even if it removes the key immediately,
|
||||||
|
* it doesn't do the same for the associated value T.
|
||||||
|
*
|
||||||
|
* T will only be removed when the ratio between the size of the map and
|
||||||
|
* the size of the map + the number of deleted values still stored is low enough.
|
||||||
|
*
|
||||||
|
* To force the deletion you can call shrink_to_fit.
|
||||||
|
*/
|
||||||
|
iterator erase(const_iterator pos) { return m_ht.erase(pos); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc erase(const_iterator pos)
|
||||||
|
*/
|
||||||
|
iterator erase(const_iterator first, const_iterator last) { return m_ht.erase(first, last); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TSL_AH_HAS_STRING_VIEW
|
||||||
|
/**
|
||||||
|
* @copydoc erase(const_iterator pos)
|
||||||
|
*/
|
||||||
|
size_type erase(const std::basic_string_view<CharT>& key) {
|
||||||
|
return m_ht.erase(key.data(), key.size());
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/**
|
||||||
|
* @copydoc erase(const_iterator pos)
|
||||||
|
*/
|
||||||
|
size_type erase(const CharT* key) {
|
||||||
|
return m_ht.erase(key, std::char_traits<CharT>::length(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc erase(const_iterator pos)
|
||||||
|
*/
|
||||||
|
size_type erase(const std::basic_string<CharT>& key) {
|
||||||
|
return m_ht.erase(key.data(), key.size());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/**
|
||||||
|
* @copydoc erase(const_iterator pos)
|
||||||
|
*/
|
||||||
|
size_type erase_ks(const CharT* key, size_type key_size) {
|
||||||
|
return m_ht.erase(key, key_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TSL_AH_HAS_STRING_VIEW
|
||||||
|
/**
|
||||||
|
* @copydoc erase_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash)
|
||||||
|
*/
|
||||||
|
size_type erase(const std::basic_string_view<CharT>& key, std::size_t precalculated_hash) {
|
||||||
|
return m_ht.erase(key.data(), key.size(), precalculated_hash);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/**
|
||||||
|
* @copydoc erase_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash)
|
||||||
|
*/
|
||||||
|
size_type erase(const CharT* key, std::size_t precalculated_hash) {
|
||||||
|
return m_ht.erase(key, std::char_traits<CharT>::length(key), precalculated_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc erase_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash)
|
||||||
|
*/
|
||||||
|
size_type erase(const std::basic_string<CharT>& key, std::size_t precalculated_hash) {
|
||||||
|
return m_ht.erase(key.data(), key.size(), precalculated_hash);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/**
|
||||||
|
* @copydoc erase(const_iterator pos)
|
||||||
|
*
|
||||||
|
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||||
|
* as hash_function()(key). Useful to speed-up the lookup to the value if you already have the hash.
|
||||||
|
*/
|
||||||
|
size_type erase_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash) {
|
||||||
|
return m_ht.erase(key, key_size, precalculated_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void swap(array_map& other) { other.m_ht.swap(m_ht); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Lookup
|
||||||
|
*/
|
||||||
|
#ifdef TSL_AH_HAS_STRING_VIEW
|
||||||
|
T& at(const std::basic_string_view<CharT>& key) {
|
||||||
|
return m_ht.at(key.data(), key.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
const T& at(const std::basic_string_view<CharT>& key) const {
|
||||||
|
return m_ht.at(key.data(), key.size());
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
T& at(const CharT* key) {
|
||||||
|
return m_ht.at(key, std::char_traits<CharT>::length(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
const T& at(const CharT* key) const {
|
||||||
|
return m_ht.at(key, std::char_traits<CharT>::length(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
T& at(const std::basic_string<CharT>& key) {
|
||||||
|
return m_ht.at(key.data(), key.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
const T& at(const std::basic_string<CharT>& key) const {
|
||||||
|
return m_ht.at(key.data(), key.size());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
T& at_ks(const CharT* key, size_type key_size) {
|
||||||
|
return m_ht.at(key, key_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
const T& at_ks(const CharT* key, size_type key_size) const {
|
||||||
|
return m_ht.at(key, key_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TSL_AH_HAS_STRING_VIEW
|
||||||
|
/**
|
||||||
|
* @copydoc at_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash)
|
||||||
|
*/
|
||||||
|
T& at(const std::basic_string_view<CharT>& key, std::size_t precalculated_hash) {
|
||||||
|
return m_ht.at(key.data(), key.size(), precalculated_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc at_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash)
|
||||||
|
*/
|
||||||
|
const T& at(const std::basic_string_view<CharT>& key, std::size_t precalculated_hash) const {
|
||||||
|
return m_ht.at(key.data(), key.size(), precalculated_hash);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/**
|
||||||
|
* @copydoc at_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash)
|
||||||
|
*/
|
||||||
|
T& at(const CharT* key, std::size_t precalculated_hash) {
|
||||||
|
return m_ht.at(key, std::char_traits<CharT>::length(key), precalculated_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc at_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash)
|
||||||
|
*/
|
||||||
|
const T& at(const CharT* key, std::size_t precalculated_hash) const {
|
||||||
|
return m_ht.at(key, std::char_traits<CharT>::length(key), precalculated_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc at_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash)
|
||||||
|
*/
|
||||||
|
T& at(const std::basic_string<CharT>& key, std::size_t precalculated_hash) {
|
||||||
|
return m_ht.at(key.data(), key.size(), precalculated_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc at_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash)
|
||||||
|
*/
|
||||||
|
const T& at(const std::basic_string<CharT>& key, std::size_t precalculated_hash) const {
|
||||||
|
return m_ht.at(key.data(), key.size(), precalculated_hash);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/**
|
||||||
|
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||||
|
* as hash_function()(key). Useful to speed-up the lookup to the value if you already have the hash.
|
||||||
|
*/
|
||||||
|
T& at_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash) {
|
||||||
|
return m_ht.at(key, key_size, precalculated_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc at_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash)
|
||||||
|
*/
|
||||||
|
const T& at_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash) const {
|
||||||
|
return m_ht.at(key, key_size, precalculated_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TSL_AH_HAS_STRING_VIEW
|
||||||
|
T& operator[](const std::basic_string_view<CharT>& key) { return m_ht.access_operator(key.data(), key.size()); }
|
||||||
|
#else
|
||||||
|
T& operator[](const CharT* key) { return m_ht.access_operator(key, std::char_traits<CharT>::length(key)); }
|
||||||
|
T& operator[](const std::basic_string<CharT>& key) { return m_ht.access_operator(key.data(), key.size()); }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TSL_AH_HAS_STRING_VIEW
|
||||||
|
size_type count(const std::basic_string_view<CharT>& key) const {
|
||||||
|
return m_ht.count(key.data(), key.size());
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
size_type count(const CharT* key) const {
|
||||||
|
return m_ht.count(key, std::char_traits<CharT>::length(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
size_type count(const std::basic_string<CharT>& key) const {
|
||||||
|
return m_ht.count(key.data(), key.size());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
size_type count_ks(const CharT* key, size_type key_size) const {
|
||||||
|
return m_ht.count(key, key_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TSL_AH_HAS_STRING_VIEW
|
||||||
|
/**
|
||||||
|
* @copydoc count_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash) const
|
||||||
|
*/
|
||||||
|
size_type count(const std::basic_string_view<CharT>& key, std::size_t precalculated_hash) const {
|
||||||
|
return m_ht.count(key.data(), key.size(), precalculated_hash);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/**
|
||||||
|
* @copydoc count_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash) const
|
||||||
|
*/
|
||||||
|
size_type count(const CharT* key, std::size_t precalculated_hash) const {
|
||||||
|
return m_ht.count(key, std::char_traits<CharT>::length(key), precalculated_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc count_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash) const
|
||||||
|
*/
|
||||||
|
size_type count(const std::basic_string<CharT>& key, std::size_t precalculated_hash) const {
|
||||||
|
return m_ht.count(key.data(), key.size(), precalculated_hash);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/**
|
||||||
|
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||||
|
* as hash_function()(key). Useful to speed-up the lookup to the value if you already have the hash.
|
||||||
|
*/
|
||||||
|
size_type count_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash) const {
|
||||||
|
return m_ht.count(key, key_size, precalculated_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TSL_AH_HAS_STRING_VIEW
|
||||||
|
iterator find(const std::basic_string_view<CharT>& key) {
|
||||||
|
return m_ht.find(key.data(), key.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator find(const std::basic_string_view<CharT>& key) const {
|
||||||
|
return m_ht.find(key.data(), key.size());
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
iterator find(const CharT* key) {
|
||||||
|
return m_ht.find(key, std::char_traits<CharT>::length(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator find(const CharT* key) const {
|
||||||
|
return m_ht.find(key, std::char_traits<CharT>::length(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator find(const std::basic_string<CharT>& key) {
|
||||||
|
return m_ht.find(key.data(), key.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator find(const std::basic_string<CharT>& key) const {
|
||||||
|
return m_ht.find(key.data(), key.size());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
iterator find_ks(const CharT* key, size_type key_size) {
|
||||||
|
return m_ht.find(key, key_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator find_ks(const CharT* key, size_type key_size) const {
|
||||||
|
return m_ht.find(key, key_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TSL_AH_HAS_STRING_VIEW
|
||||||
|
/**
|
||||||
|
* @copydoc find_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash)
|
||||||
|
*/
|
||||||
|
iterator find(const std::basic_string_view<CharT>& key, std::size_t precalculated_hash) {
|
||||||
|
return m_ht.find(key.data(), key.size(), precalculated_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc find_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash)
|
||||||
|
*/
|
||||||
|
const_iterator find(const std::basic_string_view<CharT>& key, std::size_t precalculated_hash) const {
|
||||||
|
return m_ht.find(key.data(), key.size(), precalculated_hash);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/**
|
||||||
|
* @copydoc find_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash)
|
||||||
|
*/
|
||||||
|
iterator find(const CharT* key, std::size_t precalculated_hash) {
|
||||||
|
return m_ht.find(key, std::char_traits<CharT>::length(key), precalculated_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc find_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash)
|
||||||
|
*/
|
||||||
|
const_iterator find(const CharT* key, std::size_t precalculated_hash) const {
|
||||||
|
return m_ht.find(key, std::char_traits<CharT>::length(key), precalculated_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc find_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash)
|
||||||
|
*/
|
||||||
|
iterator find(const std::basic_string<CharT>& key, std::size_t precalculated_hash) {
|
||||||
|
return m_ht.find(key.data(), key.size(), precalculated_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc find_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash)
|
||||||
|
*/
|
||||||
|
const_iterator find(const std::basic_string<CharT>& key, std::size_t precalculated_hash) const {
|
||||||
|
return m_ht.find(key.data(), key.size(), precalculated_hash);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/**
|
||||||
|
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||||
|
* as hash_function()(key). Useful to speed-up the lookup to the value if you already have the hash.
|
||||||
|
*/
|
||||||
|
iterator find_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash) {
|
||||||
|
return m_ht.find(key, key_size, precalculated_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc find_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash)
|
||||||
|
*/
|
||||||
|
const_iterator find_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash) const {
|
||||||
|
return m_ht.find(key, key_size, precalculated_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TSL_AH_HAS_STRING_VIEW
|
||||||
|
std::pair<iterator, iterator> equal_range(const std::basic_string_view<CharT>& key) {
|
||||||
|
return m_ht.equal_range(key.data(), key.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<const_iterator, const_iterator> equal_range(const std::basic_string_view<CharT>& key) const {
|
||||||
|
return m_ht.equal_range(key.data(), key.size());
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
std::pair<iterator, iterator> equal_range(const CharT* key) {
|
||||||
|
return m_ht.equal_range(key, std::char_traits<CharT>::length(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<const_iterator, const_iterator> equal_range(const CharT* key) const {
|
||||||
|
return m_ht.equal_range(key, std::char_traits<CharT>::length(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<iterator, iterator> equal_range(const std::basic_string<CharT>& key) {
|
||||||
|
return m_ht.equal_range(key.data(), key.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<const_iterator, const_iterator> equal_range(const std::basic_string<CharT>& key) const {
|
||||||
|
return m_ht.equal_range(key.data(), key.size());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
std::pair<iterator, iterator> equal_range_ks(const CharT* key, size_type key_size) {
|
||||||
|
return m_ht.equal_range(key, key_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<const_iterator, const_iterator> equal_range_ks(const CharT* key, size_type key_size) const {
|
||||||
|
return m_ht.equal_range(key, key_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TSL_AH_HAS_STRING_VIEW
|
||||||
|
/**
|
||||||
|
* @copydoc equal_range_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash)
|
||||||
|
*/
|
||||||
|
std::pair<iterator, iterator> equal_range(const std::basic_string_view<CharT>& key, std::size_t precalculated_hash) {
|
||||||
|
return m_ht.equal_range(key.data(), key.size(), precalculated_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc equal_range_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash)
|
||||||
|
*/
|
||||||
|
std::pair<const_iterator, const_iterator> equal_range(const std::basic_string_view<CharT>& key, std::size_t precalculated_hash) const {
|
||||||
|
return m_ht.equal_range(key.data(), key.size(), precalculated_hash);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/**
|
||||||
|
* @copydoc equal_range_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash)
|
||||||
|
*/
|
||||||
|
std::pair<iterator, iterator> equal_range(const CharT* key, std::size_t precalculated_hash) {
|
||||||
|
return m_ht.equal_range(key, std::char_traits<CharT>::length(key), precalculated_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc equal_range_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash)
|
||||||
|
*/
|
||||||
|
std::pair<const_iterator, const_iterator> equal_range(const CharT* key, std::size_t precalculated_hash) const {
|
||||||
|
return m_ht.equal_range(key, std::char_traits<CharT>::length(key), precalculated_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc equal_range_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash)
|
||||||
|
*/
|
||||||
|
std::pair<iterator, iterator> equal_range(const std::basic_string<CharT>& key, std::size_t precalculated_hash) {
|
||||||
|
return m_ht.equal_range(key.data(), key.size(), precalculated_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc equal_range_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash)
|
||||||
|
*/
|
||||||
|
std::pair<const_iterator, const_iterator> equal_range(const std::basic_string<CharT>& key, std::size_t precalculated_hash) const {
|
||||||
|
return m_ht.equal_range(key.data(), key.size(), precalculated_hash);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/**
|
||||||
|
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||||
|
* as hash_function()(key). Useful to speed-up the lookup to the value if you already have the hash.
|
||||||
|
*/
|
||||||
|
std::pair<iterator, iterator> equal_range_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash) {
|
||||||
|
return m_ht.equal_range(key, key_size, precalculated_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc equal_range_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash)
|
||||||
|
*/
|
||||||
|
std::pair<const_iterator, const_iterator> equal_range_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash) const {
|
||||||
|
return m_ht.equal_range(key, key_size, precalculated_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Bucket interface
|
||||||
|
*/
|
||||||
|
size_type bucket_count() const { return m_ht.bucket_count(); }
|
||||||
|
size_type max_bucket_count() const { return m_ht.max_bucket_count(); }
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Hash policy
|
||||||
|
*/
|
||||||
|
float load_factor() const { return m_ht.load_factor(); }
|
||||||
|
float max_load_factor() const { return m_ht.max_load_factor(); }
|
||||||
|
void max_load_factor(float ml) { m_ht.max_load_factor(ml); }
|
||||||
|
|
||||||
|
void rehash(size_type count) { m_ht.rehash(count); }
|
||||||
|
void reserve(size_type count) { m_ht.reserve(count); }
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Observers
|
||||||
|
*/
|
||||||
|
hasher hash_function() const { return m_ht.hash_function(); }
|
||||||
|
key_equal key_eq() const { return m_ht.key_eq(); }
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Other
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Return the `const_iterator it` as an `iterator`.
|
||||||
|
*/
|
||||||
|
iterator mutable_iterator(const_iterator it) noexcept { return m_ht.mutable_iterator(it); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize the map through the `serializer` parameter.
|
||||||
|
*
|
||||||
|
* The `serializer` parameter must be a function object that supports the following calls:
|
||||||
|
* - `template<typename U> void operator()(const U& value);` where the types `std::uint64_t`, `float` and `T` must be supported for U.
|
||||||
|
* - `void operator()(const CharT* value, std::size_t value_size);`
|
||||||
|
*
|
||||||
|
* The implementation leaves binary compatibility (endianness, IEEE 754 for floats, ...) of the types it serializes
|
||||||
|
* in the hands of the `Serializer` function object if compatibility is required.
|
||||||
|
*/
|
||||||
|
template<class Serializer>
|
||||||
|
void serialize(Serializer& serializer) const {
|
||||||
|
m_ht.serialize(serializer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deserialize a previously serialized map through the `deserializer` parameter.
|
||||||
|
*
|
||||||
|
* The `deserializer` parameter must be a function object that supports the following calls:
|
||||||
|
* - `template<typename U> U operator()();` where the types `std::uint64_t`, `float` and `T` must be supported for U.
|
||||||
|
* - `void operator()(CharT* value_out, std::size_t value_size);`
|
||||||
|
*
|
||||||
|
* If the deserialized hash map type is hash compatible with the serialized map, the deserialization process can be
|
||||||
|
* sped up by setting `hash_compatible` to true. To be hash compatible, the Hash (take care of the 32-bits vs 64 bits),
|
||||||
|
* KeyEqual, GrowthPolicy, StoreNullTerminator, KeySizeT and IndexSizeT must behave the same than the ones used on the
|
||||||
|
* serialized map. Otherwise the behaviour is undefined with `hash_compatible` sets to true.
|
||||||
|
*
|
||||||
|
* The behaviour is undefined if the type `CharT` and `T` of the `array_map` are not the same as the
|
||||||
|
* types used during serialization.
|
||||||
|
*
|
||||||
|
* The implementation leaves binary compatibility (endianness, IEEE 754 for floats, size of int, ...) of the types it
|
||||||
|
* deserializes in the hands of the `Deserializer` function object if compatibility is required.
|
||||||
|
*/
|
||||||
|
template<class Deserializer>
|
||||||
|
static array_map deserialize(Deserializer& deserializer, bool hash_compatible = false) {
|
||||||
|
array_map map(0);
|
||||||
|
map.m_ht.deserialize(deserializer, hash_compatible);
|
||||||
|
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool operator==(const array_map& lhs, const array_map& rhs) {
|
||||||
|
if(lhs.size() != rhs.size()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto it = lhs.cbegin(); it != lhs.cend(); ++it) {
|
||||||
|
const auto it_element_rhs = rhs.find_ks(it.key(), it.key_size());
|
||||||
|
if(it_element_rhs == rhs.cend() || it.value() != it_element_rhs.value()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool operator!=(const array_map& lhs, const array_map& rhs) {
|
||||||
|
return !operator==(lhs, rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
friend void swap(array_map& lhs, array_map& rhs) {
|
||||||
|
lhs.swap(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
template<class U, class V>
|
||||||
|
void insert_pair(const std::pair<U, V>& value) {
|
||||||
|
insert(value.first, value.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class U, class V>
|
||||||
|
void insert_pair(std::pair<U, V>&& value) {
|
||||||
|
insert(value.first, std::move(value.second));
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
static const size_type MAX_KEY_SIZE = ht::MAX_KEY_SIZE;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ht m_ht;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as
|
||||||
|
* `tsl::array_map<CharT, T, Hash, KeyEqual, StoreNullTerminator, KeySizeT, IndexSizeT, tsl::ah::prime_growth_policy>`.
|
||||||
|
*/
|
||||||
|
template<class CharT,
|
||||||
|
class T,
|
||||||
|
class Hash = tsl::ah::str_hash<CharT>,
|
||||||
|
class KeyEqual = tsl::ah::str_equal<CharT>,
|
||||||
|
bool StoreNullTerminator = true,
|
||||||
|
class KeySizeT = std::uint16_t,
|
||||||
|
class IndexSizeT = std::uint32_t>
|
||||||
|
using array_pg_map = array_map<CharT, T, Hash, KeyEqual, StoreNullTerminator,
|
||||||
|
KeySizeT, IndexSizeT, tsl::ah::prime_growth_policy>;
|
||||||
|
|
||||||
|
} //end namespace tsl
|
||||||
|
|
||||||
|
#endif
|
||||||
664
ios/include/tsl/array-hash/array_set.h
Normal file
664
ios/include/tsl/array-hash/array_set.h
Normal file
@@ -0,0 +1,664 @@
|
|||||||
|
/**
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017 Thibaut Goetghebuer-Planchon <tessil@gmx.com>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
#ifndef TSL_ARRAY_SET_H
|
||||||
|
#define TSL_ARRAY_SET_H
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <initializer_list>
|
||||||
|
#include <iterator>
|
||||||
|
#include <string>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <utility>
|
||||||
|
#include "array_hash.h"
|
||||||
|
|
||||||
|
namespace tsl {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of a cache-conscious string hash set.
|
||||||
|
*
|
||||||
|
* The set stores the strings as `const CharT*`. If `StoreNullTerminator` is true,
|
||||||
|
* the strings are stored with the a null-terminator (the `key()` method of the iterators
|
||||||
|
* will return a pointer to this null-terminated string). Otherwise the null character
|
||||||
|
* is not stored (which allow an economy of 1 byte per string).
|
||||||
|
*
|
||||||
|
* The size of a key string is limited to `std::numeric_limits<KeySizeT>::max() - 1`.
|
||||||
|
* That is 65 535 characters by default, but can be raised with the `KeySizeT` template parameter.
|
||||||
|
* See `max_key_size()` for an easy access to this limit.
|
||||||
|
*
|
||||||
|
* The number of elements in the set is limited to `std::numeric_limits<IndexSizeT>::max()`.
|
||||||
|
* That is 4 294 967 296 elements, but can be raised with the `IndexSizeT` template parameter.
|
||||||
|
* See `max_size()` for an easy access to this limit.
|
||||||
|
*
|
||||||
|
* Iterators invalidation:
|
||||||
|
* - clear, operator=: always invalidate the iterators.
|
||||||
|
* - insert, emplace, operator[]: always invalidate the iterators.
|
||||||
|
* - erase: always invalidate the iterators.
|
||||||
|
* - shrink_to_fit: always invalidate the iterators.
|
||||||
|
*/
|
||||||
|
template<class CharT,
|
||||||
|
class Hash = tsl::ah::str_hash<CharT>,
|
||||||
|
class KeyEqual = tsl::ah::str_equal<CharT>,
|
||||||
|
bool StoreNullTerminator = true,
|
||||||
|
class KeySizeT = std::uint16_t,
|
||||||
|
class IndexSizeT = std::uint32_t,
|
||||||
|
class GrowthPolicy = tsl::ah::power_of_two_growth_policy<2>>
|
||||||
|
class array_set {
|
||||||
|
private:
|
||||||
|
template<typename U>
|
||||||
|
using is_iterator = tsl::detail_array_hash::is_iterator<U>;
|
||||||
|
|
||||||
|
using ht = tsl::detail_array_hash::array_hash<CharT, void, Hash, KeyEqual, StoreNullTerminator,
|
||||||
|
KeySizeT, IndexSizeT, GrowthPolicy>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using char_type = typename ht::char_type;
|
||||||
|
using key_size_type = typename ht::key_size_type;
|
||||||
|
using index_size_type = typename ht::index_size_type;
|
||||||
|
using size_type = typename ht::size_type;
|
||||||
|
using hasher = typename ht::hasher;
|
||||||
|
using key_equal = typename ht::key_equal;
|
||||||
|
using iterator = typename ht::iterator;
|
||||||
|
using const_iterator = typename ht::const_iterator;
|
||||||
|
|
||||||
|
array_set(): array_set(ht::DEFAULT_INIT_BUCKET_COUNT) {
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit array_set(size_type bucket_count,
|
||||||
|
const Hash& hash = Hash()): m_ht(bucket_count, hash, ht::DEFAULT_MAX_LOAD_FACTOR)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class InputIt, typename std::enable_if<is_iterator<InputIt>::value>::type* = nullptr>
|
||||||
|
array_set(InputIt first, InputIt last,
|
||||||
|
size_type bucket_count = ht::DEFAULT_INIT_BUCKET_COUNT,
|
||||||
|
const Hash& hash = Hash()): array_set(bucket_count, hash)
|
||||||
|
{
|
||||||
|
insert(first, last);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TSL_AH_HAS_STRING_VIEW
|
||||||
|
array_set(std::initializer_list<std::basic_string_view<CharT>> init,
|
||||||
|
size_type bucket_count = ht::DEFAULT_INIT_BUCKET_COUNT,
|
||||||
|
const Hash& hash = Hash()): array_set(bucket_count, hash)
|
||||||
|
{
|
||||||
|
insert(init);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
array_set(std::initializer_list<const CharT*> init,
|
||||||
|
size_type bucket_count = ht::DEFAULT_INIT_BUCKET_COUNT,
|
||||||
|
const Hash& hash = Hash()): array_set(bucket_count, hash)
|
||||||
|
{
|
||||||
|
insert(init);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TSL_AH_HAS_STRING_VIEW
|
||||||
|
array_set& operator=(std::initializer_list<std::basic_string_view<CharT>> ilist) {
|
||||||
|
clear();
|
||||||
|
|
||||||
|
reserve(ilist.size());
|
||||||
|
insert(ilist);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
array_set& operator=(std::initializer_list<const CharT*> ilist) {
|
||||||
|
clear();
|
||||||
|
|
||||||
|
reserve(ilist.size());
|
||||||
|
insert(ilist);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Iterators
|
||||||
|
*/
|
||||||
|
iterator begin() noexcept { return m_ht.begin(); }
|
||||||
|
const_iterator begin() const noexcept { return m_ht.begin(); }
|
||||||
|
const_iterator cbegin() const noexcept { return m_ht.cbegin(); }
|
||||||
|
|
||||||
|
iterator end() noexcept { return m_ht.end(); }
|
||||||
|
const_iterator end() const noexcept { return m_ht.end(); }
|
||||||
|
const_iterator cend() const noexcept { return m_ht.cend(); }
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Capacity
|
||||||
|
*/
|
||||||
|
bool empty() const noexcept { return m_ht.empty(); }
|
||||||
|
size_type size() const noexcept { return m_ht.size(); }
|
||||||
|
size_type max_size() const noexcept { return m_ht.max_size(); }
|
||||||
|
size_type max_key_size() const noexcept { return m_ht.max_key_size(); }
|
||||||
|
void shrink_to_fit() { m_ht.shrink_to_fit(); }
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Modifiers
|
||||||
|
*/
|
||||||
|
void clear() noexcept { m_ht.clear(); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TSL_AH_HAS_STRING_VIEW
|
||||||
|
std::pair<iterator, bool> insert(const std::basic_string_view<CharT>& key) {
|
||||||
|
return m_ht.emplace(key.data(), key.size());
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
std::pair<iterator, bool> insert(const CharT* key) {
|
||||||
|
return m_ht.emplace(key, std::char_traits<CharT>::length(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<iterator, bool> insert(const std::basic_string<CharT>& key) {
|
||||||
|
return m_ht.emplace(key.data(), key.size());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
std::pair<iterator, bool> insert_ks(const CharT* key, size_type key_size) {
|
||||||
|
return m_ht.emplace(key, key_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template<class InputIt, typename std::enable_if<is_iterator<InputIt>::value>::type* = nullptr>
|
||||||
|
void insert(InputIt first, InputIt last) {
|
||||||
|
if(std::is_base_of<std::forward_iterator_tag,
|
||||||
|
typename std::iterator_traits<InputIt>::iterator_category>::value)
|
||||||
|
{
|
||||||
|
const auto nb_elements_insert = std::distance(first, last);
|
||||||
|
const std::size_t nb_free_buckets = std::size_t(float(bucket_count())*max_load_factor()) - size();
|
||||||
|
|
||||||
|
if(nb_elements_insert > 0 && nb_free_buckets < std::size_t(nb_elements_insert)) {
|
||||||
|
reserve(size() + std::size_t(nb_elements_insert));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto it = first; it != last; ++it) {
|
||||||
|
insert(*it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TSL_AH_HAS_STRING_VIEW
|
||||||
|
void insert(std::initializer_list<std::basic_string_view<CharT>> ilist) {
|
||||||
|
insert(ilist.begin(), ilist.end());
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void insert(std::initializer_list<const CharT*> ilist) {
|
||||||
|
insert(ilist.begin(), ilist.end());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TSL_AH_HAS_STRING_VIEW
|
||||||
|
/**
|
||||||
|
* @copydoc emplace_ks(const CharT* key, size_type key_size)
|
||||||
|
*/
|
||||||
|
std::pair<iterator, bool> emplace(const std::basic_string_view<CharT>& key) {
|
||||||
|
return m_ht.emplace(key.data(), key.size());
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/**
|
||||||
|
* @copydoc emplace_ks(const CharT* key, size_type key_size)
|
||||||
|
*/
|
||||||
|
std::pair<iterator, bool> emplace(const CharT* key) {
|
||||||
|
return m_ht.emplace(key, std::char_traits<CharT>::length(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc emplace_ks(const CharT* key, size_type key_size)
|
||||||
|
*/
|
||||||
|
std::pair<iterator, bool> emplace(const std::basic_string<CharT>& key) {
|
||||||
|
return m_ht.emplace(key.data(), key.size());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/**
|
||||||
|
* No difference compared to the insert method. Mainly here for coherence with array_map.
|
||||||
|
*/
|
||||||
|
std::pair<iterator, bool> emplace_ks(const CharT* key, size_type key_size) {
|
||||||
|
return m_ht.emplace(key, key_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
iterator erase(const_iterator pos) { return m_ht.erase(pos); }
|
||||||
|
iterator erase(const_iterator first, const_iterator last) { return m_ht.erase(first, last); }
|
||||||
|
|
||||||
|
#ifdef TSL_AH_HAS_STRING_VIEW
|
||||||
|
size_type erase(const std::basic_string_view<CharT>& key) {
|
||||||
|
return m_ht.erase(key.data(), key.size());
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
size_type erase(const CharT* key) {
|
||||||
|
return m_ht.erase(key, std::char_traits<CharT>::length(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
size_type erase(const std::basic_string<CharT>& key) {
|
||||||
|
return m_ht.erase(key.data(), key.size());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
size_type erase_ks(const CharT* key, size_type key_size) {
|
||||||
|
return m_ht.erase(key, key_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TSL_AH_HAS_STRING_VIEW
|
||||||
|
/**
|
||||||
|
* @copydoc erase_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash)
|
||||||
|
*/
|
||||||
|
size_type erase(const std::basic_string_view<CharT>& key, std::size_t precalculated_hash) {
|
||||||
|
return m_ht.erase(key.data(), key.size(), precalculated_hash);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/**
|
||||||
|
* @copydoc erase_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash)
|
||||||
|
*/
|
||||||
|
size_type erase(const CharT* key, std::size_t precalculated_hash) {
|
||||||
|
return m_ht.erase(key, std::char_traits<CharT>::length(key), precalculated_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc erase_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash)
|
||||||
|
*/
|
||||||
|
size_type erase(const std::basic_string<CharT>& key, std::size_t precalculated_hash) {
|
||||||
|
return m_ht.erase(key.data(), key.size(), precalculated_hash);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/**
|
||||||
|
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||||
|
* as hash_function()(key). Useful to speed-up the lookup to the value if you already have the hash.
|
||||||
|
*/
|
||||||
|
size_type erase_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash) {
|
||||||
|
return m_ht.erase(key, key_size, precalculated_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void swap(array_set& other) { other.m_ht.swap(m_ht); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Lookup
|
||||||
|
*/
|
||||||
|
#ifdef TSL_AH_HAS_STRING_VIEW
|
||||||
|
size_type count(const std::basic_string_view<CharT>& key) const { return m_ht.count(key.data(), key.size()); }
|
||||||
|
#else
|
||||||
|
size_type count(const CharT* key) const { return m_ht.count(key, std::char_traits<CharT>::length(key)); }
|
||||||
|
size_type count(const std::basic_string<CharT>& key) const { return m_ht.count(key.data(), key.size()); }
|
||||||
|
#endif
|
||||||
|
size_type count_ks(const CharT* key, size_type key_size) const { return m_ht.count(key, key_size); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TSL_AH_HAS_STRING_VIEW
|
||||||
|
/**
|
||||||
|
* @copydoc count_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash) const
|
||||||
|
*/
|
||||||
|
size_type count(const std::basic_string_view<CharT>& key, std::size_t precalculated_hash) const {
|
||||||
|
return m_ht.count(key.data(), key.size(), precalculated_hash);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/**
|
||||||
|
* @copydoc count_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash) const
|
||||||
|
*/
|
||||||
|
size_type count(const CharT* key, std::size_t precalculated_hash) const {
|
||||||
|
return m_ht.count(key, std::char_traits<CharT>::length(key), precalculated_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc count_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash) const
|
||||||
|
*/
|
||||||
|
size_type count(const std::basic_string<CharT>& key, std::size_t precalculated_hash) const {
|
||||||
|
return m_ht.count(key.data(), key.size(), precalculated_hash);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/**
|
||||||
|
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||||
|
* as hash_function()(key). Useful to speed-up the lookup to the value if you already have the hash.
|
||||||
|
*/
|
||||||
|
size_type count_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash) const {
|
||||||
|
return m_ht.count(key, key_size, precalculated_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TSL_AH_HAS_STRING_VIEW
|
||||||
|
iterator find(const std::basic_string_view<CharT>& key) {
|
||||||
|
return m_ht.find(key.data(), key.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator find(const std::basic_string_view<CharT>& key) const {
|
||||||
|
return m_ht.find(key.data(), key.size());
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
iterator find(const CharT* key) {
|
||||||
|
return m_ht.find(key, std::char_traits<CharT>::length(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator find(const CharT* key) const {
|
||||||
|
return m_ht.find(key, std::char_traits<CharT>::length(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator find(const std::basic_string<CharT>& key) {
|
||||||
|
return m_ht.find(key.data(), key.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator find(const std::basic_string<CharT>& key) const {
|
||||||
|
return m_ht.find(key.data(), key.size());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
iterator find_ks(const CharT* key, size_type key_size) {
|
||||||
|
return m_ht.find(key, key_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator find_ks(const CharT* key, size_type key_size) const {
|
||||||
|
return m_ht.find(key, key_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TSL_AH_HAS_STRING_VIEW
|
||||||
|
/**
|
||||||
|
* @copydoc find_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash)
|
||||||
|
*/
|
||||||
|
iterator find(const std::basic_string_view<CharT>& key, std::size_t precalculated_hash) {
|
||||||
|
return m_ht.find(key.data(), key.size(), precalculated_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc find_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash)
|
||||||
|
*/
|
||||||
|
const_iterator find(const std::basic_string_view<CharT>& key, std::size_t precalculated_hash) const {
|
||||||
|
return m_ht.find(key.data(), key.size(), precalculated_hash);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/**
|
||||||
|
* @copydoc find_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash)
|
||||||
|
*/
|
||||||
|
iterator find(const CharT* key, std::size_t precalculated_hash) {
|
||||||
|
return m_ht.find(key, std::char_traits<CharT>::length(key), precalculated_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc find_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash)
|
||||||
|
*/
|
||||||
|
const_iterator find(const CharT* key, std::size_t precalculated_hash) const {
|
||||||
|
return m_ht.find(key, std::char_traits<CharT>::length(key), precalculated_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc find_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash)
|
||||||
|
*/
|
||||||
|
iterator find(const std::basic_string<CharT>& key, std::size_t precalculated_hash) {
|
||||||
|
return m_ht.find(key.data(), key.size(), precalculated_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc find_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash)
|
||||||
|
*/
|
||||||
|
const_iterator find(const std::basic_string<CharT>& key, std::size_t precalculated_hash) const {
|
||||||
|
return m_ht.find(key.data(), key.size(), precalculated_hash);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/**
|
||||||
|
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||||
|
* as hash_function()(key). Useful to speed-up the lookup to the value if you already have the hash.
|
||||||
|
*/
|
||||||
|
iterator find_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash) {
|
||||||
|
return m_ht.find(key, key_size, precalculated_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc find_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash)
|
||||||
|
*/
|
||||||
|
const_iterator find_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash) const {
|
||||||
|
return m_ht.find(key, key_size, precalculated_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TSL_AH_HAS_STRING_VIEW
|
||||||
|
std::pair<iterator, iterator> equal_range(const std::basic_string_view<CharT>& key) {
|
||||||
|
return m_ht.equal_range(key.data(), key.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<const_iterator, const_iterator> equal_range(const std::basic_string_view<CharT>& key) const {
|
||||||
|
return m_ht.equal_range(key.data(), key.size());
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
std::pair<iterator, iterator> equal_range(const CharT* key) {
|
||||||
|
return m_ht.equal_range(key, std::char_traits<CharT>::length(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<const_iterator, const_iterator> equal_range(const CharT* key) const {
|
||||||
|
return m_ht.equal_range(key, std::char_traits<CharT>::length(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<iterator, iterator> equal_range(const std::basic_string<CharT>& key) {
|
||||||
|
return m_ht.equal_range(key.data(), key.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<const_iterator, const_iterator> equal_range(const std::basic_string<CharT>& key) const {
|
||||||
|
return m_ht.equal_range(key.data(), key.size());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
std::pair<iterator, iterator> equal_range_ks(const CharT* key, size_type key_size) {
|
||||||
|
return m_ht.equal_range(key, key_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<const_iterator, const_iterator> equal_range_ks(const CharT* key, size_type key_size) const {
|
||||||
|
return m_ht.equal_range(key, key_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TSL_AH_HAS_STRING_VIEW
|
||||||
|
/**
|
||||||
|
* @copydoc equal_range_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash)
|
||||||
|
*/
|
||||||
|
std::pair<iterator, iterator> equal_range(const std::basic_string_view<CharT>& key, std::size_t precalculated_hash) {
|
||||||
|
return m_ht.equal_range(key.data(), key.size(), precalculated_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc equal_range_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash)
|
||||||
|
*/
|
||||||
|
std::pair<const_iterator, const_iterator> equal_range(const std::basic_string_view<CharT>& key, std::size_t precalculated_hash) const {
|
||||||
|
return m_ht.equal_range(key.data(), key.size(), precalculated_hash);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/**
|
||||||
|
* @copydoc equal_range_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash)
|
||||||
|
*/
|
||||||
|
std::pair<iterator, iterator> equal_range(const CharT* key, std::size_t precalculated_hash) {
|
||||||
|
return m_ht.equal_range(key, std::char_traits<CharT>::length(key), precalculated_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc equal_range_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash)
|
||||||
|
*/
|
||||||
|
std::pair<const_iterator, const_iterator> equal_range(const CharT* key, std::size_t precalculated_hash) const {
|
||||||
|
return m_ht.equal_range(key, std::char_traits<CharT>::length(key), precalculated_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc equal_range_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash)
|
||||||
|
*/
|
||||||
|
std::pair<iterator, iterator> equal_range(const std::basic_string<CharT>& key, std::size_t precalculated_hash) {
|
||||||
|
return m_ht.equal_range(key.data(), key.size(), precalculated_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc equal_range_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash)
|
||||||
|
*/
|
||||||
|
std::pair<const_iterator, const_iterator> equal_range(const std::basic_string<CharT>& key, std::size_t precalculated_hash) const {
|
||||||
|
return m_ht.equal_range(key.data(), key.size(), precalculated_hash);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/**
|
||||||
|
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||||
|
* as hash_function()(key). Useful to speed-up the lookup to the value if you already have the hash.
|
||||||
|
*/
|
||||||
|
std::pair<iterator, iterator> equal_range_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash) {
|
||||||
|
return m_ht.equal_range(key, key_size, precalculated_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc equal_range_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash)
|
||||||
|
*/
|
||||||
|
std::pair<const_iterator, const_iterator> equal_range_ks(const CharT* key, size_type key_size, std::size_t precalculated_hash) const {
|
||||||
|
return m_ht.equal_range(key, key_size, precalculated_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Bucket interface
|
||||||
|
*/
|
||||||
|
size_type bucket_count() const { return m_ht.bucket_count(); }
|
||||||
|
size_type max_bucket_count() const { return m_ht.max_bucket_count(); }
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Hash policy
|
||||||
|
*/
|
||||||
|
float load_factor() const { return m_ht.load_factor(); }
|
||||||
|
float max_load_factor() const { return m_ht.max_load_factor(); }
|
||||||
|
void max_load_factor(float ml) { m_ht.max_load_factor(ml); }
|
||||||
|
|
||||||
|
void rehash(size_type count) { m_ht.rehash(count); }
|
||||||
|
void reserve(size_type count) { m_ht.reserve(count); }
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Observers
|
||||||
|
*/
|
||||||
|
hasher hash_function() const { return m_ht.hash_function(); }
|
||||||
|
key_equal key_eq() const { return m_ht.key_eq(); }
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Other
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Return the `const_iterator it` as an `iterator`.
|
||||||
|
*/
|
||||||
|
iterator mutable_iterator(const_iterator it) noexcept { return m_ht.mutable_iterator(it); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize the set through the `serializer` parameter.
|
||||||
|
*
|
||||||
|
* The `serializer` parameter must be a function object that supports the following calls:
|
||||||
|
* - `template<typename U> void operator()(const U& value);` where the types `std::uint64_t` and `float` must be supported for U.
|
||||||
|
* - `void operator()(const CharT* value, std::size_t value_size);`
|
||||||
|
*
|
||||||
|
* The implementation leaves binary compatibility (endianness, IEEE 754 for floats, ...) of the types it serializes
|
||||||
|
* in the hands of the `Serializer` function object if compatibility is required.
|
||||||
|
*/
|
||||||
|
template<class Serializer>
|
||||||
|
void serialize(Serializer& serializer) const {
|
||||||
|
m_ht.serialize(serializer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deserialize a previously serialized set through the `deserializer` parameter.
|
||||||
|
*
|
||||||
|
* The `deserializer` parameter must be a function object that supports the following calls:
|
||||||
|
* - `template<typename U> U operator()();` where the types `std::uint64_t` and `float` must be supported for U.
|
||||||
|
* - `void operator()(CharT* value_out, std::size_t value_size);`
|
||||||
|
*
|
||||||
|
* If the deserialized hash set type is hash compatible with the serialized set, the deserialization process can be
|
||||||
|
* sped up by setting `hash_compatible` to true. To be hash compatible, the Hash (take care of the 32-bits vs 64 bits),
|
||||||
|
* KeyEqual, GrowthPolicy, StoreNullTerminator, KeySizeT and IndexSizeT must behave the same than the ones used on the
|
||||||
|
* serialized set. Otherwise the behaviour is undefined with `hash_compatible` sets to true.
|
||||||
|
*
|
||||||
|
* The behaviour is undefined if the type `CharT` of the `array_set` is not the same as the
|
||||||
|
* type used during serialization.
|
||||||
|
*
|
||||||
|
* The implementation leaves binary compatibility (endianness, IEEE 754 for floats, size of int, ...) of the types it
|
||||||
|
* deserializes in the hands of the `Deserializer` function object if compatibility is required.
|
||||||
|
*/
|
||||||
|
template<class Deserializer>
|
||||||
|
static array_set deserialize(Deserializer& deserializer, bool hash_compatible = false) {
|
||||||
|
array_set set(0);
|
||||||
|
set.m_ht.deserialize(deserializer, hash_compatible);
|
||||||
|
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool operator==(const array_set& lhs, const array_set& rhs) {
|
||||||
|
if(lhs.size() != rhs.size()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto it = lhs.cbegin(); it != lhs.cend(); ++it) {
|
||||||
|
const auto it_element_rhs = rhs.find_ks(it.key(), it.key_size());
|
||||||
|
if(it_element_rhs == rhs.cend()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool operator!=(const array_set& lhs, const array_set& rhs) {
|
||||||
|
return !operator==(lhs, rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
friend void swap(array_set& lhs, array_set& rhs) {
|
||||||
|
lhs.swap(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
static const size_type MAX_KEY_SIZE = ht::MAX_KEY_SIZE;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ht m_ht;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as
|
||||||
|
* `tsl::array_set<CharT, Hash, KeyEqual, StoreNullTerminator, KeySizeT, IndexSizeT, tsl::ah::prime_growth_policy>`.
|
||||||
|
*/
|
||||||
|
template<class CharT,
|
||||||
|
class Hash = tsl::ah::str_hash<CharT>,
|
||||||
|
class KeyEqual = tsl::ah::str_equal<CharT>,
|
||||||
|
bool StoreNullTerminator = true,
|
||||||
|
class KeySizeT = std::uint16_t,
|
||||||
|
class IndexSizeT = std::uint32_t>
|
||||||
|
using array_pg_set = array_set<CharT, Hash, KeyEqual, StoreNullTerminator,
|
||||||
|
KeySizeT, IndexSizeT, tsl::ah::prime_growth_policy>;
|
||||||
|
|
||||||
|
} //end namespace tsl
|
||||||
|
|
||||||
|
#endif
|
||||||
2090
ios/include/tsl/htrie_hash.h
Normal file
2090
ios/include/tsl/htrie_hash.h
Normal file
File diff suppressed because it is too large
Load Diff
647
ios/include/tsl/htrie_map.h
Normal file
647
ios/include/tsl/htrie_map.h
Normal file
@@ -0,0 +1,647 @@
|
|||||||
|
/**
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017 Thibaut Goetghebuer-Planchon <tessil@gmx.com>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
#ifndef TSL_HTRIE_MAP_H
|
||||||
|
#define TSL_HTRIE_MAP_H
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstring>
|
||||||
|
#include <initializer_list>
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
#include "htrie_hash.h"
|
||||||
|
|
||||||
|
namespace tsl {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of a hat-trie map.
|
||||||
|
*
|
||||||
|
* The value T must be either nothrow move-constructible/assignable, copy-constructible or both.
|
||||||
|
*
|
||||||
|
* The size of a key string is limited to std::numeric_limits<KeySizeT>::max() - 1.
|
||||||
|
* That is 65 535 characters by default, but can be raised with the KeySizeT template parameter.
|
||||||
|
* See max_key_size() for an easy access to this limit.
|
||||||
|
*
|
||||||
|
* Iterators invalidation:
|
||||||
|
* - clear, operator=: always invalidate the iterators.
|
||||||
|
* - insert, emplace, operator[]: always invalidate the iterators.
|
||||||
|
* - erase: always invalidate the iterators.
|
||||||
|
*/
|
||||||
|
template<class CharT,
|
||||||
|
class T,
|
||||||
|
class Hash = tsl::ah::str_hash<CharT>,
|
||||||
|
class KeySizeT = std::uint16_t>
|
||||||
|
class htrie_map {
|
||||||
|
private:
|
||||||
|
template<typename U>
|
||||||
|
using is_iterator = tsl::detail_array_hash::is_iterator<U>;
|
||||||
|
|
||||||
|
using ht = tsl::detail_htrie_hash::htrie_hash<CharT, T, Hash, KeySizeT>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using char_type = typename ht::char_type;
|
||||||
|
using mapped_type = T;
|
||||||
|
using key_size_type = typename ht::key_size_type;
|
||||||
|
using size_type = typename ht::size_type;
|
||||||
|
using hasher = typename ht::hasher;
|
||||||
|
using iterator = typename ht::iterator;
|
||||||
|
using const_iterator = typename ht::const_iterator;
|
||||||
|
using prefix_iterator = typename ht::prefix_iterator;
|
||||||
|
using const_prefix_iterator = typename ht::const_prefix_iterator;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit htrie_map(const Hash& hash = Hash()): m_ht(hash, ht::HASH_NODE_DEFAULT_MAX_LOAD_FACTOR,
|
||||||
|
ht::DEFAULT_BURST_THRESHOLD)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit htrie_map(size_type burst_threshold,
|
||||||
|
const Hash& hash = Hash()): m_ht(hash, ht::HASH_NODE_DEFAULT_MAX_LOAD_FACTOR,
|
||||||
|
burst_threshold)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class InputIt, typename std::enable_if<is_iterator<InputIt>::value>::type* = nullptr>
|
||||||
|
htrie_map(InputIt first, InputIt last,
|
||||||
|
const Hash& hash = Hash()): htrie_map(hash)
|
||||||
|
{
|
||||||
|
insert(first, last);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TSL_HT_HAS_STRING_VIEW
|
||||||
|
htrie_map(std::initializer_list<std::pair<std::basic_string_view<CharT>, T>> init,
|
||||||
|
const Hash& hash = Hash()): htrie_map(hash)
|
||||||
|
{
|
||||||
|
insert(init);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
htrie_map(std::initializer_list<std::pair<const CharT*, T>> init,
|
||||||
|
const Hash& hash = Hash()): htrie_map(hash)
|
||||||
|
{
|
||||||
|
insert(init);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TSL_HT_HAS_STRING_VIEW
|
||||||
|
htrie_map& operator=(std::initializer_list<std::pair<std::basic_string_view<CharT>, T>> ilist) {
|
||||||
|
clear();
|
||||||
|
insert(ilist);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
htrie_map& operator=(std::initializer_list<std::pair<const CharT*, T>> ilist) {
|
||||||
|
clear();
|
||||||
|
insert(ilist);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Iterators
|
||||||
|
*/
|
||||||
|
iterator begin() noexcept { return m_ht.begin(); }
|
||||||
|
const_iterator begin() const noexcept { return m_ht.begin(); }
|
||||||
|
const_iterator cbegin() const noexcept { return m_ht.cbegin(); }
|
||||||
|
|
||||||
|
iterator end() noexcept { return m_ht.end(); }
|
||||||
|
const_iterator end() const noexcept { return m_ht.end(); }
|
||||||
|
const_iterator cend() const noexcept { return m_ht.cend(); }
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Capacity
|
||||||
|
*/
|
||||||
|
bool empty() const noexcept { return m_ht.empty(); }
|
||||||
|
size_type size() const noexcept { return m_ht.size(); }
|
||||||
|
size_type max_size() const noexcept { return m_ht.max_size(); }
|
||||||
|
size_type max_key_size() const noexcept { return m_ht.max_key_size(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call shrink_to_fit() on each hash node of the hat-trie to reduce its size.
|
||||||
|
*/
|
||||||
|
void shrink_to_fit() { m_ht.shrink_to_fit(); }
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Modifiers
|
||||||
|
*/
|
||||||
|
void clear() noexcept { m_ht.clear(); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
std::pair<iterator, bool> insert_ks(const CharT* key, size_type key_size, const T& value) {
|
||||||
|
return m_ht.insert(key, key_size, value);
|
||||||
|
}
|
||||||
|
#ifdef TSL_HT_HAS_STRING_VIEW
|
||||||
|
std::pair<iterator, bool> insert(const std::basic_string_view<CharT>& key, const T& value) {
|
||||||
|
return m_ht.insert(key.data(), key.size(), value);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
std::pair<iterator, bool> insert(const CharT* key, const T& value) {
|
||||||
|
return m_ht.insert(key, std::strlen(key), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<iterator, bool> insert(const std::basic_string<CharT>& key, const T& value) {
|
||||||
|
return m_ht.insert(key.data(), key.size(), value);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
std::pair<iterator, bool> insert_ks(const CharT* key, size_type key_size, T&& value) {
|
||||||
|
return m_ht.insert(key, key_size, std::move(value));
|
||||||
|
}
|
||||||
|
#ifdef TSL_HT_HAS_STRING_VIEW
|
||||||
|
std::pair<iterator, bool> insert(const std::basic_string_view<CharT>& key, T&& value) {
|
||||||
|
return m_ht.insert(key.data(), key.size(), std::move(value));
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
std::pair<iterator, bool> insert(const CharT* key, T&& value) {
|
||||||
|
return m_ht.insert(key, std::strlen(key), std::move(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<iterator, bool> insert(const std::basic_string<CharT>& key, T&& value) {
|
||||||
|
return m_ht.insert(key.data(), key.size(), std::move(value));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template<class InputIt, typename std::enable_if<is_iterator<InputIt>::value>::type* = nullptr>
|
||||||
|
void insert(InputIt first, InputIt last) {
|
||||||
|
for(auto it = first; it != last; ++it) {
|
||||||
|
insert_pair(*it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TSL_HT_HAS_STRING_VIEW
|
||||||
|
void insert(std::initializer_list<std::pair<std::basic_string_view<CharT>, T>> ilist) {
|
||||||
|
insert(ilist.begin(), ilist.end());
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void insert(std::initializer_list<std::pair<const CharT*, T>> ilist) {
|
||||||
|
insert(ilist.begin(), ilist.end());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template<class... Args>
|
||||||
|
std::pair<iterator, bool> emplace_ks(const CharT* key, size_type key_size, Args&&... args) {
|
||||||
|
return m_ht.insert(key, key_size, std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
#ifdef TSL_HT_HAS_STRING_VIEW
|
||||||
|
template<class... Args>
|
||||||
|
std::pair<iterator, bool> emplace(const std::basic_string_view<CharT>& key, Args&&... args) {
|
||||||
|
return m_ht.insert(key.data(), key.size(), std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
template<class... Args>
|
||||||
|
std::pair<iterator, bool> emplace(const CharT* key, Args&&... args) {
|
||||||
|
return m_ht.insert(key, std::strlen(key), std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class... Args>
|
||||||
|
std::pair<iterator, bool> emplace(const std::basic_string<CharT>& key, Args&&... args) {
|
||||||
|
return m_ht.insert(key.data(), key.size(), std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
iterator erase(const_iterator pos) { return m_ht.erase(pos); }
|
||||||
|
iterator erase(const_iterator first, const_iterator last) { return m_ht.erase(first, last); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
size_type erase_ks(const CharT* key, size_type key_size) {
|
||||||
|
return m_ht.erase(key, key_size);
|
||||||
|
}
|
||||||
|
#ifdef TSL_HT_HAS_STRING_VIEW
|
||||||
|
size_type erase(const std::basic_string_view<CharT>& key) {
|
||||||
|
return m_ht.erase(key.data(), key.size());
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
size_type erase(const CharT* key) {
|
||||||
|
return m_ht.erase(key, std::strlen(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
size_type erase(const std::basic_string<CharT>& key) {
|
||||||
|
return m_ht.erase(key.data(), key.size());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Erase all the elements which have 'prefix' as prefix. Return the number of erase elements.
|
||||||
|
*/
|
||||||
|
size_type erase_prefix_ks(const CharT* prefix, size_type prefix_size) {
|
||||||
|
return m_ht.erase_prefix(prefix, prefix_size);
|
||||||
|
}
|
||||||
|
#ifdef TSL_HT_HAS_STRING_VIEW
|
||||||
|
/**
|
||||||
|
* @copydoc erase_prefix_ks(const CharT* prefix, size_type prefix_size)
|
||||||
|
*/
|
||||||
|
size_type erase_prefix(const std::basic_string_view<CharT>& prefix) {
|
||||||
|
return m_ht.erase_prefix(prefix.data(), prefix.size());
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/**
|
||||||
|
* @copydoc erase_prefix_ks(const CharT* prefix, size_type prefix_size)
|
||||||
|
*/
|
||||||
|
size_type erase_prefix(const CharT* prefix) {
|
||||||
|
return m_ht.erase_prefix(prefix, std::strlen(prefix));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc erase_prefix_ks(const CharT* prefix, size_type prefix_size)
|
||||||
|
*/
|
||||||
|
size_type erase_prefix(const std::basic_string<CharT>& prefix) {
|
||||||
|
return m_ht.erase_prefix(prefix.data(), prefix.size());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void swap(htrie_map& other) { other.m_ht.swap(m_ht); }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Lookup
|
||||||
|
*/
|
||||||
|
T& at_ks(const CharT* key, size_type key_size) { return m_ht.at(key, key_size); }
|
||||||
|
const T& at_ks(const CharT* key, size_type key_size) const { return m_ht.at(key, key_size); }
|
||||||
|
|
||||||
|
#ifdef TSL_HT_HAS_STRING_VIEW
|
||||||
|
T& at(const std::basic_string_view<CharT>& key) { return m_ht.at(key.data(), key.size()); }
|
||||||
|
const T& at(const std::basic_string_view<CharT>& key) const { return m_ht.at(key.data(), key.size()); }
|
||||||
|
#else
|
||||||
|
T& at(const CharT* key) { return m_ht.at(key, std::strlen(key)); }
|
||||||
|
const T& at(const CharT* key) const { return m_ht.at(key, std::strlen(key)); }
|
||||||
|
|
||||||
|
T& at(const std::basic_string<CharT>& key) { return m_ht.at(key.data(), key.size()); }
|
||||||
|
const T& at(const std::basic_string<CharT>& key) const { return m_ht.at(key.data(), key.size()); }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TSL_HT_HAS_STRING_VIEW
|
||||||
|
T& operator[](const std::basic_string_view<CharT>& key) { return m_ht.access_operator(key.data(), key.size()); }
|
||||||
|
#else
|
||||||
|
T& operator[](const CharT* key) { return m_ht.access_operator(key, std::strlen(key)); }
|
||||||
|
T& operator[](const std::basic_string<CharT>& key) { return m_ht.access_operator(key.data(), key.size()); }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
size_type count_ks(const CharT* key, size_type key_size) const { return m_ht.count(key, key_size); }
|
||||||
|
#ifdef TSL_HT_HAS_STRING_VIEW
|
||||||
|
size_type count(const std::basic_string_view<CharT>& key) const { return m_ht.count(key.data(), key.size()); }
|
||||||
|
#else
|
||||||
|
size_type count(const CharT* key) const { return m_ht.count(key, std::strlen(key)); }
|
||||||
|
size_type count(const std::basic_string<CharT>& key) const { return m_ht.count(key.data(), key.size()); }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
iterator find_ks(const CharT* key, size_type key_size) {
|
||||||
|
return m_ht.find(key, key_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator find_ks(const CharT* key, size_type key_size) const {
|
||||||
|
return m_ht.find(key, key_size);
|
||||||
|
}
|
||||||
|
#ifdef TSL_HT_HAS_STRING_VIEW
|
||||||
|
iterator find(const std::basic_string_view<CharT>& key) {
|
||||||
|
return m_ht.find(key.data(), key.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator find(const std::basic_string_view<CharT>& key) const {
|
||||||
|
return m_ht.find(key.data(), key.size());
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
iterator find(const CharT* key) {
|
||||||
|
return m_ht.find(key, std::strlen(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator find(const CharT* key) const {
|
||||||
|
return m_ht.find(key, std::strlen(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator find(const std::basic_string<CharT>& key) {
|
||||||
|
return m_ht.find(key.data(), key.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator find(const std::basic_string<CharT>& key) const {
|
||||||
|
return m_ht.find(key.data(), key.size());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
std::pair<iterator, iterator> equal_range_ks(const CharT* key, size_type key_size) {
|
||||||
|
return m_ht.equal_range(key, key_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<const_iterator, const_iterator> equal_range_ks(const CharT* key, size_type key_size) const {
|
||||||
|
return m_ht.equal_range(key, key_size);
|
||||||
|
}
|
||||||
|
#ifdef TSL_HT_HAS_STRING_VIEW
|
||||||
|
std::pair<iterator, iterator> equal_range(const std::basic_string_view<CharT>& key) {
|
||||||
|
return m_ht.equal_range(key.data(), key.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<const_iterator, const_iterator> equal_range(const std::basic_string_view<CharT>& key) const {
|
||||||
|
return m_ht.equal_range(key.data(), key.size());
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
std::pair<iterator, iterator> equal_range(const CharT* key) {
|
||||||
|
return m_ht.equal_range(key, std::strlen(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<const_iterator, const_iterator> equal_range(const CharT* key) const {
|
||||||
|
return m_ht.equal_range(key, std::strlen(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<iterator, iterator> equal_range(const std::basic_string<CharT>& key) {
|
||||||
|
return m_ht.equal_range(key.data(), key.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<const_iterator, const_iterator> equal_range(const std::basic_string<CharT>& key) const {
|
||||||
|
return m_ht.equal_range(key.data(), key.size());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a range containing all the elements which have 'prefix' as prefix. The range is defined by a pair
|
||||||
|
* of iterator, the first being the begin iterator and the second being the end iterator.
|
||||||
|
*/
|
||||||
|
std::pair<prefix_iterator, prefix_iterator> equal_prefix_range_ks(const CharT* prefix, size_type prefix_size) {
|
||||||
|
return m_ht.equal_prefix_range(prefix, prefix_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc equal_prefix_range_ks(const CharT* prefix, size_type prefix_size)
|
||||||
|
*/
|
||||||
|
std::pair<const_prefix_iterator, const_prefix_iterator> equal_prefix_range_ks(const CharT* prefix, size_type prefix_size) const {
|
||||||
|
return m_ht.equal_prefix_range(prefix, prefix_size);
|
||||||
|
}
|
||||||
|
#ifdef TSL_HT_HAS_STRING_VIEW
|
||||||
|
/**
|
||||||
|
* @copydoc equal_prefix_range_ks(const CharT* prefix, size_type prefix_size)
|
||||||
|
*/
|
||||||
|
std::pair<prefix_iterator, prefix_iterator> equal_prefix_range(const std::basic_string_view<CharT>& prefix) {
|
||||||
|
return m_ht.equal_prefix_range(prefix.data(), prefix.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc equal_prefix_range_ks(const CharT* prefix, size_type prefix_size)
|
||||||
|
*/
|
||||||
|
std::pair<const_prefix_iterator, const_prefix_iterator> equal_prefix_range(const std::basic_string_view<CharT>& prefix) const {
|
||||||
|
return m_ht.equal_prefix_range(prefix.data(), prefix.size());
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/**
|
||||||
|
* @copydoc equal_prefix_range_ks(const CharT* prefix, size_type prefix_size)
|
||||||
|
*/
|
||||||
|
std::pair<prefix_iterator, prefix_iterator> equal_prefix_range(const CharT* prefix) {
|
||||||
|
return m_ht.equal_prefix_range(prefix, std::strlen(prefix));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc equal_prefix_range_ks(const CharT* prefix, size_type prefix_size)
|
||||||
|
*/
|
||||||
|
std::pair<const_prefix_iterator, const_prefix_iterator> equal_prefix_range(const CharT* prefix) const {
|
||||||
|
return m_ht.equal_prefix_range(prefix, std::strlen(prefix));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc equal_prefix_range_ks(const CharT* prefix, size_type prefix_size)
|
||||||
|
*/
|
||||||
|
std::pair<prefix_iterator, prefix_iterator> equal_prefix_range(const std::basic_string<CharT>& prefix) {
|
||||||
|
return m_ht.equal_prefix_range(prefix.data(), prefix.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc equal_prefix_range_ks(const CharT* prefix, size_type prefix_size)
|
||||||
|
*/
|
||||||
|
std::pair<const_prefix_iterator, const_prefix_iterator> equal_prefix_range(const std::basic_string<CharT>& prefix) const {
|
||||||
|
return m_ht.equal_prefix_range(prefix.data(), prefix.size());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the element in the trie which is the longest prefix of `key`. If no
|
||||||
|
* element in the trie is a prefix of `key`, the end iterator is returned.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* tsl::htrie_map<char, int> map = {{"/foo", 1}, {"/foo/bar", 1}};
|
||||||
|
*
|
||||||
|
* map.longest_prefix("/foo"); // returns {"/foo", 1}
|
||||||
|
* map.longest_prefix("/foo/baz"); // returns {"/foo", 1}
|
||||||
|
* map.longest_prefix("/foo/bar/baz"); // returns {"/foo/bar", 1}
|
||||||
|
* map.longest_prefix("/foo/bar/"); // returns {"/foo/bar", 1}
|
||||||
|
* map.longest_prefix("/bar"); // returns end()
|
||||||
|
* map.longest_prefix(""); // returns end()
|
||||||
|
*/
|
||||||
|
iterator longest_prefix_ks(const CharT* key, size_type key_size) {
|
||||||
|
return m_ht.longest_prefix(key, key_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc longest_prefix_ks(const CharT* key, size_type key_size)
|
||||||
|
*/
|
||||||
|
const_iterator longest_prefix_ks(const CharT* key, size_type key_size) const {
|
||||||
|
return m_ht.longest_prefix(key, key_size);
|
||||||
|
}
|
||||||
|
#ifdef TSL_HT_HAS_STRING_VIEW
|
||||||
|
/**
|
||||||
|
* @copydoc longest_prefix_ks(const CharT* key, size_type key_size)
|
||||||
|
*/
|
||||||
|
iterator longest_prefix(const std::basic_string_view<CharT>& key) {
|
||||||
|
return m_ht.longest_prefix(key.data(), key.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc longest_prefix_ks(const CharT* key, size_type key_size)
|
||||||
|
*/
|
||||||
|
const_iterator longest_prefix(const std::basic_string_view<CharT>& key) const {
|
||||||
|
return m_ht.longest_prefix(key.data(), key.size());
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/**
|
||||||
|
* @copydoc longest_prefix_ks(const CharT* key, size_type key_size)
|
||||||
|
*/
|
||||||
|
iterator longest_prefix(const CharT* key) {
|
||||||
|
return m_ht.longest_prefix(key, std::strlen(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc longest_prefix_ks(const CharT* key, size_type key_size)
|
||||||
|
*/
|
||||||
|
const_iterator longest_prefix(const CharT* key) const {
|
||||||
|
return m_ht.longest_prefix(key, std::strlen(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc longest_prefix_ks(const CharT* key, size_type key_size)
|
||||||
|
*/
|
||||||
|
iterator longest_prefix(const std::basic_string<CharT>& key) {
|
||||||
|
return m_ht.longest_prefix(key.data(), key.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc longest_prefix_ks(const CharT* key, size_type key_size)
|
||||||
|
*/
|
||||||
|
const_iterator longest_prefix(const std::basic_string<CharT>& key) const {
|
||||||
|
return m_ht.longest_prefix(key.data(), key.size());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Hash policy
|
||||||
|
*/
|
||||||
|
float max_load_factor() const { return m_ht.max_load_factor(); }
|
||||||
|
void max_load_factor(float ml) { m_ht.max_load_factor(ml); }
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Burst policy
|
||||||
|
*/
|
||||||
|
size_type burst_threshold() const { return m_ht.burst_threshold(); }
|
||||||
|
void burst_threshold(size_type threshold) { m_ht.burst_threshold(threshold); }
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Observers
|
||||||
|
*/
|
||||||
|
hasher hash_function() const { return m_ht.hash_function(); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Other
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize the map through the `serializer` parameter.
|
||||||
|
*
|
||||||
|
* The `serializer` parameter must be a function object that supports the following calls:
|
||||||
|
* - `void operator()(const U& value);` where the types `std::uint64_t`, `float` and `T` must be supported for U.
|
||||||
|
* - `void operator()(const CharT* value, std::size_t value_size);`
|
||||||
|
*
|
||||||
|
* The implementation leaves binary compatibility (endianness, IEEE 754 for floats, ...) of the types it serializes
|
||||||
|
* in the hands of the `Serializer` function object if compatibility is required.
|
||||||
|
*/
|
||||||
|
template<class Serializer>
|
||||||
|
void serialize(Serializer& serializer) const {
|
||||||
|
m_ht.serialize(serializer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deserialize a previously serialized map through the `deserializer` parameter.
|
||||||
|
*
|
||||||
|
* The `deserializer` parameter must be a function object that supports the following calls:
|
||||||
|
* - `template<typename U> U operator()();` where the types `std::uint64_t`, `float` and `T` must be supported for U.
|
||||||
|
* - `void operator()(CharT* value_out, std::size_t value_size);`
|
||||||
|
*
|
||||||
|
* If the deserialized hash map part of the hat-trie is hash compatible with the serialized map, the deserialization process
|
||||||
|
* can be sped up by setting `hash_compatible` to true. To be hash compatible, the Hash (take care of the 32-bits vs 64 bits),
|
||||||
|
* and KeySizeT must behave the same than the ones used in the serialized map. Otherwise the behaviour is undefined
|
||||||
|
* with `hash_compatible` sets to true.
|
||||||
|
*
|
||||||
|
* The behaviour is undefined if the type `CharT` and `T` of the `htrie_map` are not the same as the
|
||||||
|
* types used during serialization.
|
||||||
|
*
|
||||||
|
* The implementation leaves binary compatibility (endianness, IEEE 754 for floats, size of int, ...) of the types it
|
||||||
|
* deserializes in the hands of the `Deserializer` function object if compatibility is required.
|
||||||
|
*/
|
||||||
|
template<class Deserializer>
|
||||||
|
static htrie_map deserialize(Deserializer& deserializer, bool hash_compatible = false) {
|
||||||
|
htrie_map map;
|
||||||
|
map.m_ht.deserialize(deserializer, hash_compatible);
|
||||||
|
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool operator==(const htrie_map& lhs, const htrie_map& rhs) {
|
||||||
|
if(lhs.size() != rhs.size()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string key_buffer;
|
||||||
|
for(auto it = lhs.cbegin(); it != lhs.cend(); ++it) {
|
||||||
|
it.key(key_buffer);
|
||||||
|
|
||||||
|
const auto it_element_rhs = rhs.find(key_buffer);
|
||||||
|
if(it_element_rhs == rhs.cend() || it.value() != it_element_rhs.value()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool operator!=(const htrie_map& lhs, const htrie_map& rhs) {
|
||||||
|
return !operator==(lhs, rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
friend void swap(htrie_map& lhs, htrie_map& rhs) {
|
||||||
|
lhs.swap(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
template<class U, class V>
|
||||||
|
void insert_pair(const std::pair<U, V>& value) {
|
||||||
|
insert(value.first, value.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class U, class V>
|
||||||
|
void insert_pair(std::pair<U, V>&& value) {
|
||||||
|
insert(value.first, std::move(value.second));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
ht m_ht;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end namespace tsl
|
||||||
|
|
||||||
|
#endif
|
||||||
586
ios/include/tsl/htrie_set.h
Normal file
586
ios/include/tsl/htrie_set.h
Normal file
@@ -0,0 +1,586 @@
|
|||||||
|
/**
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017 Thibaut Goetghebuer-Planchon <tessil@gmx.com>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
#ifndef TSL_HTRIE_SET_H
|
||||||
|
#define TSL_HTRIE_SET_H
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstring>
|
||||||
|
#include <initializer_list>
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
#include "htrie_hash.h"
|
||||||
|
|
||||||
|
namespace tsl {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of a hat-trie set.
|
||||||
|
*
|
||||||
|
* The size of a key string is limited to std::numeric_limits<KeySizeT>::max() - 1.
|
||||||
|
* That is 65 535 characters by default, but can be raised with the KeySizeT template parameter.
|
||||||
|
* See max_key_size() for an easy access to this limit.
|
||||||
|
*
|
||||||
|
* Iterators invalidation:
|
||||||
|
* - clear, operator=: always invalidate the iterators.
|
||||||
|
* - insert: always invalidate the iterators.
|
||||||
|
* - erase: always invalidate the iterators.
|
||||||
|
*/
|
||||||
|
template<class CharT,
|
||||||
|
class Hash = tsl::ah::str_hash<CharT>,
|
||||||
|
class KeySizeT = std::uint16_t>
|
||||||
|
class htrie_set {
|
||||||
|
private:
|
||||||
|
template<typename U>
|
||||||
|
using is_iterator = tsl::detail_array_hash::is_iterator<U>;
|
||||||
|
|
||||||
|
using ht = tsl::detail_htrie_hash::htrie_hash<CharT, void, Hash, KeySizeT>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using char_type = typename ht::char_type;
|
||||||
|
using key_size_type = typename ht::key_size_type;
|
||||||
|
using size_type = typename ht::size_type;
|
||||||
|
using hasher = typename ht::hasher;
|
||||||
|
using iterator = typename ht::iterator;
|
||||||
|
using const_iterator = typename ht::const_iterator;
|
||||||
|
using prefix_iterator = typename ht::prefix_iterator;
|
||||||
|
using const_prefix_iterator = typename ht::const_prefix_iterator;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit htrie_set(const Hash& hash = Hash()): m_ht(hash, ht::HASH_NODE_DEFAULT_MAX_LOAD_FACTOR,
|
||||||
|
ht::DEFAULT_BURST_THRESHOLD)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit htrie_set(size_type burst_threshold,
|
||||||
|
const Hash& hash = Hash()): m_ht(hash, ht::HASH_NODE_DEFAULT_MAX_LOAD_FACTOR,
|
||||||
|
burst_threshold)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class InputIt, typename std::enable_if<is_iterator<InputIt>::value>::type* = nullptr>
|
||||||
|
htrie_set(InputIt first, InputIt last,
|
||||||
|
const Hash& hash = Hash()): htrie_set(hash)
|
||||||
|
{
|
||||||
|
insert(first, last);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TSL_HT_HAS_STRING_VIEW
|
||||||
|
htrie_set(std::initializer_list<std::basic_string_view<CharT>> init,
|
||||||
|
const Hash& hash = Hash()): htrie_set(hash)
|
||||||
|
{
|
||||||
|
insert(init);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
htrie_set(std::initializer_list<const CharT*> init,
|
||||||
|
const Hash& hash = Hash()): htrie_set(hash)
|
||||||
|
{
|
||||||
|
insert(init);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TSL_HT_HAS_STRING_VIEW
|
||||||
|
htrie_set& operator=(std::initializer_list<std::basic_string_view<CharT>> ilist) {
|
||||||
|
clear();
|
||||||
|
insert(ilist);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
htrie_set& operator=(std::initializer_list<const CharT*> ilist) {
|
||||||
|
clear();
|
||||||
|
insert(ilist);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Iterators
|
||||||
|
*/
|
||||||
|
iterator begin() noexcept { return m_ht.begin(); }
|
||||||
|
const_iterator begin() const noexcept { return m_ht.begin(); }
|
||||||
|
const_iterator cbegin() const noexcept { return m_ht.cbegin(); }
|
||||||
|
|
||||||
|
iterator end() noexcept { return m_ht.end(); }
|
||||||
|
const_iterator end() const noexcept { return m_ht.end(); }
|
||||||
|
const_iterator cend() const noexcept { return m_ht.cend(); }
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Capacity
|
||||||
|
*/
|
||||||
|
bool empty() const noexcept { return m_ht.empty(); }
|
||||||
|
size_type size() const noexcept { return m_ht.size(); }
|
||||||
|
size_type max_size() const noexcept { return m_ht.max_size(); }
|
||||||
|
size_type max_key_size() const noexcept { return m_ht.max_key_size(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call shrink_to_fit() on each hash node of the hat-trie to reduce its size.
|
||||||
|
*/
|
||||||
|
void shrink_to_fit() { m_ht.shrink_to_fit(); }
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Modifiers
|
||||||
|
*/
|
||||||
|
void clear() noexcept { m_ht.clear(); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
std::pair<iterator, bool> insert_ks(const CharT* key, size_type key_size) {
|
||||||
|
return m_ht.insert(key, key_size);
|
||||||
|
}
|
||||||
|
#ifdef TSL_HT_HAS_STRING_VIEW
|
||||||
|
std::pair<iterator, bool> insert(const std::basic_string_view<CharT>& key) {
|
||||||
|
return m_ht.insert(key.data(), key.size());
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
std::pair<iterator, bool> insert(const CharT* key) {
|
||||||
|
return m_ht.insert(key, std::strlen(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<iterator, bool> insert(const std::basic_string<CharT>& key) {
|
||||||
|
return m_ht.insert(key.data(), key.size());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template<class InputIt, typename std::enable_if<is_iterator<InputIt>::value>::type* = nullptr>
|
||||||
|
void insert(InputIt first, InputIt last) {
|
||||||
|
for(auto it = first; it != last; ++it) {
|
||||||
|
insert(*it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TSL_HT_HAS_STRING_VIEW
|
||||||
|
void insert(std::initializer_list<std::basic_string_view<CharT>> ilist) {
|
||||||
|
insert(ilist.begin(), ilist.end());
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void insert(std::initializer_list<const CharT*> ilist) {
|
||||||
|
insert(ilist.begin(), ilist.end());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
std::pair<iterator, bool> emplace_ks(const CharT* key, size_type key_size) {
|
||||||
|
return m_ht.insert(key, key_size);
|
||||||
|
}
|
||||||
|
#ifdef TSL_HT_HAS_STRING_VIEW
|
||||||
|
std::pair<iterator, bool> emplace(const std::basic_string_view<CharT>& key) {
|
||||||
|
return m_ht.insert(key.data(), key.size());
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
std::pair<iterator, bool> emplace(const CharT* key) {
|
||||||
|
return m_ht.insert(key, std::strlen(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<iterator, bool> emplace(const std::basic_string<CharT>& key) {
|
||||||
|
return m_ht.insert(key.data(), key.size());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
iterator erase(const_iterator pos) { return m_ht.erase(pos); }
|
||||||
|
iterator erase(const_iterator first, const_iterator last) { return m_ht.erase(first, last); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
size_type erase_ks(const CharT* key, size_type key_size) {
|
||||||
|
return m_ht.erase(key, key_size);
|
||||||
|
}
|
||||||
|
#ifdef TSL_HT_HAS_STRING_VIEW
|
||||||
|
size_type erase(const std::basic_string_view<CharT>& key) {
|
||||||
|
return m_ht.erase(key.data(), key.size());
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
size_type erase(const CharT* key) {
|
||||||
|
return m_ht.erase(key, std::strlen(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
size_type erase(const std::basic_string<CharT>& key) {
|
||||||
|
return m_ht.erase(key.data(), key.size());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Erase all the elements which have 'prefix' as prefix. Return the number of erase elements.
|
||||||
|
*/
|
||||||
|
size_type erase_prefix_ks(const CharT* prefix, size_type prefix_size) {
|
||||||
|
return m_ht.erase_prefix(prefix, prefix_size);
|
||||||
|
}
|
||||||
|
#ifdef TSL_HT_HAS_STRING_VIEW
|
||||||
|
/**
|
||||||
|
* @copydoc erase_prefix_ks(const CharT* prefix, size_type prefix_size)
|
||||||
|
*/
|
||||||
|
size_type erase_prefix(const std::basic_string_view<CharT>& prefix) {
|
||||||
|
return m_ht.erase_prefix(prefix.data(), prefix.size());
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/**
|
||||||
|
* @copydoc erase_prefix_ks(const CharT* prefix, size_type prefix_size)
|
||||||
|
*/
|
||||||
|
size_type erase_prefix(const CharT* prefix) {
|
||||||
|
return m_ht.erase_prefix(prefix, std::strlen(prefix));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc erase_prefix_ks(const CharT* prefix, size_type prefix_size)
|
||||||
|
*/
|
||||||
|
size_type erase_prefix(const std::basic_string<CharT>& prefix) {
|
||||||
|
return m_ht.erase_prefix(prefix.data(), prefix.size());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void swap(htrie_set& other) { other.m_ht.swap(m_ht); }
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Lookup
|
||||||
|
*/
|
||||||
|
size_type count_ks(const CharT* key, size_type key_size) const { return m_ht.count(key, key_size); }
|
||||||
|
#ifdef TSL_HT_HAS_STRING_VIEW
|
||||||
|
size_type count(const std::basic_string_view<CharT>& key) const { return m_ht.count(key.data(), key.size()); }
|
||||||
|
#else
|
||||||
|
size_type count(const CharT* key) const { return m_ht.count(key, std::strlen(key)); }
|
||||||
|
size_type count(const std::basic_string<CharT>& key) const { return m_ht.count(key.data(), key.size()); }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
iterator find_ks(const CharT* key, size_type key_size) {
|
||||||
|
return m_ht.find(key, key_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator find_ks(const CharT* key, size_type key_size) const {
|
||||||
|
return m_ht.find(key, key_size);
|
||||||
|
}
|
||||||
|
#ifdef TSL_HT_HAS_STRING_VIEW
|
||||||
|
iterator find(const std::basic_string_view<CharT>& key) {
|
||||||
|
return m_ht.find(key.data(), key.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator find(const std::basic_string_view<CharT>& key) const {
|
||||||
|
return m_ht.find(key.data(), key.size());
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
iterator find(const CharT* key) {
|
||||||
|
return m_ht.find(key, std::strlen(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator find(const CharT* key) const {
|
||||||
|
return m_ht.find(key, std::strlen(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator find(const std::basic_string<CharT>& key) {
|
||||||
|
return m_ht.find(key.data(), key.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator find(const std::basic_string<CharT>& key) const {
|
||||||
|
return m_ht.find(key.data(), key.size());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
std::pair<iterator, iterator> equal_range_ks(const CharT* key, size_type key_size) {
|
||||||
|
return m_ht.equal_range(key, key_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<const_iterator, const_iterator> equal_range_ks(const CharT* key, size_type key_size) const {
|
||||||
|
return m_ht.equal_range(key, key_size);
|
||||||
|
}
|
||||||
|
#ifdef TSL_HT_HAS_STRING_VIEW
|
||||||
|
std::pair<iterator, iterator> equal_range(const std::basic_string_view<CharT>& key) {
|
||||||
|
return m_ht.equal_range(key.data(), key.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<const_iterator, const_iterator> equal_range(const std::basic_string_view<CharT>& key) const {
|
||||||
|
return m_ht.equal_range(key.data(), key.size());
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
std::pair<iterator, iterator> equal_range(const CharT* key) {
|
||||||
|
return m_ht.equal_range(key, std::strlen(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<const_iterator, const_iterator> equal_range(const CharT* key) const {
|
||||||
|
return m_ht.equal_range(key, std::strlen(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<iterator, iterator> equal_range(const std::basic_string<CharT>& key) {
|
||||||
|
return m_ht.equal_range(key.data(), key.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<const_iterator, const_iterator> equal_range(const std::basic_string<CharT>& key) const {
|
||||||
|
return m_ht.equal_range(key.data(), key.size());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a range containing all the elements which have 'prefix' as prefix. The range is defined by a pair
|
||||||
|
* of iterator, the first being the begin iterator and the second being the end iterator.
|
||||||
|
*/
|
||||||
|
std::pair<prefix_iterator, prefix_iterator> equal_prefix_range_ks(const CharT* prefix, size_type prefix_size) {
|
||||||
|
return m_ht.equal_prefix_range(prefix, prefix_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc equal_prefix_range_ks(const CharT* prefix, size_type prefix_size)
|
||||||
|
*/
|
||||||
|
std::pair<const_prefix_iterator, const_prefix_iterator> equal_prefix_range_ks(const CharT* prefix, size_type prefix_size) const {
|
||||||
|
return m_ht.equal_prefix_range(prefix, prefix_size);
|
||||||
|
}
|
||||||
|
#ifdef TSL_HT_HAS_STRING_VIEW
|
||||||
|
/**
|
||||||
|
* @copydoc equal_prefix_range_ks(const CharT* prefix, size_type prefix_size)
|
||||||
|
*/
|
||||||
|
std::pair<prefix_iterator, prefix_iterator> equal_prefix_range(const std::basic_string_view<CharT>& prefix) {
|
||||||
|
return m_ht.equal_prefix_range(prefix.data(), prefix.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc equal_prefix_range_ks(const CharT* prefix, size_type prefix_size)
|
||||||
|
*/
|
||||||
|
std::pair<const_prefix_iterator, const_prefix_iterator> equal_prefix_range(const std::basic_string_view<CharT>& prefix) const {
|
||||||
|
return m_ht.equal_prefix_range(prefix.data(), prefix.size());
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/**
|
||||||
|
* @copydoc equal_prefix_range_ks(const CharT* prefix, size_type prefix_size)
|
||||||
|
*/
|
||||||
|
std::pair<prefix_iterator, prefix_iterator> equal_prefix_range(const CharT* prefix) {
|
||||||
|
return m_ht.equal_prefix_range(prefix, std::strlen(prefix));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc equal_prefix_range_ks(const CharT* prefix, size_type prefix_size)
|
||||||
|
*/
|
||||||
|
std::pair<const_prefix_iterator, const_prefix_iterator> equal_prefix_range(const CharT* prefix) const {
|
||||||
|
return m_ht.equal_prefix_range(prefix, std::strlen(prefix));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc equal_prefix_range_ks(const CharT* prefix, size_type prefix_size)
|
||||||
|
*/
|
||||||
|
std::pair<prefix_iterator, prefix_iterator> equal_prefix_range(const std::basic_string<CharT>& prefix) {
|
||||||
|
return m_ht.equal_prefix_range(prefix.data(), prefix.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc equal_prefix_range_ks(const CharT* prefix, size_type prefix_size)
|
||||||
|
*/
|
||||||
|
std::pair<const_prefix_iterator, const_prefix_iterator> equal_prefix_range(const std::basic_string<CharT>& prefix) const {
|
||||||
|
return m_ht.equal_prefix_range(prefix.data(), prefix.size());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the element in the trie which is the longest prefix of `key`. If no
|
||||||
|
* element in the trie is a prefix of `key`, the end iterator is returned.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* tsl::htrie_set<char> set = {"/foo", "/foo/bar"};
|
||||||
|
*
|
||||||
|
* set.longest_prefix("/foo"); // returns "/foo"
|
||||||
|
* set.longest_prefix("/foo/baz"); // returns "/foo"
|
||||||
|
* set.longest_prefix("/foo/bar/baz"); // returns "/foo/bar"
|
||||||
|
* set.longest_prefix("/foo/bar/"); // returns "/foo/bar"
|
||||||
|
* set.longest_prefix("/bar"); // returns end()
|
||||||
|
* set.longest_prefix(""); // returns end()
|
||||||
|
*/
|
||||||
|
iterator longest_prefix_ks(const CharT* key, size_type key_size) {
|
||||||
|
return m_ht.longest_prefix(key, key_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc longest_prefix_ks(const CharT* key, size_type key_size)
|
||||||
|
*/
|
||||||
|
const_iterator longest_prefix_ks(const CharT* key, size_type key_size) const {
|
||||||
|
return m_ht.longest_prefix(key, key_size);
|
||||||
|
}
|
||||||
|
#ifdef TSL_HT_HAS_STRING_VIEW
|
||||||
|
/**
|
||||||
|
* @copydoc longest_prefix_ks(const CharT* key, size_type key_size)
|
||||||
|
*/
|
||||||
|
iterator longest_prefix(const std::basic_string_view<CharT>& key) {
|
||||||
|
return m_ht.longest_prefix(key.data(), key.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc longest_prefix_ks(const CharT* key, size_type key_size)
|
||||||
|
*/
|
||||||
|
const_iterator longest_prefix(const std::basic_string_view<CharT>& key) const {
|
||||||
|
return m_ht.longest_prefix(key.data(), key.size());
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/**
|
||||||
|
* @copydoc longest_prefix_ks(const CharT* key, size_type key_size)
|
||||||
|
*/
|
||||||
|
iterator longest_prefix(const CharT* key) {
|
||||||
|
return m_ht.longest_prefix(key, std::strlen(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc longest_prefix_ks(const CharT* key, size_type key_size)
|
||||||
|
*/
|
||||||
|
const_iterator longest_prefix(const CharT* key) const {
|
||||||
|
return m_ht.longest_prefix(key, std::strlen(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc longest_prefix_ks(const CharT* key, size_type key_size)
|
||||||
|
*/
|
||||||
|
iterator longest_prefix(const std::basic_string<CharT>& key) {
|
||||||
|
return m_ht.longest_prefix(key.data(), key.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc longest_prefix_ks(const CharT* key, size_type key_size)
|
||||||
|
*/
|
||||||
|
const_iterator longest_prefix(const std::basic_string<CharT>& key) const {
|
||||||
|
return m_ht.longest_prefix(key.data(), key.size());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Hash policy
|
||||||
|
*/
|
||||||
|
float max_load_factor() const { return m_ht.max_load_factor(); }
|
||||||
|
void max_load_factor(float ml) { m_ht.max_load_factor(ml); }
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Burst policy
|
||||||
|
*/
|
||||||
|
size_type burst_threshold() const { return m_ht.burst_threshold(); }
|
||||||
|
void burst_threshold(size_type threshold) { m_ht.burst_threshold(threshold); }
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Observers
|
||||||
|
*/
|
||||||
|
hasher hash_function() const { return m_ht.hash_function(); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Other
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize the set through the `serializer` parameter.
|
||||||
|
*
|
||||||
|
* The `serializer` parameter must be a function object that supports the following calls:
|
||||||
|
* - `void operator()(const U& value);` where the types `std::uint64_t` and `float` must be supported for U.
|
||||||
|
* - `void operator()(const CharT* value, std::size_t value_size);`
|
||||||
|
*
|
||||||
|
* The implementation leaves binary compatibility (endianness, IEEE 754 for floats, ...) of the types it serializes
|
||||||
|
* in the hands of the `Serializer` function object if compatibility is required.
|
||||||
|
*/
|
||||||
|
template<class Serializer>
|
||||||
|
void serialize(Serializer& serializer) const {
|
||||||
|
m_ht.serialize(serializer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deserialize a previously serialized set through the `deserializer` parameter.
|
||||||
|
*
|
||||||
|
* The `deserializer` parameter must be a function object that supports the following calls:
|
||||||
|
* - `template<typename U> U operator()();` where the types `std::uint64_t` and `float` must be supported for U.
|
||||||
|
* - `void operator()(CharT* value_out, std::size_t value_size);`
|
||||||
|
*
|
||||||
|
* If the deserialized hash set part of the hat-trie is hash compatible with the serialized set, the deserialization process
|
||||||
|
* can be sped up by setting `hash_compatible` to true. To be hash compatible, the Hash (take care of the 32-bits vs 64 bits),
|
||||||
|
* and KeySizeT must behave the same than the ones used in the serialized set. Otherwise the behaviour is undefined
|
||||||
|
* with `hash_compatible` sets to true.
|
||||||
|
*
|
||||||
|
* The behaviour is undefined if the type `CharT` of the `htrie_set` is not the same as the
|
||||||
|
* type used during serialization.
|
||||||
|
*
|
||||||
|
* The implementation leaves binary compatibility (endianness, IEEE 754 for floats, size of int, ...) of the types it
|
||||||
|
* deserializes in the hands of the `Deserializer` function object if compatibility is required.
|
||||||
|
*/
|
||||||
|
template<class Deserializer>
|
||||||
|
static htrie_set deserialize(Deserializer& deserializer, bool hash_compatible = false) {
|
||||||
|
htrie_set set;
|
||||||
|
set.m_ht.deserialize(deserializer, hash_compatible);
|
||||||
|
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool operator==(const htrie_set& lhs, const htrie_set& rhs) {
|
||||||
|
if(lhs.size() != rhs.size()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string key_buffer;
|
||||||
|
for(auto it = lhs.cbegin(); it != lhs.cend(); ++it) {
|
||||||
|
it.key(key_buffer);
|
||||||
|
|
||||||
|
const auto it_element_rhs = rhs.find(key_buffer);
|
||||||
|
if(it_element_rhs == rhs.cend()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool operator!=(const htrie_set& lhs, const htrie_set& rhs) {
|
||||||
|
return !operator==(lhs, rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
friend void swap(htrie_set& lhs, htrie_set& rhs) {
|
||||||
|
lhs.swap(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
ht m_ht;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end namespace tsl
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include <utils/compiler.h>
|
#include <utils/compiler.h>
|
||||||
|
#include <utils/debug.h>
|
||||||
#include <utils/memalign.h>
|
#include <utils/memalign.h>
|
||||||
#include <utils/Mutex.h>
|
#include <utils/Mutex.h>
|
||||||
#include <utils/SpinLock.h>
|
#include <utils/SpinLock.h>
|
||||||
@@ -793,7 +794,9 @@ public:
|
|||||||
explicit STLAllocator(STLAllocator<U, ARENA> const& rhs) : mArena(rhs.mArena) { }
|
explicit STLAllocator(STLAllocator<U, ARENA> const& rhs) : mArena(rhs.mArena) { }
|
||||||
|
|
||||||
TYPE* allocate(std::size_t n) {
|
TYPE* allocate(std::size_t n) {
|
||||||
return static_cast<TYPE *>(mArena.alloc(n * sizeof(TYPE), alignof(TYPE)));
|
auto p = static_cast<TYPE *>(mArena.alloc(n * sizeof(TYPE), alignof(TYPE)));
|
||||||
|
assert_invariant(p);
|
||||||
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
void deallocate(TYPE* p, std::size_t n) {
|
void deallocate(TYPE* p, std::size_t n) {
|
||||||
|
|||||||
@@ -14,8 +14,8 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef TNT_FILAMENT_CSTRING_H
|
#ifndef TNT_UTILS_CSTRING_H
|
||||||
#define TNT_FILAMENT_CSTRING_H
|
#define TNT_UTILS_CSTRING_H
|
||||||
|
|
||||||
// NOTE: this header should not include STL headers
|
// NOTE: this header should not include STL headers
|
||||||
|
|
||||||
@@ -390,4 +390,4 @@ struct hash<utils::StaticString> {
|
|||||||
|
|
||||||
} // namespace std
|
} // namespace std
|
||||||
|
|
||||||
#endif // TNT_FILAMENT_CSTRING_H
|
#endif // TNT_UTILS_CSTRING_H
|
||||||
|
|||||||
@@ -14,8 +14,8 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef UTILS_CALLSTACK_H_
|
#ifndef UTILS_CALLSTACK_H
|
||||||
#define UTILS_CALLSTACK_H_
|
#define UTILS_CALLSTACK_H
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@@ -124,4 +124,4 @@ private:
|
|||||||
|
|
||||||
} // namespace utils
|
} // namespace utils
|
||||||
|
|
||||||
#endif // UTILS_CALLSTACK_H_
|
#endif // UTILS_CALLSTACK_H
|
||||||
|
|||||||
@@ -14,13 +14,13 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef UTILS_CONDITION_H
|
#ifndef TNT_UTILS_CONDITION_H
|
||||||
#define UTILS_CONDITION_H
|
#define TNT_UTILS_CONDITION_H
|
||||||
|
|
||||||
#if defined(__linux__) && !defined(__SANITIZE_THREAD__)
|
#if defined(__linux__)
|
||||||
#include <utils/linux/Condition.h>
|
#include <utils/linux/Condition.h>
|
||||||
#else
|
#else
|
||||||
#include <utils/generic/Condition.h>
|
#include <utils/generic/Condition.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // UTILS_CONDITION_H
|
#endif // TNT_UTILS_CONDITION_H
|
||||||
|
|||||||
@@ -14,8 +14,8 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef UTILS_COUNTDOWNLATCH_H_
|
#ifndef TNT_UTILS_COUNTDOWNLATCH_H
|
||||||
#define UTILS_COUNTDOWNLATCH_H_
|
#define TNT_UTILS_COUNTDOWNLATCH_H
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
@@ -88,4 +88,4 @@ private:
|
|||||||
|
|
||||||
} // namespace utils
|
} // namespace utils
|
||||||
|
|
||||||
#endif // UTILS_COUNTDOWNLATCH_H_
|
#endif // TNT_UTILS_COUNTDOWNLATCH_H
|
||||||
|
|||||||
@@ -14,8 +14,8 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef UTILS_CYCLIC_BARRIER_H_
|
#ifndef TNT_UTILS_CYCLIC_BARRIER_H
|
||||||
#define UTILS_CYCLIC_BARRIER_H_
|
#define TNT_UTILS_CYCLIC_BARRIER_H
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
@@ -81,4 +81,4 @@ private:
|
|||||||
|
|
||||||
} // namespace utils
|
} // namespace utils
|
||||||
|
|
||||||
#endif // UTILS_CYCLIC_BARRIER_H_
|
#endif // TNT_UTILS_CYCLIC_BARRIER_H
|
||||||
|
|||||||
@@ -14,8 +14,8 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef TNT_FILAMENT_UTILS_ENTITYINSTANCE_H
|
#ifndef TNT_UTILS_ENTITYINSTANCE_H
|
||||||
#define TNT_FILAMENT_UTILS_ENTITYINSTANCE_H
|
#define TNT_UTILS_ENTITYINSTANCE_H
|
||||||
|
|
||||||
#include <utils/compiler.h>
|
#include <utils/compiler.h>
|
||||||
|
|
||||||
@@ -86,4 +86,4 @@ public:
|
|||||||
|
|
||||||
} // namespace utils
|
} // namespace utils
|
||||||
|
|
||||||
#endif // TNT_FILAMENT_UTILS_ENTITYINSTANCE_H
|
#endif // TNT_UTILS_ENTITYINSTANCE_H
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include <utils/Panic.h>
|
#include <utils/Panic.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <limits>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
@@ -407,4 +408,4 @@ private:
|
|||||||
|
|
||||||
} // namespace utils
|
} // namespace utils
|
||||||
|
|
||||||
#endif //TNT_UTILS_FIXEDCAPACITYVECTOR_H
|
#endif // TNT_UTILS_FIXEDCAPACITYVECTOR_H
|
||||||
|
|||||||
@@ -34,6 +34,9 @@ struct UTILS_PUBLIC Loggers {
|
|||||||
|
|
||||||
// INFORMATION level logging stream
|
// INFORMATION level logging stream
|
||||||
io::ostream& i;
|
io::ostream& i;
|
||||||
|
|
||||||
|
// VERBOSE level logging stream
|
||||||
|
io::ostream& v;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern UTILS_PUBLIC Loggers const slog;
|
extern UTILS_PUBLIC Loggers const slog;
|
||||||
|
|||||||
@@ -14,13 +14,13 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef UTILS_MUTEX_H
|
#ifndef TNT_UTILS_MUTEX_H
|
||||||
#define UTILS_MUTEX_H
|
#define TNT_UTILS_MUTEX_H
|
||||||
|
|
||||||
#if defined(__linux__) && !defined(__SANITIZE_THREAD__)
|
#if defined(__linux__)
|
||||||
#include <utils/linux/Mutex.h>
|
#include <utils/linux/Mutex.h>
|
||||||
#else
|
#else
|
||||||
#include <utils/generic/Mutex.h>
|
#include <utils/generic/Mutex.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // UTILS_MUTEX_H
|
#endif // TNT_UTILS_MUTEX_H
|
||||||
|
|||||||
@@ -14,8 +14,8 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef UTILS_PANIC_H_
|
#ifndef TNT_UTILS_PANIC_H
|
||||||
#define UTILS_PANIC_H_
|
#define TNT_UTILS_PANIC_H
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@@ -558,4 +558,4 @@ class UTILS_PUBLIC ArithmeticPanic : public TPanic<ArithmeticPanic> {
|
|||||||
*/
|
*/
|
||||||
#define ASSERT_DESTRUCTOR(cond, format, ...) (!(cond) ? PANIC_LOG(format, ##__VA_ARGS__) : (void)0)
|
#define ASSERT_DESTRUCTOR(cond, format, ...) (!(cond) ? PANIC_LOG(format, ##__VA_ARGS__) : (void)0)
|
||||||
|
|
||||||
#endif // UTILS_PANIC_H_
|
#endif // TNT_UTILS_PANIC_H
|
||||||
|
|||||||
@@ -14,8 +14,8 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef UTILS_PATH_H_
|
#ifndef TNT_UTILS_PATH_H
|
||||||
#define UTILS_PATH_H_
|
#define TNT_UTILS_PATH_H
|
||||||
|
|
||||||
#include <utils/compiler.h>
|
#include <utils/compiler.h>
|
||||||
|
|
||||||
@@ -287,4 +287,4 @@ private:
|
|||||||
|
|
||||||
} // namespace utils
|
} // namespace utils
|
||||||
|
|
||||||
#endif // UTILS_PATH_H_
|
#endif // TNT_UTILS_PATH_H
|
||||||
|
|||||||
@@ -75,8 +75,8 @@ private:
|
|||||||
};
|
};
|
||||||
} // namespace details
|
} // namespace details
|
||||||
|
|
||||||
#if defined(__SANITIZE_THREAD__)
|
#if UTILS_HAS_SANITIZE_THREAD
|
||||||
// Unfortunately TSAN doesn't support homegrown synchronization primitives
|
// Active spins with atomics slow down execution too much under ThreadSanitizer.
|
||||||
using SpinLock = Mutex;
|
using SpinLock = Mutex;
|
||||||
#elif defined(__ARM_ARCH_7A__)
|
#elif defined(__ARM_ARCH_7A__)
|
||||||
// We've had problems with "wfe" on some ARM-V7 devices, causing spurious SIGILL
|
// We've had problems with "wfe" on some ARM-V7 devices, causing spurious SIGILL
|
||||||
@@ -87,4 +87,4 @@ using SpinLock = details::SpinLock;
|
|||||||
|
|
||||||
} // namespace utils
|
} // namespace utils
|
||||||
|
|
||||||
#endif //TNT_UTILS_SPINLOCK_H
|
#endif // TNT_UTILS_SPINLOCK_H
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
#define SYSTRACE_TAG_JOBSYSTEM (1<<2)
|
#define SYSTRACE_TAG_JOBSYSTEM (1<<2)
|
||||||
|
|
||||||
|
|
||||||
#if defined(ANDROID)
|
#if defined(__ANDROID__)
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
|
||||||
|
|||||||
26
ios/include/utils/ThermalManager.h
Normal file
26
ios/include/utils/ThermalManager.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TNT_UTILS_THERMALMANAGER_H
|
||||||
|
#define TNT_UTILS_THERMALMANAGER_H
|
||||||
|
|
||||||
|
#if defined(__ANDROID__)
|
||||||
|
#include <utils/android/ThermalManager.h>
|
||||||
|
#else
|
||||||
|
#include <utils/generic/ThermalManager.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // TNT_UTILS_THERMALMANAGER_H
|
||||||
@@ -119,4 +119,4 @@ public:
|
|||||||
|
|
||||||
} // namespace utils
|
} // namespace utils
|
||||||
|
|
||||||
#endif /* TNT_UTILS_ZIP2ITERATOR_H */
|
#endif // TNT_UTILS_ZIP2ITERATOR_H
|
||||||
|
|||||||
60
ios/include/utils/android/ThermalManager.h
Normal file
60
ios/include/utils/android/ThermalManager.h
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TNT_UTILS_ANDROID_THERMALMANAGER_H
|
||||||
|
#define TNT_UTILS_ANDROID_THERMALMANAGER_H
|
||||||
|
|
||||||
|
#include <utils/compiler.h>
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
struct AThermalManager;
|
||||||
|
|
||||||
|
namespace utils {
|
||||||
|
|
||||||
|
class ThermalManager {
|
||||||
|
public:
|
||||||
|
enum class ThermalStatus : int8_t {
|
||||||
|
ERROR = -1,
|
||||||
|
NONE,
|
||||||
|
LIGHT,
|
||||||
|
MODERATE,
|
||||||
|
SEVERE,
|
||||||
|
CRITICAL,
|
||||||
|
EMERGENCY,
|
||||||
|
SHUTDOWN
|
||||||
|
};
|
||||||
|
|
||||||
|
ThermalManager();
|
||||||
|
~ThermalManager();
|
||||||
|
|
||||||
|
// Movable
|
||||||
|
ThermalManager(ThermalManager&& rhs) noexcept;
|
||||||
|
ThermalManager& operator=(ThermalManager&& rhs) noexcept;
|
||||||
|
|
||||||
|
// not copiable
|
||||||
|
ThermalManager(ThermalManager const& rhs) = delete;
|
||||||
|
ThermalManager& operator=(ThermalManager const& rhs) = delete;
|
||||||
|
|
||||||
|
ThermalStatus getCurrentThermalStatus() const noexcept;
|
||||||
|
|
||||||
|
private:
|
||||||
|
AThermalManager* mThermalManager = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace utils
|
||||||
|
|
||||||
|
#endif // TNT_UTILS_ANDROID_THERMALMANAGER_H
|
||||||
@@ -14,8 +14,8 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef TNT_UTILS_API_H
|
#ifndef TNT_UTILS_APILEVEL_H
|
||||||
#define TNT_UTILS_API_H
|
#define TNT_UTILS_APILEVEL_H
|
||||||
|
|
||||||
#include <utils/compiler.h>
|
#include <utils/compiler.h>
|
||||||
|
|
||||||
@@ -31,4 +31,4 @@ int api_level();
|
|||||||
|
|
||||||
} // namespace utils
|
} // namespace utils
|
||||||
|
|
||||||
#endif // TNT_UTILS_ARCHITECTURE_H
|
#endif // TNT_UTILS_APILEVEL_H
|
||||||
|
|||||||
@@ -25,4 +25,4 @@ int ashmem_create_region(const char *name, size_t size);
|
|||||||
|
|
||||||
} // namespace utils
|
} // namespace utils
|
||||||
|
|
||||||
#endif /* TNT_UTILS_ASHMEM_H */
|
#endif // TNT_UTILS_ASHMEM_H
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
#include <utils/compiler.h>
|
#include <utils/compiler.h>
|
||||||
|
#include <utils/debug.h>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
@@ -59,10 +60,12 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
T getBitsAt(size_t n) const noexcept {
|
T getBitsAt(size_t n) const noexcept {
|
||||||
|
assert_invariant(n<N);
|
||||||
return storage[n];
|
return storage[n];
|
||||||
}
|
}
|
||||||
|
|
||||||
T& getBitsAt(size_t n) noexcept {
|
T& getBitsAt(size_t n) noexcept {
|
||||||
|
assert_invariant(n<N);
|
||||||
return storage[n];
|
return storage[n];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,19 +96,23 @@ public:
|
|||||||
bool test(size_t bit) const noexcept { return operator[](bit); }
|
bool test(size_t bit) const noexcept { return operator[](bit); }
|
||||||
|
|
||||||
void set(size_t b) noexcept {
|
void set(size_t b) noexcept {
|
||||||
|
assert_invariant(b / BITS_PER_WORD < N);
|
||||||
storage[b / BITS_PER_WORD] |= T(1) << (b % BITS_PER_WORD);
|
storage[b / BITS_PER_WORD] |= T(1) << (b % BITS_PER_WORD);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set(size_t b, bool value) noexcept {
|
void set(size_t b, bool value) noexcept {
|
||||||
|
assert_invariant(b / BITS_PER_WORD < N);
|
||||||
storage[b / BITS_PER_WORD] &= ~(T(1) << (b % BITS_PER_WORD));
|
storage[b / BITS_PER_WORD] &= ~(T(1) << (b % BITS_PER_WORD));
|
||||||
storage[b / BITS_PER_WORD] |= T(value) << (b % BITS_PER_WORD);
|
storage[b / BITS_PER_WORD] |= T(value) << (b % BITS_PER_WORD);
|
||||||
}
|
}
|
||||||
|
|
||||||
void unset(size_t b) noexcept {
|
void unset(size_t b) noexcept {
|
||||||
|
assert_invariant(b / BITS_PER_WORD < N);
|
||||||
storage[b / BITS_PER_WORD] &= ~(T(1) << (b % BITS_PER_WORD));
|
storage[b / BITS_PER_WORD] &= ~(T(1) << (b % BITS_PER_WORD));
|
||||||
}
|
}
|
||||||
|
|
||||||
void flip(size_t b) noexcept {
|
void flip(size_t b) noexcept {
|
||||||
|
assert_invariant(b / BITS_PER_WORD < N);
|
||||||
storage[b / BITS_PER_WORD] ^= T(1) << (b % BITS_PER_WORD);
|
storage[b / BITS_PER_WORD] ^= T(1) << (b % BITS_PER_WORD);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,6 +122,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool operator[](size_t b) const noexcept {
|
bool operator[](size_t b) const noexcept {
|
||||||
|
assert_invariant(b / BITS_PER_WORD < N);
|
||||||
return bool(storage[b / BITS_PER_WORD] & (T(1) << (b % BITS_PER_WORD)));
|
return bool(storage[b / BITS_PER_WORD] & (T(1) << (b % BITS_PER_WORD)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -65,19 +65,21 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define UTILS_NO_SANITIZE_THREAD
|
#define UTILS_NO_SANITIZE_THREAD
|
||||||
#if defined(__has_feature)
|
#if __has_feature(thread_sanitizer)
|
||||||
# if __has_feature(thread_sanitizer)
|
#undef UTILS_NO_SANITIZE_THREAD
|
||||||
# undef UTILS_NO_SANITIZE_THREAD
|
#define UTILS_NO_SANITIZE_THREAD __attribute__((no_sanitize("thread")))
|
||||||
# define UTILS_NO_SANITIZE_THREAD __attribute__((no_sanitize("thread")))
|
#endif
|
||||||
# endif
|
|
||||||
|
#define UTILS_HAS_SANITIZE_THREAD 0
|
||||||
|
#if __has_feature(thread_sanitizer) || defined(__SANITIZE_THREAD__)
|
||||||
|
#undef UTILS_HAS_SANITIZE_THREAD
|
||||||
|
#define UTILS_HAS_SANITIZE_THREAD 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define UTILS_HAS_SANITIZE_MEMORY 0
|
#define UTILS_HAS_SANITIZE_MEMORY 0
|
||||||
#if defined(__has_feature)
|
#if __has_feature(memory_sanitizer)
|
||||||
# if __has_feature(memory_sanitizer)
|
#undef UTILS_HAS_SANITIZE_MEMORY
|
||||||
# undef UTILS_HAS_SANITIZE_MEMORY
|
#define UTILS_HAS_SANITIZE_MEMORY 1
|
||||||
# define UTILS_HAS_SANITIZE_MEMORY 1
|
|
||||||
# endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -65,4 +65,4 @@ struct compressed_pair : private T1, private T2 {
|
|||||||
|
|
||||||
} // namespace utils
|
} // namespace utils
|
||||||
|
|
||||||
#endif //TNT_UTILS_COMPRESSED_PAIR_H
|
#endif // TNT_UTILS_COMPRESSED_PAIR_H
|
||||||
|
|||||||
@@ -30,4 +30,4 @@ void panic(const char *func, const char * file, int line, const char *assertion)
|
|||||||
(UTILS_LIKELY(e) ? ((void)0) : utils::panic(__func__, __FILE__, __LINE__, #e))
|
(UTILS_LIKELY(e) ? ((void)0) : utils::panic(__func__, __FILE__, __LINE__, #e))
|
||||||
#endif // NDEBUG
|
#endif // NDEBUG
|
||||||
|
|
||||||
#endif //TNT_UTILS_DEBUG_H
|
#endif // TNT_UTILS_DEBUG_H
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user