first commit
This commit is contained in:
68
ios/include/MaterialKey.h
Normal file
68
ios/include/MaterialKey.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include <gltfio/MaterialProvider.h>
|
||||
|
||||
#define JAVA_MATERIAL_KEY "com/google/android/filament/gltfio/MaterialProvider$MaterialKey"
|
||||
|
||||
class MaterialKeyHelper {
|
||||
public:
|
||||
static MaterialKeyHelper& get();
|
||||
|
||||
void copy(JNIEnv* env, gltfio::MaterialKey& dst, jobject src);
|
||||
void copy(JNIEnv* env, jobject dst, const gltfio::MaterialKey& src);
|
||||
|
||||
void init(JNIEnv* env); // called only from the Java static class constructor
|
||||
|
||||
private:
|
||||
jfieldID doubleSided;
|
||||
jfieldID unlit;
|
||||
jfieldID hasVertexColors;
|
||||
jfieldID hasBaseColorTexture;
|
||||
jfieldID hasNormalTexture;
|
||||
jfieldID hasOcclusionTexture;
|
||||
jfieldID hasEmissiveTexture;
|
||||
jfieldID useSpecularGlossiness;
|
||||
jfieldID alphaMode;
|
||||
jfieldID enableDiagnostics;
|
||||
jfieldID hasMetallicRoughnessTexture;
|
||||
jfieldID metallicRoughnessUV;
|
||||
jfieldID baseColorUV;
|
||||
jfieldID hasClearCoatTexture;
|
||||
jfieldID clearCoatUV;
|
||||
jfieldID hasClearCoatRoughnessTexture;
|
||||
jfieldID clearCoatRoughnessUV;
|
||||
jfieldID hasClearCoatNormalTexture;
|
||||
jfieldID clearCoatNormalUV;
|
||||
jfieldID hasClearCoat;
|
||||
jfieldID hasTransmission;
|
||||
jfieldID hasTextureTransforms;
|
||||
jfieldID emissiveUV;
|
||||
jfieldID aoUV;
|
||||
jfieldID normalUV;
|
||||
jfieldID hasTransmissionTexture;
|
||||
jfieldID transmissionUV;
|
||||
jfieldID hasSheenColorTexture;
|
||||
jfieldID sheenColorUV;
|
||||
jfieldID hasSheenRoughnessTexture;
|
||||
jfieldID sheenRoughnessUV;
|
||||
jfieldID hasVolumeThicknessTexture;
|
||||
jfieldID volumeThicknessUV;
|
||||
jfieldID hasSheen;
|
||||
jfieldID hasIOR;
|
||||
};
|
||||
132
ios/include/backend/BufferDescriptor.h
Normal file
132
ios/include/backend/BufferDescriptor.h
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef TNT_FILAMENT_DRIVER_BUFFERDESCRIPTOR_H
|
||||
#define TNT_FILAMENT_DRIVER_BUFFERDESCRIPTOR_H
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
|
||||
/**
|
||||
* A CPU memory-buffer descriptor, typically used to transfer data from the CPU to the GPU.
|
||||
*
|
||||
* A BufferDescriptor owns the memory buffer it references, therefore BufferDescriptor cannot
|
||||
* be copied, but can be moved.
|
||||
*
|
||||
* BufferDescriptor releases ownership of the memory-buffer when it's destroyed.
|
||||
*/
|
||||
class UTILS_PUBLIC BufferDescriptor {
|
||||
public:
|
||||
/**
|
||||
* Callback used to destroy the buffer data.
|
||||
* Guarantees:
|
||||
* Called on the main filament thread.
|
||||
*
|
||||
* Limitations:
|
||||
* Must be lightweight.
|
||||
* Must not call filament APIs.
|
||||
*/
|
||||
using Callback = void(*)(void* buffer, size_t size, void* user);
|
||||
|
||||
//! creates an empty descriptor
|
||||
BufferDescriptor() noexcept = default;
|
||||
|
||||
//! calls the callback to advertise BufferDescriptor no-longer owns the buffer
|
||||
~BufferDescriptor() noexcept {
|
||||
if (callback) {
|
||||
callback(buffer, size, user);
|
||||
}
|
||||
}
|
||||
|
||||
BufferDescriptor(const BufferDescriptor& rhs) = delete;
|
||||
BufferDescriptor& operator=(const BufferDescriptor& rhs) = delete;
|
||||
|
||||
BufferDescriptor(BufferDescriptor&& rhs) noexcept
|
||||
: buffer(rhs.buffer), size(rhs.size), callback(rhs.callback), user(rhs.user) {
|
||||
rhs.buffer = nullptr;
|
||||
rhs.callback = nullptr;
|
||||
}
|
||||
|
||||
BufferDescriptor& operator=(BufferDescriptor&& rhs) noexcept {
|
||||
if (this != &rhs) {
|
||||
buffer = rhs.buffer;
|
||||
size = rhs.size;
|
||||
callback = rhs.callback;
|
||||
user = rhs.user;
|
||||
rhs.buffer = nullptr;
|
||||
rhs.callback = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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,
|
||||
Callback callback = nullptr, void* user = nullptr) noexcept
|
||||
: buffer(const_cast<void*>(buffer)), size(size), callback(callback), user(user) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set or replace the release callback function
|
||||
* @param callback The new callback function
|
||||
* @param user An opaque user pointer passed to the callbeck function when it's called
|
||||
*/
|
||||
void setCallback(Callback callback, void* user = nullptr) noexcept {
|
||||
this->callback = callback;
|
||||
this->user = user;
|
||||
}
|
||||
|
||||
//! Returns whether a release callback is set
|
||||
bool hasCallback() const noexcept { return callback != nullptr; }
|
||||
|
||||
//! Returns the currently set release callback function
|
||||
Callback getCallback() const noexcept {
|
||||
return callback;
|
||||
}
|
||||
|
||||
//! Returns the user opaque pointer associated to this BufferDescriptor
|
||||
void* getUser() const noexcept {
|
||||
return user;
|
||||
}
|
||||
|
||||
//! CPU mempry-buffer virtual address
|
||||
void* buffer = nullptr;
|
||||
|
||||
//! CPU memory-buffer size in bytes
|
||||
size_t size = 0;
|
||||
|
||||
private:
|
||||
// callback when the buffer is consumed.
|
||||
Callback callback = nullptr;
|
||||
void* user = nullptr;
|
||||
};
|
||||
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
|
||||
#endif // TNT_FILAMENT_DRIVER_BUFFERDESCRIPTOR_H
|
||||
929
ios/include/backend/DriverEnums.h
Normal file
929
ios/include/backend/DriverEnums.h
Normal file
@@ -0,0 +1,929 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef TNT_FILAMENT_DRIVER_DRIVERENUMS_H
|
||||
#define TNT_FILAMENT_DRIVER_DRIVERENUMS_H
|
||||
|
||||
#include <utils/BitmaskEnum.h>
|
||||
#include <utils/unwindows.h> // Because we define ERROR in the FenceStatus enum.
|
||||
|
||||
#include <backend/PresentCallable.h>
|
||||
|
||||
#include <math/vec4.h>
|
||||
|
||||
#include <array> // FIXME: STL headers are not allowed in public headers
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace filament {
|
||||
/**
|
||||
* Types and enums used by filament's driver.
|
||||
*
|
||||
* Effectively these types are public but should not be used directly. Instead use public classes
|
||||
* internal redeclaration of these types.
|
||||
* For e.g. Use Texture::Sampler instead of filament::SamplerType.
|
||||
*/
|
||||
namespace backend {
|
||||
|
||||
static constexpr uint64_t SWAP_CHAIN_CONFIG_TRANSPARENT = 0x1;
|
||||
static constexpr uint64_t SWAP_CHAIN_CONFIG_READABLE = 0x2;
|
||||
static constexpr uint64_t SWAP_CHAIN_CONFIG_ENABLE_XCB = 0x4;
|
||||
static constexpr uint64_t SWAP_CHAIN_CONFIG_APPLE_CVPIXELBUFFER = 0x8;
|
||||
|
||||
static constexpr size_t MAX_VERTEX_ATTRIBUTE_COUNT = 16; // This is guaranteed by OpenGL ES.
|
||||
static constexpr size_t MAX_SAMPLER_COUNT = 16; // Matches the Adreno Vulkan driver.
|
||||
static constexpr size_t MAX_VERTEX_BUFFER_COUNT = 16; // Max number of bound buffer objects.
|
||||
|
||||
static_assert(MAX_VERTEX_BUFFER_COUNT <= MAX_VERTEX_ATTRIBUTE_COUNT,
|
||||
"The number of buffer objects that can be attached to a VertexBuffer must be "
|
||||
"less than or equal to the maximum number of vertex attributes.");
|
||||
|
||||
static constexpr size_t CONFIG_BINDING_COUNT = 8;
|
||||
|
||||
/**
|
||||
* Selects which driver a particular Engine should use.
|
||||
*/
|
||||
enum class Backend : uint8_t {
|
||||
DEFAULT = 0, //!< Automatically selects an appropriate driver for the platform.
|
||||
OPENGL = 1, //!< Selects the OpenGL/ES driver (default on Android)
|
||||
VULKAN = 2, //!< Selects the Vulkan driver if the platform supports it (default on Linux/Windows)
|
||||
METAL = 3, //!< Selects the Metal driver if the platform supports it (default on MacOS/iOS).
|
||||
NOOP = 4, //!< Selects the no-op driver for testing purposes.
|
||||
};
|
||||
|
||||
static constexpr const char* backendToString(Backend backend) {
|
||||
switch (backend) {
|
||||
case Backend::NOOP:
|
||||
return "Noop";
|
||||
case Backend::OPENGL:
|
||||
return "OpenGL";
|
||||
case Backend::VULKAN:
|
||||
return "Vulkan";
|
||||
case Backend::METAL:
|
||||
return "Metal";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Bitmask for selecting render buffers
|
||||
*/
|
||||
enum class TargetBufferFlags : uint32_t {
|
||||
NONE = 0x0u, //!< No buffer selected.
|
||||
COLOR0 = 0x00000001u, //!< Color buffer selected.
|
||||
COLOR1 = 0x00000002u, //!< Color buffer selected.
|
||||
COLOR2 = 0x00000004u, //!< Color buffer selected.
|
||||
COLOR3 = 0x00000008u, //!< Color buffer selected.
|
||||
COLOR4 = 0x00000010u, //!< Color buffer selected.
|
||||
COLOR5 = 0x00000020u, //!< Color buffer selected.
|
||||
COLOR6 = 0x00000040u, //!< Color buffer selected.
|
||||
COLOR7 = 0x00000080u, //!< Color buffer selected.
|
||||
|
||||
COLOR = COLOR0, //!< \deprecated
|
||||
COLOR_ALL = COLOR0 | COLOR1 | COLOR2 | COLOR3 | COLOR4 | COLOR5 | COLOR6 | COLOR7,
|
||||
DEPTH = 0x10000000u, //!< Depth buffer selected.
|
||||
STENCIL = 0x20000000u, //!< Stencil buffer selected.
|
||||
DEPTH_AND_STENCIL = DEPTH | STENCIL, //!< depth and stencil buffer selected.
|
||||
ALL = COLOR_ALL | DEPTH | STENCIL //!< Color, depth and stencil buffer selected.
|
||||
};
|
||||
|
||||
inline constexpr TargetBufferFlags getTargetBufferFlagsAt(size_t index) noexcept {
|
||||
if (index == 0u) return TargetBufferFlags::COLOR0;
|
||||
if (index == 1u) return TargetBufferFlags::COLOR1;
|
||||
if (index == 2u) return TargetBufferFlags::COLOR2;
|
||||
if (index == 3u) return TargetBufferFlags::COLOR3;
|
||||
if (index == 4u) return TargetBufferFlags::COLOR4;
|
||||
if (index == 5u) return TargetBufferFlags::COLOR5;
|
||||
if (index == 6u) return TargetBufferFlags::COLOR6;
|
||||
if (index == 7u) return TargetBufferFlags::COLOR7;
|
||||
if (index == 8u) return TargetBufferFlags::DEPTH;
|
||||
if (index == 9u) return TargetBufferFlags::STENCIL;
|
||||
return TargetBufferFlags::NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Frequency at which a buffer is expected to be modified and used. This is used as an hint
|
||||
* for the driver to make better decisions about managing memory internally.
|
||||
*/
|
||||
enum class BufferUsage : uint8_t {
|
||||
STATIC, //!< content modified once, used many times
|
||||
DYNAMIC, //!< content modified frequently, used many times
|
||||
STREAM, //!< content invalidated and modified frequently, used many times
|
||||
};
|
||||
|
||||
/**
|
||||
* Defines a viewport, which is the origin and extent of the clip-space.
|
||||
* All drawing is clipped to the viewport.
|
||||
*/
|
||||
struct Viewport {
|
||||
int32_t left; //!< left coordinate in window space.
|
||||
int32_t bottom; //!< bottom coordinate in window space.
|
||||
uint32_t width; //!< width in pixels
|
||||
uint32_t height; //!< height in pixels
|
||||
//! get the right coordinate in window space of the viewport
|
||||
int32_t right() const noexcept { return left + width; }
|
||||
//! get the top coordinate in window space of the viewport
|
||||
int32_t top() const noexcept { return bottom + height; }
|
||||
};
|
||||
|
||||
/**
|
||||
* Specifies the mapping of the near and far clipping plane to window coordinates.
|
||||
*/
|
||||
struct DepthRange {
|
||||
float near = 0.0f; //!< mapping of the near plane to window coordinates.
|
||||
float far = 1.0f; //!< mapping of the far plane to window coordinates.
|
||||
};
|
||||
|
||||
/**
|
||||
* Error codes for Fence::wait()
|
||||
* @see Fence, Fence::wait()
|
||||
*/
|
||||
enum class FenceStatus : int8_t {
|
||||
ERROR = -1, //!< An error occured. The Fence condition is not satisfied.
|
||||
CONDITION_SATISFIED = 0, //!< The Fence condition is satisfied.
|
||||
TIMEOUT_EXPIRED = 1, //!< wait()'s timeout expired. The Fence condition is not satisfied.
|
||||
};
|
||||
|
||||
/**
|
||||
* Status codes for sync objects
|
||||
*/
|
||||
enum class SyncStatus : int8_t {
|
||||
ERROR = -1, //!< An error occured. The Sync is not signaled.
|
||||
SIGNALED = 0, //!< The Sync is signaled.
|
||||
NOT_SIGNALED = 1, //!< The Sync is not signaled yet
|
||||
};
|
||||
|
||||
static constexpr uint64_t FENCE_WAIT_FOR_EVER = uint64_t(-1);
|
||||
|
||||
/**
|
||||
* Shader model.
|
||||
*
|
||||
* These enumerants are used across all backends and refer to a level of functionality, rather
|
||||
* than to an OpenGL specific shader model.
|
||||
*/
|
||||
enum class ShaderModel : uint8_t {
|
||||
//! For testing
|
||||
UNKNOWN = 0,
|
||||
GL_ES_30 = 1, //!< Mobile level functionality
|
||||
GL_CORE_41 = 2, //!< Desktop level functionality
|
||||
};
|
||||
static constexpr size_t SHADER_MODEL_COUNT = 3;
|
||||
|
||||
/**
|
||||
* Primitive types
|
||||
*/
|
||||
enum class PrimitiveType : uint8_t {
|
||||
// don't change the enums values (made to match GL)
|
||||
POINTS = 0, //!< points
|
||||
LINES = 1, //!< lines
|
||||
TRIANGLES = 4, //!< triangles
|
||||
NONE = 0xFF
|
||||
};
|
||||
|
||||
/**
|
||||
* Supported uniform types
|
||||
*/
|
||||
enum class UniformType : uint8_t {
|
||||
BOOL,
|
||||
BOOL2,
|
||||
BOOL3,
|
||||
BOOL4,
|
||||
FLOAT,
|
||||
FLOAT2,
|
||||
FLOAT3,
|
||||
FLOAT4,
|
||||
INT,
|
||||
INT2,
|
||||
INT3,
|
||||
INT4,
|
||||
UINT,
|
||||
UINT2,
|
||||
UINT3,
|
||||
UINT4,
|
||||
MAT3, //!< a 3x3 float matrix
|
||||
MAT4 //!< a 4x4 float matrix
|
||||
};
|
||||
|
||||
enum class Precision : uint8_t {
|
||||
LOW,
|
||||
MEDIUM,
|
||||
HIGH,
|
||||
DEFAULT
|
||||
};
|
||||
|
||||
//! Texture sampler type
|
||||
enum class SamplerType : uint8_t {
|
||||
SAMPLER_2D, //!< 2D texture
|
||||
SAMPLER_2D_ARRAY, //!< 2D array texture
|
||||
SAMPLER_CUBEMAP, //!< Cube map texture
|
||||
SAMPLER_EXTERNAL, //!< External texture
|
||||
SAMPLER_3D, //!< 3D texture
|
||||
};
|
||||
|
||||
//! Subpass type
|
||||
enum class SubpassType : uint8_t {
|
||||
SUBPASS_INPUT
|
||||
};
|
||||
|
||||
//! Texture sampler format
|
||||
enum class SamplerFormat : uint8_t {
|
||||
INT = 0, //!< signed integer sampler
|
||||
UINT = 1, //!< unsigned integer sampler
|
||||
FLOAT = 2, //!< float sampler
|
||||
SHADOW = 3 //!< shadow sampler (PCF)
|
||||
};
|
||||
|
||||
/**
|
||||
* Supported element types
|
||||
*/
|
||||
enum class ElementType : uint8_t {
|
||||
BYTE,
|
||||
BYTE2,
|
||||
BYTE3,
|
||||
BYTE4,
|
||||
UBYTE,
|
||||
UBYTE2,
|
||||
UBYTE3,
|
||||
UBYTE4,
|
||||
SHORT,
|
||||
SHORT2,
|
||||
SHORT3,
|
||||
SHORT4,
|
||||
USHORT,
|
||||
USHORT2,
|
||||
USHORT3,
|
||||
USHORT4,
|
||||
INT,
|
||||
UINT,
|
||||
FLOAT,
|
||||
FLOAT2,
|
||||
FLOAT3,
|
||||
FLOAT4,
|
||||
HALF,
|
||||
HALF2,
|
||||
HALF3,
|
||||
HALF4,
|
||||
};
|
||||
|
||||
//! Buffer object binding type
|
||||
enum class BufferObjectBinding : uint8_t {
|
||||
VERTEX,
|
||||
UNIFORM
|
||||
};
|
||||
|
||||
//! Face culling Mode
|
||||
enum class CullingMode : uint8_t {
|
||||
NONE, //!< No culling, front and back faces are visible
|
||||
FRONT, //!< Front face culling, only back faces are visible
|
||||
BACK, //!< Back face culling, only front faces are visible
|
||||
FRONT_AND_BACK //!< Front and Back, geometry is not visible
|
||||
};
|
||||
|
||||
//! Pixel Data Format
|
||||
enum class PixelDataFormat : uint8_t {
|
||||
R, //!< One Red channel, float
|
||||
R_INTEGER, //!< One Red channel, integer
|
||||
RG, //!< Two Red and Green channels, float
|
||||
RG_INTEGER, //!< Two Red and Green channels, integer
|
||||
RGB, //!< Three Red, Green and Blue channels, float
|
||||
RGB_INTEGER, //!< Three Red, Green and Blue channels, integer
|
||||
RGBA, //!< Four Red, Green, Blue and Alpha channels, float
|
||||
RGBA_INTEGER, //!< Four Red, Green, Blue and Alpha channels, integer
|
||||
UNUSED, // used to be rgbm
|
||||
DEPTH_COMPONENT, //!< Depth, 16-bit or 24-bits usually
|
||||
DEPTH_STENCIL, //!< Two Depth (24-bits) + Stencil (8-bits) channels
|
||||
ALPHA //! One Alpha channel, float
|
||||
};
|
||||
|
||||
//! Pixel Data Type
|
||||
enum class PixelDataType : uint8_t {
|
||||
UBYTE, //!< unsigned byte
|
||||
BYTE, //!< signed byte
|
||||
USHORT, //!< unsigned short (16-bit)
|
||||
SHORT, //!< signed short (16-bit)
|
||||
UINT, //!< unsigned int (16-bit)
|
||||
INT, //!< signed int (32-bit)
|
||||
HALF, //!< half-float (16-bit float)
|
||||
FLOAT, //!< float (32-bits float)
|
||||
COMPRESSED, //!< compressed pixels, @see CompressedPixelDataType
|
||||
UINT_10F_11F_11F_REV, //!< three low precision floating-point numbers
|
||||
USHORT_565, //!< unsigned int (16-bit), encodes 3 RGB channels
|
||||
UINT_2_10_10_10_REV, //!< unsigned normalized 10 bits RGB, 2 bits alpha
|
||||
};
|
||||
|
||||
//! Compressed pixel data types
|
||||
enum class CompressedPixelDataType : uint16_t {
|
||||
// Mandatory in GLES 3.0 and GL 4.3
|
||||
EAC_R11, EAC_R11_SIGNED, EAC_RG11, EAC_RG11_SIGNED,
|
||||
ETC2_RGB8, ETC2_SRGB8,
|
||||
ETC2_RGB8_A1, ETC2_SRGB8_A1,
|
||||
ETC2_EAC_RGBA8, ETC2_EAC_SRGBA8,
|
||||
|
||||
// Available everywhere except Android/iOS
|
||||
DXT1_RGB, DXT1_RGBA, DXT3_RGBA, DXT5_RGBA,
|
||||
DXT1_SRGB, DXT1_SRGBA, DXT3_SRGBA, DXT5_SRGBA,
|
||||
|
||||
// ASTC formats are available with a GLES extension
|
||||
RGBA_ASTC_4x4,
|
||||
RGBA_ASTC_5x4,
|
||||
RGBA_ASTC_5x5,
|
||||
RGBA_ASTC_6x5,
|
||||
RGBA_ASTC_6x6,
|
||||
RGBA_ASTC_8x5,
|
||||
RGBA_ASTC_8x6,
|
||||
RGBA_ASTC_8x8,
|
||||
RGBA_ASTC_10x5,
|
||||
RGBA_ASTC_10x6,
|
||||
RGBA_ASTC_10x8,
|
||||
RGBA_ASTC_10x10,
|
||||
RGBA_ASTC_12x10,
|
||||
RGBA_ASTC_12x12,
|
||||
SRGB8_ALPHA8_ASTC_4x4,
|
||||
SRGB8_ALPHA8_ASTC_5x4,
|
||||
SRGB8_ALPHA8_ASTC_5x5,
|
||||
SRGB8_ALPHA8_ASTC_6x5,
|
||||
SRGB8_ALPHA8_ASTC_6x6,
|
||||
SRGB8_ALPHA8_ASTC_8x5,
|
||||
SRGB8_ALPHA8_ASTC_8x6,
|
||||
SRGB8_ALPHA8_ASTC_8x8,
|
||||
SRGB8_ALPHA8_ASTC_10x5,
|
||||
SRGB8_ALPHA8_ASTC_10x6,
|
||||
SRGB8_ALPHA8_ASTC_10x8,
|
||||
SRGB8_ALPHA8_ASTC_10x10,
|
||||
SRGB8_ALPHA8_ASTC_12x10,
|
||||
SRGB8_ALPHA8_ASTC_12x12,
|
||||
};
|
||||
|
||||
/** Supported texel formats
|
||||
* These formats are typically used to specify a texture's internal storage format.
|
||||
*
|
||||
* Enumerants syntax format
|
||||
* ========================
|
||||
*
|
||||
* `[components][size][type]`
|
||||
*
|
||||
* `components` : List of stored components by this format.\n
|
||||
* `size` : Size in bit of each component.\n
|
||||
* `type` : Type this format is stored as.\n
|
||||
*
|
||||
*
|
||||
* Name | Component
|
||||
* :--------|:-------------------------------
|
||||
* R | Linear Red
|
||||
* RG | Linear Red, Green
|
||||
* RGB | Linear Red, Green, Blue
|
||||
* RGBA | Linear Red, Green Blue, Alpha
|
||||
* SRGB | sRGB encoded Red, Green, Blue
|
||||
* DEPTH | Depth
|
||||
* STENCIL | Stencil
|
||||
*
|
||||
* \n
|
||||
* Name | Type
|
||||
* :--------|:---------------------------------------------------
|
||||
* (none) | Unsigned Normalized Integer [0, 1]
|
||||
* _SNORM | Signed Normalized Integer [-1, 1]
|
||||
* UI | Unsigned Integer @f$ [0, 2^{size}] @f$
|
||||
* I | Signed Integer @f$ [-2^{size-1}, 2^{size-1}-1] @f$
|
||||
* F | Floating-point
|
||||
*
|
||||
*
|
||||
* Special color formats
|
||||
* ---------------------
|
||||
*
|
||||
* There are a few special color formats that don't follow the convention above:
|
||||
*
|
||||
* Name | Format
|
||||
* :----------------|:--------------------------------------------------------------------------
|
||||
* RGB565 | 5-bits for R and B, 6-bits for G.
|
||||
* RGB5_A1 | 5-bits for R, G and B, 1-bit for A.
|
||||
* RGB10_A2 | 10-bits for R, G and B, 2-bits for A.
|
||||
* RGB9_E5 | **Unsigned** floating point. 9-bits mantissa for RGB, 5-bits shared exponent
|
||||
* R11F_G11F_B10F | **Unsigned** floating point. 6-bits mantissa, for R and G, 5-bits for B. 5-bits exponent.
|
||||
* SRGB8_A8 | sRGB 8-bits with linear 8-bits alpha.
|
||||
* DEPTH24_STENCIL8 | 24-bits unsigned normalized integer depth, 8-bits stencil.
|
||||
* DEPTH32F_STENCIL8| 32-bits floating-point depth, 8-bits stencil.
|
||||
*
|
||||
*
|
||||
* Compressed texture formats
|
||||
* --------------------------
|
||||
*
|
||||
* Many compressed texture formats are supported as well, which include (but are not limited to)
|
||||
* the following list:
|
||||
*
|
||||
* Name | Format
|
||||
* :----------------|:--------------------------------------------------------------------------
|
||||
* EAC_R11 | Compresses R11UI
|
||||
* EAC_R11_SIGNED | Compresses R11I
|
||||
* EAC_RG11 | Compresses RG11UI
|
||||
* EAC_RG11_SIGNED | Compresses RG11I
|
||||
* ETC2_RGB8 | Compresses RGB8
|
||||
* ETC2_SRGB8 | compresses SRGB8
|
||||
* ETC2_EAC_RGBA8 | Compresses RGBA8
|
||||
* ETC2_EAC_SRGBA8 | Compresses SRGB8_A8
|
||||
* ETC2_RGB8_A1 | Compresses RGB8 with 1-bit alpha
|
||||
* ETC2_SRGB8_A1 | Compresses sRGB8 with 1-bit alpha
|
||||
*
|
||||
*
|
||||
* @see Texture
|
||||
*/
|
||||
enum class TextureFormat : uint16_t {
|
||||
// 8-bits per element
|
||||
R8, R8_SNORM, R8UI, R8I, STENCIL8,
|
||||
|
||||
// 16-bits per element
|
||||
R16F, R16UI, R16I,
|
||||
RG8, RG8_SNORM, RG8UI, RG8I,
|
||||
RGB565,
|
||||
RGB9_E5, // 9995 is actually 32 bpp but it's here for historical reasons.
|
||||
RGB5_A1,
|
||||
RGBA4,
|
||||
DEPTH16,
|
||||
|
||||
// 24-bits per element
|
||||
RGB8, SRGB8, RGB8_SNORM, RGB8UI, RGB8I,
|
||||
DEPTH24,
|
||||
|
||||
// 32-bits per element
|
||||
R32F, R32UI, R32I,
|
||||
RG16F, RG16UI, RG16I,
|
||||
R11F_G11F_B10F,
|
||||
RGBA8, SRGB8_A8,RGBA8_SNORM,
|
||||
UNUSED, // used to be rgbm
|
||||
RGB10_A2, RGBA8UI, RGBA8I,
|
||||
DEPTH32F, DEPTH24_STENCIL8, DEPTH32F_STENCIL8,
|
||||
|
||||
// 48-bits per element
|
||||
RGB16F, RGB16UI, RGB16I,
|
||||
|
||||
// 64-bits per element
|
||||
RG32F, RG32UI, RG32I,
|
||||
RGBA16F, RGBA16UI, RGBA16I,
|
||||
|
||||
// 96-bits per element
|
||||
RGB32F, RGB32UI, RGB32I,
|
||||
|
||||
// 128-bits per element
|
||||
RGBA32F, RGBA32UI, RGBA32I,
|
||||
|
||||
// compressed formats
|
||||
|
||||
// Mandatory in GLES 3.0 and GL 4.3
|
||||
EAC_R11, EAC_R11_SIGNED, EAC_RG11, EAC_RG11_SIGNED,
|
||||
ETC2_RGB8, ETC2_SRGB8,
|
||||
ETC2_RGB8_A1, ETC2_SRGB8_A1,
|
||||
ETC2_EAC_RGBA8, ETC2_EAC_SRGBA8,
|
||||
|
||||
// Available everywhere except Android/iOS
|
||||
DXT1_RGB, DXT1_RGBA, DXT3_RGBA, DXT5_RGBA,
|
||||
DXT1_SRGB, DXT1_SRGBA, DXT3_SRGBA, DXT5_SRGBA,
|
||||
|
||||
// ASTC formats are available with a GLES extension
|
||||
RGBA_ASTC_4x4,
|
||||
RGBA_ASTC_5x4,
|
||||
RGBA_ASTC_5x5,
|
||||
RGBA_ASTC_6x5,
|
||||
RGBA_ASTC_6x6,
|
||||
RGBA_ASTC_8x5,
|
||||
RGBA_ASTC_8x6,
|
||||
RGBA_ASTC_8x8,
|
||||
RGBA_ASTC_10x5,
|
||||
RGBA_ASTC_10x6,
|
||||
RGBA_ASTC_10x8,
|
||||
RGBA_ASTC_10x10,
|
||||
RGBA_ASTC_12x10,
|
||||
RGBA_ASTC_12x12,
|
||||
SRGB8_ALPHA8_ASTC_4x4,
|
||||
SRGB8_ALPHA8_ASTC_5x4,
|
||||
SRGB8_ALPHA8_ASTC_5x5,
|
||||
SRGB8_ALPHA8_ASTC_6x5,
|
||||
SRGB8_ALPHA8_ASTC_6x6,
|
||||
SRGB8_ALPHA8_ASTC_8x5,
|
||||
SRGB8_ALPHA8_ASTC_8x6,
|
||||
SRGB8_ALPHA8_ASTC_8x8,
|
||||
SRGB8_ALPHA8_ASTC_10x5,
|
||||
SRGB8_ALPHA8_ASTC_10x6,
|
||||
SRGB8_ALPHA8_ASTC_10x8,
|
||||
SRGB8_ALPHA8_ASTC_10x10,
|
||||
SRGB8_ALPHA8_ASTC_12x10,
|
||||
SRGB8_ALPHA8_ASTC_12x12,
|
||||
};
|
||||
|
||||
//! Bitmask describing the intended Texture Usage
|
||||
enum class TextureUsage : uint8_t {
|
||||
NONE = 0x0,
|
||||
COLOR_ATTACHMENT = 0x1, //!< Texture can be used as a color attachment
|
||||
DEPTH_ATTACHMENT = 0x2, //!< Texture can be used as a depth attachment
|
||||
STENCIL_ATTACHMENT = 0x4, //!< Texture can be used as a stencil attachment
|
||||
UPLOADABLE = 0x8, //!< Data can be uploaded into this texture (default)
|
||||
SAMPLEABLE = 0x10, //!< Texture can be sampled (default)
|
||||
SUBPASS_INPUT = 0x20, //!< Texture can be used as a subpass input
|
||||
DEFAULT = UPLOADABLE | SAMPLEABLE //!< Default texture usage
|
||||
};
|
||||
|
||||
//! Texture swizzle
|
||||
enum class TextureSwizzle : uint8_t {
|
||||
SUBSTITUTE_ZERO,
|
||||
SUBSTITUTE_ONE,
|
||||
CHANNEL_0,
|
||||
CHANNEL_1,
|
||||
CHANNEL_2,
|
||||
CHANNEL_3
|
||||
};
|
||||
|
||||
//! returns whether this format a depth format
|
||||
static constexpr bool isDepthFormat(TextureFormat format) noexcept {
|
||||
switch (format) {
|
||||
case TextureFormat::DEPTH32F:
|
||||
case TextureFormat::DEPTH24:
|
||||
case TextureFormat::DEPTH16:
|
||||
case TextureFormat::DEPTH32F_STENCIL8:
|
||||
case TextureFormat::DEPTH24_STENCIL8:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//! returns whether this format a compressed format
|
||||
static constexpr bool isCompressedFormat(TextureFormat format) noexcept {
|
||||
return format >= TextureFormat::EAC_R11;
|
||||
}
|
||||
|
||||
//! returns whether this format is an ETC2 compressed format
|
||||
static constexpr bool isETC2Compression(TextureFormat format) noexcept {
|
||||
return format >= TextureFormat::EAC_R11 && format <= TextureFormat::ETC2_EAC_SRGBA8;
|
||||
}
|
||||
|
||||
//! returns whether this format is an ETC3 compressed format
|
||||
static constexpr bool isS3TCCompression(TextureFormat format) noexcept {
|
||||
return format >= TextureFormat::DXT1_RGB && format <= TextureFormat::DXT5_SRGBA;
|
||||
}
|
||||
|
||||
static constexpr bool isS3TCSRGBCompression(TextureFormat format) noexcept {
|
||||
return format >= TextureFormat::DXT1_SRGB && format <= TextureFormat::DXT5_SRGBA;
|
||||
}
|
||||
|
||||
//! Texture Cubemap Face
|
||||
enum class TextureCubemapFace : uint8_t {
|
||||
// don't change the enums values
|
||||
POSITIVE_X = 0, //!< +x face
|
||||
NEGATIVE_X = 1, //!< -x face
|
||||
POSITIVE_Y = 2, //!< +y face
|
||||
NEGATIVE_Y = 3, //!< -y face
|
||||
POSITIVE_Z = 4, //!< +z face
|
||||
NEGATIVE_Z = 5, //!< -z face
|
||||
};
|
||||
|
||||
//! Face offsets for all faces of a cubemap
|
||||
struct FaceOffsets {
|
||||
using size_type = size_t;
|
||||
union {
|
||||
struct {
|
||||
size_type px; //!< +x face offset in bytes
|
||||
size_type nx; //!< -x face offset in bytes
|
||||
size_type py; //!< +y face offset in bytes
|
||||
size_type ny; //!< -y face offset in bytes
|
||||
size_type pz; //!< +z face offset in bytes
|
||||
size_type nz; //!< -z face offset in bytes
|
||||
};
|
||||
size_type offsets[6];
|
||||
};
|
||||
size_type operator[](size_t n) const noexcept { return offsets[n]; }
|
||||
size_type& operator[](size_t n) { return offsets[n]; }
|
||||
FaceOffsets() noexcept = default;
|
||||
explicit FaceOffsets(size_type faceSize) noexcept {
|
||||
px = faceSize * 0;
|
||||
nx = faceSize * 1;
|
||||
py = faceSize * 2;
|
||||
ny = faceSize * 3;
|
||||
pz = faceSize * 4;
|
||||
nz = faceSize * 5;
|
||||
}
|
||||
FaceOffsets(const FaceOffsets& rhs) noexcept {
|
||||
px = rhs.px;
|
||||
nx = rhs.nx;
|
||||
py = rhs.py;
|
||||
ny = rhs.ny;
|
||||
pz = rhs.pz;
|
||||
nz = rhs.nz;
|
||||
}
|
||||
FaceOffsets& operator=(const FaceOffsets& rhs) noexcept {
|
||||
px = rhs.px;
|
||||
nx = rhs.nx;
|
||||
py = rhs.py;
|
||||
ny = rhs.ny;
|
||||
pz = rhs.pz;
|
||||
nz = rhs.nz;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
//! Sampler Wrap mode
|
||||
enum class SamplerWrapMode : uint8_t {
|
||||
CLAMP_TO_EDGE, //!< clamp-to-edge. The edge of the texture extends to infinity.
|
||||
REPEAT, //!< repeat. The texture infinitely repeats in the wrap direction.
|
||||
MIRRORED_REPEAT, //!< mirrored-repeat. The texture infinitely repeats and mirrors in the wrap direction.
|
||||
};
|
||||
|
||||
//! Sampler minification filter
|
||||
enum class SamplerMinFilter : uint8_t {
|
||||
// don't change the enums values
|
||||
NEAREST = 0, //!< No filtering. Nearest neighbor is used.
|
||||
LINEAR = 1, //!< Box filtering. Weighted average of 4 neighbors is used.
|
||||
NEAREST_MIPMAP_NEAREST = 2, //!< Mip-mapping is activated. But no filtering occurs.
|
||||
LINEAR_MIPMAP_NEAREST = 3, //!< Box filtering within a mip-map level.
|
||||
NEAREST_MIPMAP_LINEAR = 4, //!< Mip-map levels are interpolated, but no other filtering occurs.
|
||||
LINEAR_MIPMAP_LINEAR = 5 //!< Both interpolated Mip-mapping and linear filtering are used.
|
||||
};
|
||||
|
||||
//! Sampler magnification filter
|
||||
enum class SamplerMagFilter : uint8_t {
|
||||
// don't change the enums values
|
||||
NEAREST = 0, //!< No filtering. Nearest neighbor is used.
|
||||
LINEAR = 1, //!< Box filtering. Weighted average of 4 neighbors is used.
|
||||
};
|
||||
|
||||
//! Sampler compare mode
|
||||
enum class SamplerCompareMode : uint8_t {
|
||||
// don't change the enums values
|
||||
NONE = 0,
|
||||
COMPARE_TO_TEXTURE = 1
|
||||
};
|
||||
|
||||
//! comparison function for the depth sampler
|
||||
enum class SamplerCompareFunc : uint8_t {
|
||||
// don't change the enums values
|
||||
LE = 0, //!< Less or equal
|
||||
GE, //!< Greater or equal
|
||||
L, //!< Strictly less than
|
||||
G, //!< Strictly greater than
|
||||
E, //!< Equal
|
||||
NE, //!< Not equal
|
||||
A, //!< Always. Depth testing is deactivated.
|
||||
N //!< Never. The depth test always fails.
|
||||
};
|
||||
|
||||
//! Sampler paramters
|
||||
struct SamplerParams { // NOLINT
|
||||
union {
|
||||
struct {
|
||||
SamplerMagFilter filterMag : 1; //!< magnification filter (NEAREST)
|
||||
SamplerMinFilter filterMin : 3; //!< minification filter (NEAREST)
|
||||
SamplerWrapMode wrapS : 2; //!< s-coordinate wrap mode (CLAMP_TO_EDGE)
|
||||
SamplerWrapMode wrapT : 2; //!< t-coordinate wrap mode (CLAMP_TO_EDGE)
|
||||
|
||||
SamplerWrapMode wrapR : 2; //!< r-coordinate wrap mode (CLAMP_TO_EDGE)
|
||||
uint8_t anisotropyLog2 : 3; //!< anisotropy level (0)
|
||||
SamplerCompareMode compareMode : 1; //!< sampler compare mode (NONE)
|
||||
uint8_t padding0 : 2; //!< reserved. must be 0.
|
||||
|
||||
SamplerCompareFunc compareFunc : 3; //!< sampler comparison function (LE)
|
||||
uint8_t padding1 : 5; //!< reserved. must be 0.
|
||||
|
||||
uint8_t padding2 : 8; //!< reserved. must be 0.
|
||||
};
|
||||
uint32_t u;
|
||||
};
|
||||
private:
|
||||
friend inline bool operator < (SamplerParams lhs, SamplerParams rhs) {
|
||||
return lhs.u < rhs.u;
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(sizeof(SamplerParams) == sizeof(uint32_t), "SamplerParams must be 32 bits");
|
||||
|
||||
//! blending equation function
|
||||
enum class BlendEquation : uint8_t {
|
||||
ADD, //!< the fragment is added to the color buffer
|
||||
SUBTRACT, //!< the fragment is subtracted from the color buffer
|
||||
REVERSE_SUBTRACT, //!< the color buffer is subtracted from the fragment
|
||||
MIN, //!< the min between the fragment and color buffer
|
||||
MAX //!< the max between the fragment and color buffer
|
||||
};
|
||||
|
||||
//! blending function
|
||||
enum class BlendFunction : uint8_t {
|
||||
ZERO, //!< f(src, dst) = 0
|
||||
ONE, //!< f(src, dst) = 1
|
||||
SRC_COLOR, //!< f(src, dst) = src
|
||||
ONE_MINUS_SRC_COLOR, //!< f(src, dst) = 1-src
|
||||
DST_COLOR, //!< f(src, dst) = dst
|
||||
ONE_MINUS_DST_COLOR, //!< f(src, dst) = 1-dst
|
||||
SRC_ALPHA, //!< f(src, dst) = src.a
|
||||
ONE_MINUS_SRC_ALPHA, //!< f(src, dst) = 1-src.a
|
||||
DST_ALPHA, //!< f(src, dst) = dst.a
|
||||
ONE_MINUS_DST_ALPHA, //!< f(src, dst) = 1-dst.a
|
||||
SRC_ALPHA_SATURATE //!< f(src, dst) = (1,1,1) * min(src.a, 1 - dst.a), 1
|
||||
};
|
||||
|
||||
//! Stream for external textures
|
||||
enum class StreamType {
|
||||
NATIVE, //!< Not synchronized but copy-free. Good for video.
|
||||
TEXTURE_ID, //!< Synchronized, but GL-only and incurs copies. Good for AR on devices before API 26.
|
||||
ACQUIRED, //!< Synchronized, copy-free, and take a release callback. Good for AR but requires API 26+.
|
||||
};
|
||||
|
||||
//! Releases an ACQUIRED external texture, guaranteed to be called on the application thread.
|
||||
using StreamCallback = void(*)(void* image, void* user);
|
||||
|
||||
//! Vertex attribute descriptor
|
||||
struct Attribute {
|
||||
//! attribute is normalized (remapped between 0 and 1)
|
||||
static constexpr uint8_t FLAG_NORMALIZED = 0x1;
|
||||
//! attribute is an integer
|
||||
static constexpr uint8_t FLAG_INTEGER_TARGET = 0x2;
|
||||
static constexpr uint8_t BUFFER_UNUSED = 0xFF;
|
||||
uint32_t offset = 0; //!< attribute offset in bytes
|
||||
uint8_t stride = 0; //!< attribute stride in bytes
|
||||
uint8_t buffer = BUFFER_UNUSED; //!< attribute buffer index
|
||||
ElementType type = ElementType::BYTE; //!< attribute element type
|
||||
uint8_t flags = 0x0; //!< attribute flags
|
||||
};
|
||||
|
||||
using AttributeArray = std::array<Attribute, MAX_VERTEX_ATTRIBUTE_COUNT>;
|
||||
|
||||
//! Raster state descriptor
|
||||
struct RasterState {
|
||||
|
||||
using CullingMode = CullingMode;
|
||||
using DepthFunc = SamplerCompareFunc;
|
||||
using BlendEquation = BlendEquation;
|
||||
using BlendFunction = BlendFunction;
|
||||
|
||||
RasterState() noexcept { // NOLINT
|
||||
static_assert(sizeof(RasterState) == sizeof(uint32_t),
|
||||
"RasterState size not what was intended");
|
||||
culling = CullingMode::BACK;
|
||||
blendEquationRGB = BlendEquation::ADD;
|
||||
blendEquationAlpha = BlendEquation::ADD;
|
||||
blendFunctionSrcRGB = BlendFunction::ONE;
|
||||
blendFunctionSrcAlpha = BlendFunction::ONE;
|
||||
blendFunctionDstRGB = BlendFunction::ZERO;
|
||||
blendFunctionDstAlpha = BlendFunction::ZERO;
|
||||
}
|
||||
|
||||
bool operator == (RasterState rhs) const noexcept { return u == rhs.u; }
|
||||
bool operator != (RasterState rhs) const noexcept { return u != rhs.u; }
|
||||
|
||||
void disableBlending() noexcept {
|
||||
blendEquationRGB = BlendEquation::ADD;
|
||||
blendEquationAlpha = BlendEquation::ADD;
|
||||
blendFunctionSrcRGB = BlendFunction::ONE;
|
||||
blendFunctionSrcAlpha = BlendFunction::ONE;
|
||||
blendFunctionDstRGB = BlendFunction::ZERO;
|
||||
blendFunctionDstAlpha = BlendFunction::ZERO;
|
||||
}
|
||||
|
||||
// note: clang reduces this entire function to a simple load/mask/compare
|
||||
bool hasBlending() const noexcept {
|
||||
// This is used to decide if blending needs to be enabled in the h/w
|
||||
return !(blendEquationRGB == BlendEquation::ADD &&
|
||||
blendEquationAlpha == BlendEquation::ADD &&
|
||||
blendFunctionSrcRGB == BlendFunction::ONE &&
|
||||
blendFunctionSrcAlpha == BlendFunction::ONE &&
|
||||
blendFunctionDstRGB == BlendFunction::ZERO &&
|
||||
blendFunctionDstAlpha == BlendFunction::ZERO);
|
||||
}
|
||||
|
||||
union {
|
||||
struct {
|
||||
//! culling mode
|
||||
CullingMode culling : 2; // 2
|
||||
|
||||
//! blend equation for the red, green and blue components
|
||||
BlendEquation blendEquationRGB : 3; // 5
|
||||
//! blend equation for the alpha component
|
||||
BlendEquation blendEquationAlpha : 3; // 8
|
||||
|
||||
//! blending function for the source color
|
||||
BlendFunction blendFunctionSrcRGB : 4; // 12
|
||||
//! blending function for the source alpha
|
||||
BlendFunction blendFunctionSrcAlpha : 4; // 16
|
||||
//! blending function for the destination color
|
||||
BlendFunction blendFunctionDstRGB : 4; // 20
|
||||
//! blending function for the destination alpha
|
||||
BlendFunction blendFunctionDstAlpha : 4; // 24
|
||||
|
||||
//! Whether depth-buffer writes are enabled
|
||||
bool depthWrite : 1; // 25
|
||||
//! Depth test function
|
||||
DepthFunc depthFunc : 3; // 28
|
||||
|
||||
//! Whether color-buffer writes are enabled
|
||||
bool colorWrite : 1; // 29
|
||||
|
||||
//! use alpha-channel as coverage mask for anti-aliasing
|
||||
bool alphaToCoverage : 1; // 30
|
||||
|
||||
//! whether front face winding direction must be inverted
|
||||
bool inverseFrontFaces : 1; // 31
|
||||
|
||||
//! padding, must be 0
|
||||
uint8_t padding : 1; // 32
|
||||
};
|
||||
uint32_t u = 0;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
**********************************************************************************************
|
||||
* \privatesection
|
||||
*/
|
||||
|
||||
enum ShaderType : uint8_t {
|
||||
VERTEX = 0,
|
||||
FRAGMENT = 1
|
||||
};
|
||||
static constexpr size_t PIPELINE_STAGE_COUNT = 2;
|
||||
|
||||
/**
|
||||
* Selects which buffers to clear at the beginning of the render pass, as well as which buffers
|
||||
* can be discarded at the beginning and end of the render pass.
|
||||
*
|
||||
*/
|
||||
struct RenderPassFlags {
|
||||
/**
|
||||
* bitmask indicating which buffers to clear at the beginning of a render pass.
|
||||
* This implies discard.
|
||||
*/
|
||||
TargetBufferFlags clear;
|
||||
|
||||
/**
|
||||
* bitmask indicating which buffers to discard at the beginning of a render pass.
|
||||
* Discarded buffers have uninitialized content, they must be entirely drawn over or cleared.
|
||||
*/
|
||||
TargetBufferFlags discardStart;
|
||||
|
||||
/**
|
||||
* bitmask indicating which buffers to discard at the end of a render pass.
|
||||
* Discarded buffers' content becomes invalid, they must not be read from again.
|
||||
*/
|
||||
TargetBufferFlags discardEnd;
|
||||
};
|
||||
|
||||
/**
|
||||
* Parameters of a render pass.
|
||||
*/
|
||||
struct RenderPassParams {
|
||||
RenderPassFlags flags{}; //!< operations performed on the buffers for this pass
|
||||
|
||||
Viewport viewport{}; //!< viewport for this pass
|
||||
DepthRange depthRange{}; //!< depth range for this pass
|
||||
|
||||
//! Color to use to clear the COLOR buffer. RenderPassFlags::clear must be set.
|
||||
math::float4 clearColor = {};
|
||||
|
||||
//! Depth value to clear the depth buffer with
|
||||
double clearDepth = 0.0;
|
||||
|
||||
//! Stencil value to clear the stencil buffer with
|
||||
uint32_t clearStencil = 0;
|
||||
|
||||
/**
|
||||
* The subpass mask specifies which color attachments are designated for read-back in the second
|
||||
* subpass. If this is zero, the render pass has only one subpass. The least significant bit
|
||||
* specifies that the first color attachment in the render target is a subpass input.
|
||||
*
|
||||
* For now only 2 subpasses are supported, so only the lower 4 bits are used, one for each color
|
||||
* attachment (see MRT::TARGET_COUNT).
|
||||
*/
|
||||
uint32_t subpassMask = 0;
|
||||
};
|
||||
|
||||
struct PolygonOffset {
|
||||
float slope = 0; // factor in GL-speak
|
||||
float constant = 0; // units in GL-speak
|
||||
};
|
||||
|
||||
|
||||
using FrameScheduledCallback = void(*)(PresentCallable callable, void* user);
|
||||
|
||||
using FrameCompletedCallback = void(*)(void* user);
|
||||
|
||||
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
|
||||
template<> struct utils::EnableBitMaskOperators<filament::backend::TargetBufferFlags>
|
||||
: public std::true_type {};
|
||||
template<> struct utils::EnableBitMaskOperators<filament::backend::TextureUsage>
|
||||
: public std::true_type {};
|
||||
|
||||
#endif // TNT_FILAMENT_DRIVER_DRIVERENUMS_H
|
||||
116
ios/include/backend/Handle.h
Normal file
116
ios/include/backend/Handle.h
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* 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 TNT_FILAMENT_DRIVER_HANDLE_H
|
||||
#define TNT_FILAMENT_DRIVER_HANDLE_H
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/Log.h>
|
||||
#include <utils/debug.h>
|
||||
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
|
||||
struct HwBufferObject;
|
||||
struct HwFence;
|
||||
struct HwIndexBuffer;
|
||||
struct HwProgram;
|
||||
struct HwRenderPrimitive;
|
||||
struct HwRenderTarget;
|
||||
struct HwSamplerGroup;
|
||||
struct HwStream;
|
||||
struct HwSwapChain;
|
||||
struct HwSync;
|
||||
struct HwTexture;
|
||||
struct HwTimerQuery;
|
||||
struct HwVertexBuffer;
|
||||
|
||||
/*
|
||||
* A type handle to a h/w resource
|
||||
*/
|
||||
|
||||
//! \privatesection
|
||||
|
||||
class HandleBase {
|
||||
public:
|
||||
using HandleId = uint32_t;
|
||||
static constexpr const HandleId nullid = HandleId{ std::numeric_limits<HandleId>::max() };
|
||||
|
||||
constexpr HandleBase() noexcept: object(nullid) {}
|
||||
|
||||
explicit HandleBase(HandleId id) noexcept : object(id) {
|
||||
assert_invariant(object != nullid); // usually means an uninitialized handle is used
|
||||
}
|
||||
|
||||
HandleBase(HandleBase const& rhs) noexcept = default;
|
||||
HandleBase(HandleBase&& rhs) noexcept : object(rhs.object) {
|
||||
rhs.object = nullid;
|
||||
}
|
||||
|
||||
HandleBase& operator=(HandleBase const& rhs) noexcept = default;
|
||||
HandleBase& operator=(HandleBase&& rhs) noexcept {
|
||||
std::swap(object, rhs.object);
|
||||
return *this;
|
||||
}
|
||||
|
||||
explicit operator bool() const noexcept { return object != nullid; }
|
||||
|
||||
void clear() noexcept { object = nullid; }
|
||||
|
||||
bool operator==(const HandleBase& rhs) const noexcept { return object == rhs.object; }
|
||||
bool operator!=(const HandleBase& rhs) const noexcept { return object != rhs.object; }
|
||||
|
||||
// get this handle's handleId
|
||||
HandleId getId() const noexcept { return object; }
|
||||
|
||||
protected:
|
||||
HandleId object;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct Handle : public HandleBase {
|
||||
using HandleBase::HandleBase;
|
||||
|
||||
template<typename B, typename = std::enable_if_t<std::is_base_of<T, B>::value> >
|
||||
Handle(Handle<B> const& base) noexcept : HandleBase(base) { } // NOLINT(hicpp-explicit-conversions)
|
||||
|
||||
private:
|
||||
#if !defined(NDEBUG)
|
||||
template <typename U>
|
||||
friend utils::io::ostream& operator<<(utils::io::ostream& out, const Handle<U>& h) noexcept;
|
||||
#endif
|
||||
};
|
||||
|
||||
// Types used by the command stream
|
||||
// (we use this renaming because the macro-system doesn't deal well with "<" and ">")
|
||||
using BufferObjectHandle = Handle<HwBufferObject>;
|
||||
using FenceHandle = Handle<HwFence>;
|
||||
using IndexBufferHandle = Handle<HwIndexBuffer>;
|
||||
using ProgramHandle = Handle<HwProgram>;
|
||||
using RenderPrimitiveHandle = Handle<HwRenderPrimitive>;
|
||||
using RenderTargetHandle = Handle<HwRenderTarget>;
|
||||
using SamplerGroupHandle = Handle<HwSamplerGroup>;
|
||||
using StreamHandle = Handle<HwStream>;
|
||||
using SwapChainHandle = Handle<HwSwapChain>;
|
||||
using SyncHandle = Handle<HwSync>;
|
||||
using TextureHandle = Handle<HwTexture>;
|
||||
using TimerQueryHandle = Handle<HwTimerQuery>;
|
||||
using VertexBufferHandle = Handle<HwVertexBuffer>;
|
||||
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
|
||||
#endif // TNT_FILAMENT_DRIVER_HANDLE_H
|
||||
46
ios/include/backend/PipelineState.h
Normal file
46
ios/include/backend/PipelineState.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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_FILAMENT_DRIVER_PIPELINESTATE_H
|
||||
#define TNT_FILAMENT_DRIVER_PIPELINESTATE_H
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/Handle.h>
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
|
||||
//! \privatesection
|
||||
|
||||
struct PipelineState {
|
||||
Handle<HwProgram> program;
|
||||
RasterState rasterState;
|
||||
PolygonOffset polygonOffset;
|
||||
Viewport scissor{ 0, 0,
|
||||
(uint32_t)std::numeric_limits<int32_t>::max(),
|
||||
(uint32_t)std::numeric_limits<int32_t>::max()
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
|
||||
#endif //TNT_FILAMENT_DRIVER_PIPELINESTATE_H
|
||||
216
ios/include/backend/PixelBufferDescriptor.h
Normal file
216
ios/include/backend/PixelBufferDescriptor.h
Normal file
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef TNT_FILAMENT_DRIVER_PIXEL_BUFFERDESCRIPTOR_H
|
||||
#define TNT_FILAMENT_DRIVER_PIXEL_BUFFERDESCRIPTOR_H
|
||||
|
||||
#include <backend/BufferDescriptor.h>
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/debug.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
|
||||
/**
|
||||
* A descriptor to an image in main memory, typically used to transfer image data from the CPU
|
||||
* to the GPU.
|
||||
*
|
||||
* A PixelBufferDescriptor owns the memory buffer it references, therefore PixelBufferDescriptor
|
||||
* cannot be copied, but can be moved.
|
||||
*
|
||||
* PixelBufferDescriptor releases ownership of the memory-buffer when it's destroyed.
|
||||
*/
|
||||
class UTILS_PUBLIC PixelBufferDescriptor : public BufferDescriptor {
|
||||
public:
|
||||
using PixelDataFormat = backend::PixelDataFormat;
|
||||
using PixelDataType = backend::PixelDataType;
|
||||
|
||||
PixelBufferDescriptor() = default;
|
||||
|
||||
/**
|
||||
* Creates a new PixelBufferDescriptor referencing an image in main memory
|
||||
*
|
||||
* @param buffer Virtual address 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 type Type of the image pixels
|
||||
* @param alignment Alignment in bytes of pixel rows
|
||||
* @param left Left coordinate in pixels
|
||||
* @param top Top coordinate in pixels
|
||||
* @param stride Stride of a row in pixels
|
||||
* @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
|
||||
*/
|
||||
PixelBufferDescriptor(void const* buffer, size_t size,
|
||||
PixelDataFormat format, PixelDataType type, uint8_t alignment = 1,
|
||||
uint32_t left = 0, uint32_t top = 0, uint32_t stride = 0,
|
||||
Callback callback = nullptr, void* user = nullptr) noexcept
|
||||
: BufferDescriptor(buffer, size, callback, user),
|
||||
left(left), top(top), stride(stride),
|
||||
format(format), type(type), alignment(alignment) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new PixelBufferDescriptor referencing an image in main memory
|
||||
*
|
||||
* @param buffer Virtual address 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 type Type of the image pixels
|
||||
* @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
|
||||
*/
|
||||
PixelBufferDescriptor(void const* buffer, size_t size,
|
||||
PixelDataFormat format, PixelDataType type,
|
||||
Callback callback, void* user = nullptr) noexcept
|
||||
: BufferDescriptor(buffer, size, callback, user),
|
||||
stride(0), format(format), type(type), alignment(1) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new PixelBufferDescriptor referencing a compressed image in main memory
|
||||
*
|
||||
* @param buffer Virtual address 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 imageSize Compressed size of the image
|
||||
* @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
|
||||
*/
|
||||
PixelBufferDescriptor(void const* buffer, size_t size,
|
||||
backend::CompressedPixelDataType format, uint32_t imageSize,
|
||||
Callback callback, void* user = nullptr) noexcept
|
||||
: BufferDescriptor(buffer, size, callback, user),
|
||||
imageSize(imageSize), compressedFormat(format), type(PixelDataType::COMPRESSED),
|
||||
alignment(1) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the size in bytes needed to fit an image of given dimensions and format
|
||||
*
|
||||
* @param format Format of the image pixels
|
||||
* @param type Type of the image pixels
|
||||
* @param stride Stride of a row in pixels
|
||||
* @param height Height of the image in rows
|
||||
* @param alignment Alignment in bytes of pixel rows
|
||||
* @return The buffer size needed to fit this image in bytes
|
||||
*/
|
||||
static constexpr size_t computeDataSize(PixelDataFormat format, PixelDataType type,
|
||||
size_t stride, size_t height, size_t alignment) noexcept {
|
||||
assert_invariant(alignment);
|
||||
|
||||
if (type == PixelDataType::COMPRESSED) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t n = 0;
|
||||
switch (format) {
|
||||
case PixelDataFormat::R:
|
||||
case PixelDataFormat::R_INTEGER:
|
||||
case PixelDataFormat::DEPTH_COMPONENT:
|
||||
case PixelDataFormat::ALPHA:
|
||||
n = 1;
|
||||
break;
|
||||
case PixelDataFormat::RG:
|
||||
case PixelDataFormat::RG_INTEGER:
|
||||
case PixelDataFormat::DEPTH_STENCIL:
|
||||
n = 2;
|
||||
break;
|
||||
case PixelDataFormat::RGB:
|
||||
case PixelDataFormat::RGB_INTEGER:
|
||||
n = 3;
|
||||
break;
|
||||
case PixelDataFormat::UNUSED: // shouldn't happen (used to be rgbm)
|
||||
case PixelDataFormat::RGBA:
|
||||
case PixelDataFormat::RGBA_INTEGER:
|
||||
n = 4;
|
||||
break;
|
||||
}
|
||||
|
||||
size_t bpp = n;
|
||||
switch (type) {
|
||||
case PixelDataType::COMPRESSED: // Impossible -- to squash the IDE warnings
|
||||
case PixelDataType::UBYTE:
|
||||
case PixelDataType::BYTE:
|
||||
// nothing to do
|
||||
break;
|
||||
case PixelDataType::USHORT:
|
||||
case PixelDataType::SHORT:
|
||||
case PixelDataType::HALF:
|
||||
bpp *= 2;
|
||||
break;
|
||||
case PixelDataType::UINT:
|
||||
case PixelDataType::INT:
|
||||
case PixelDataType::FLOAT:
|
||||
bpp *= 4;
|
||||
break;
|
||||
case PixelDataType::UINT_10F_11F_11F_REV:
|
||||
// Special case, format must be RGB and uses 4 bytes
|
||||
assert_invariant(format == PixelDataFormat::RGB);
|
||||
bpp = 4;
|
||||
break;
|
||||
case PixelDataType::UINT_2_10_10_10_REV:
|
||||
// Special case, format must be RGBA and uses 4 bytes
|
||||
assert_invariant(format == PixelDataFormat::RGBA);
|
||||
bpp = 4;
|
||||
break;
|
||||
case PixelDataType::USHORT_565:
|
||||
// Special case, format must be RGB and uses 2 bytes
|
||||
assert_invariant(format == PixelDataFormat::RGB);
|
||||
bpp = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
size_t bpr = bpp * stride;
|
||||
size_t bprAligned = (bpr + (alignment - 1)) & -alignment;
|
||||
return bprAligned * height;
|
||||
}
|
||||
|
||||
//! left coordinate in pixels
|
||||
uint32_t left = 0;
|
||||
//! top coordinate in pixels
|
||||
uint32_t top = 0;
|
||||
union {
|
||||
struct {
|
||||
//! stride in pixels
|
||||
uint32_t stride;
|
||||
//! Pixel data format
|
||||
PixelDataFormat format;
|
||||
};
|
||||
struct {
|
||||
//! compressed image size
|
||||
uint32_t imageSize;
|
||||
//! compressed image format
|
||||
backend::CompressedPixelDataType compressedFormat;
|
||||
};
|
||||
};
|
||||
//! pixel data type
|
||||
PixelDataType type : 4;
|
||||
//! row alignment in bytes
|
||||
uint8_t alignment : 4;
|
||||
};
|
||||
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
|
||||
#endif // TNT_FILAMENT_DRIVER_PIXEL_BUFFERDESCRIPTOR_H
|
||||
103
ios/include/backend/Platform.h
Normal file
103
ios/include/backend/Platform.h
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef TNT_FILAMENT_DRIVER_PLATFORM_H
|
||||
#define TNT_FILAMENT_DRIVER_PLATFORM_H
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
|
||||
class Driver;
|
||||
|
||||
class UTILS_PUBLIC Platform {
|
||||
public:
|
||||
struct SwapChain {};
|
||||
struct Fence {};
|
||||
struct Stream {};
|
||||
struct ExternalTexture {
|
||||
uintptr_t image = 0;
|
||||
};
|
||||
|
||||
virtual ~Platform() noexcept;
|
||||
|
||||
/**
|
||||
* Queries the underlying OS version.
|
||||
* @return The OS version.
|
||||
*/
|
||||
virtual int getOSVersion() const noexcept = 0;
|
||||
|
||||
/**
|
||||
* Creates and initializes the low-level API (e.g. an OpenGL context or Vulkan instance),
|
||||
* then creates the concrete Driver.
|
||||
* The caller takes ownership of the returned Driver* and must destroy it with delete.
|
||||
*
|
||||
* @param sharedContext an optional shared context. This is not meaningful with all graphic
|
||||
* APIs and platforms.
|
||||
* For EGL platforms, this is an EGLContext.
|
||||
*
|
||||
* @return nullptr on failure, or a pointer to the newly created driver.
|
||||
*/
|
||||
virtual backend::Driver* createDriver(void* sharedContext) noexcept = 0;
|
||||
|
||||
/**
|
||||
* Processes the platform's event queue when called from its primary event-handling thread.
|
||||
*
|
||||
* Internally, Filament might need to call this when waiting on a fence. It is only implemented
|
||||
* on platforms that need it, such as macOS + OpenGL. Returns false if this is not the main
|
||||
* thread, or if the platform does not need to perform any special processing.
|
||||
*/
|
||||
virtual bool pumpEvents() noexcept { return false; }
|
||||
};
|
||||
|
||||
|
||||
class UTILS_PUBLIC DefaultPlatform : public Platform {
|
||||
public:
|
||||
~DefaultPlatform() noexcept override;
|
||||
|
||||
/**
|
||||
* Creates a Platform configured for the requested backend if available
|
||||
*
|
||||
* @param backendHint Preferred backend, if not available the backend most suitable for the
|
||||
* underlying platform is returned and \p backendHint is updated
|
||||
* accordingly. Can't be nullptr.
|
||||
*
|
||||
* @return A pointer to the Plaform object.
|
||||
*
|
||||
* @see destroy
|
||||
*/
|
||||
static DefaultPlatform* create(backend::Backend* backendHint) noexcept;
|
||||
|
||||
/**
|
||||
* Destroys a Platform object returned by create()
|
||||
*
|
||||
* @param platform a reference (as a pointer) to the DefaultPlatform pointer to destroy.
|
||||
* \p platform is cleared upon return.
|
||||
*
|
||||
* @see create
|
||||
*/
|
||||
static void destroy(DefaultPlatform** platform) noexcept;
|
||||
};
|
||||
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
|
||||
#endif // TNT_FILAMENT_DRIVER_PLATFORM_H
|
||||
104
ios/include/backend/PresentCallable.h
Normal file
104
ios/include/backend/PresentCallable.h
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef TNT_FILAMENT_BACKEND_PRESENT_CALLABLE
|
||||
#define TNT_FILAMENT_BACKEND_PRESENT_CALLABLE
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
|
||||
/**
|
||||
* A PresentCallable is a callable object that, when called, schedules a frame for presentation on
|
||||
* a SwapChain.
|
||||
*
|
||||
* Typically, Filament's backend is responsible scheduling a frame's presentation. However, there
|
||||
* are certain cases where the application might want to control when a frame is scheduled for
|
||||
* presentation.
|
||||
*
|
||||
* For example, on iOS, UIKit elements can be synchronized to 3D content by scheduling a present
|
||||
* within a CATransation:
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* void myFrameScheduledCallback(PresentCallable presentCallable, void* user) {
|
||||
* [CATransaction begin];
|
||||
* // Update other UI elements...
|
||||
* presentCallable();
|
||||
* [CATransaction commit];
|
||||
* }
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* To obtain a PresentCallable, set a SwapChain::FrameScheduledCallback on a SwapChain with the
|
||||
* SwapChain::setFrameScheduledCallback method. The callback is called with a PresentCallable object
|
||||
* and optional user data:
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* swapChain->setFrameScheduledCallback(myFrameScheduledCallback, nullptr);
|
||||
* if (renderer->beginFrame(swapChain)) {
|
||||
* renderer->render(view);
|
||||
* renderer->endFrame();
|
||||
* }
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* @remark Only Filament's Metal backend supports PresentCallables and frame callbacks. Other
|
||||
* backends ignore the callback (which will never be called) and proceed normally.
|
||||
*
|
||||
* @remark The SwapChain::FrameScheduledCallback is called on an arbitrary thread.
|
||||
*
|
||||
* Applications *must* call each PresentCallable they receive. Each PresentCallable represents a
|
||||
* frame that is waiting to be presented. If an application fails to call a PresentCallable, a
|
||||
* memory leak could occur. To "cancel" the presentation of a frame, pass false to the
|
||||
* PresentCallable, which will cancel the presentation of the frame and release associated memory.
|
||||
*
|
||||
* @see Renderer, SwapChain::setFrameScheduledCallback
|
||||
*/
|
||||
class UTILS_PUBLIC PresentCallable {
|
||||
public:
|
||||
|
||||
using PresentFn = void(*)(bool presentFrame, void* user);
|
||||
|
||||
PresentCallable(PresentFn fn, void* user) noexcept;
|
||||
~PresentCallable() noexcept = default;
|
||||
PresentCallable(const PresentCallable& rhs) = default;
|
||||
PresentCallable& operator=(const PresentCallable& rhs) = default;
|
||||
|
||||
/**
|
||||
* Call this PresentCallable, scheduling the associated frame for presentation. Pass false for
|
||||
* presentFrame to effectively "cancel" the presentation of the frame.
|
||||
*
|
||||
* @param presentFrame if false, will not present the frame but releases associated memory
|
||||
*/
|
||||
void operator()(bool presentFrame = true) noexcept;
|
||||
|
||||
private:
|
||||
|
||||
PresentFn mPresentFn;
|
||||
void* mUser = nullptr;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @deprecated, FrameFinishedCallback has been renamed to SwapChain::FrameScheduledCallback.
|
||||
*/
|
||||
using FrameFinishedCallback UTILS_DEPRECATED = void(*)(PresentCallable callable, void* user);
|
||||
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
|
||||
#endif // TNT_FILAMENT_BACKEND_PRESENT_FRAME_CALLABLE
|
||||
107
ios/include/backend/TargetBufferInfo.h
Normal file
107
ios/include/backend/TargetBufferInfo.h
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* 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_FILAMENT_DRIVER_TARGETBUFFERINFO_H
|
||||
#define TNT_FILAMENT_DRIVER_TARGETBUFFERINFO_H
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/Handle.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
|
||||
//! \privatesection
|
||||
|
||||
class TargetBufferInfo {
|
||||
public:
|
||||
// ctor for 2D textures
|
||||
TargetBufferInfo(Handle<HwTexture> h, uint8_t level = 0) noexcept // NOLINT(google-explicit-constructor)
|
||||
: handle(h), level(level) { }
|
||||
// ctor for cubemaps
|
||||
TargetBufferInfo(Handle<HwTexture> h, uint8_t level, TextureCubemapFace face) noexcept
|
||||
: handle(h), level(level), face(face) { }
|
||||
// ctor for 3D textures
|
||||
TargetBufferInfo(Handle<HwTexture> h, uint8_t level, uint16_t layer) noexcept
|
||||
: handle(h), level(level), layer(layer) { }
|
||||
|
||||
explicit TargetBufferInfo(TextureCubemapFace face) noexcept : face(face) {}
|
||||
|
||||
explicit TargetBufferInfo(uint16_t layer) noexcept : layer(layer) {}
|
||||
|
||||
// texture to be used as render target
|
||||
Handle<HwTexture> handle;
|
||||
// level to be used
|
||||
uint8_t level = 0;
|
||||
union {
|
||||
// face if texture is a cubemap
|
||||
TextureCubemapFace face;
|
||||
// for 3D textures
|
||||
uint16_t layer = 0;
|
||||
};
|
||||
TargetBufferInfo() noexcept { }
|
||||
};
|
||||
|
||||
class MRT {
|
||||
public:
|
||||
static constexpr uint8_t MIN_SUPPORTED_RENDER_TARGET_COUNT = 4u;
|
||||
|
||||
// When updating this, make sure to also take care of RenderTarget.java
|
||||
static constexpr uint8_t MAX_SUPPORTED_RENDER_TARGET_COUNT = 8u;
|
||||
|
||||
private:
|
||||
TargetBufferInfo mInfos[MAX_SUPPORTED_RENDER_TARGET_COUNT];
|
||||
|
||||
public:
|
||||
TargetBufferInfo const& operator[](size_t i) const noexcept {
|
||||
return mInfos[i];
|
||||
}
|
||||
|
||||
TargetBufferInfo& operator[](size_t i) noexcept {
|
||||
return mInfos[i];
|
||||
}
|
||||
|
||||
MRT() noexcept = default;
|
||||
|
||||
MRT(TargetBufferInfo const& color) noexcept // NOLINT(hicpp-explicit-conversions)
|
||||
: mInfos{ color } {
|
||||
}
|
||||
|
||||
MRT(TargetBufferInfo const& color0, TargetBufferInfo const& color1) noexcept
|
||||
: mInfos{ color0, color1 } {
|
||||
}
|
||||
|
||||
MRT(TargetBufferInfo const& color0, TargetBufferInfo const& color1,
|
||||
TargetBufferInfo const& color2) noexcept
|
||||
: mInfos{ color0, color1, color2 } {
|
||||
}
|
||||
|
||||
MRT(TargetBufferInfo const& color0, TargetBufferInfo const& color1,
|
||||
TargetBufferInfo const& color2, TargetBufferInfo const& color3) noexcept
|
||||
: mInfos{ color0, color1, color2, color3 } {
|
||||
}
|
||||
|
||||
// this is here for backward compatibility
|
||||
MRT(Handle<HwTexture> h, uint8_t level, uint16_t layer) noexcept
|
||||
: mInfos{{ h, level, layer }} {
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
|
||||
#endif //TNT_FILAMENT_DRIVER_TARGETBUFFERINFO_H
|
||||
85
ios/include/camutils/Bookmark.h
Normal file
85
ios/include/camutils/Bookmark.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* 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_BOOKMARK_H
|
||||
#define CAMUTILS_BOOKMARK_H
|
||||
|
||||
#include <camutils/compiler.h>
|
||||
|
||||
#include <math/vec2.h>
|
||||
#include <math/vec3.h>
|
||||
|
||||
namespace filament {
|
||||
namespace camutils {
|
||||
|
||||
template <typename FLOAT> class FreeFlightManipulator;
|
||||
template <typename FLOAT> class OrbitManipulator;
|
||||
template <typename FLOAT> class MapManipulator;
|
||||
template <typename FLOAT> class Manipulator;
|
||||
|
||||
enum class Mode { ORBIT, MAP, FREE_FLIGHT };
|
||||
|
||||
/**
|
||||
* Opaque memento to a viewing position and orientation (e.g. the "home" camera position).
|
||||
*
|
||||
* This little struct is meant to be passed around by value and can be used to track camera
|
||||
* animation between waypoints. In map mode this implements Van Wijk interpolation.
|
||||
*
|
||||
* @see Manipulator::getCurrentBookmark, Manipulator::jumpToBookmark
|
||||
*/
|
||||
template <typename FLOAT>
|
||||
struct CAMUTILS_PUBLIC Bookmark {
|
||||
/**
|
||||
* Interpolates between two bookmarks. The t argument must be between 0 and 1 (inclusive), and
|
||||
* the two endpoints must have the same mode (ORBIT or MAP).
|
||||
*/
|
||||
static Bookmark<FLOAT> interpolate(Bookmark<FLOAT> a, Bookmark<FLOAT> b, double t);
|
||||
|
||||
/**
|
||||
* Recommends a duration for animation between two MAP endpoints. The return value is a unitless
|
||||
* multiplier.
|
||||
*/
|
||||
static double duration(Bookmark<FLOAT> a, Bookmark<FLOAT> b);
|
||||
|
||||
private:
|
||||
struct MapParams {
|
||||
FLOAT extent;
|
||||
filament::math::vec2<FLOAT> center;
|
||||
};
|
||||
struct OrbitParams {
|
||||
FLOAT phi;
|
||||
FLOAT theta;
|
||||
FLOAT distance;
|
||||
filament::math::vec3<FLOAT> pivot;
|
||||
};
|
||||
struct FlightParams {
|
||||
FLOAT pitch;
|
||||
FLOAT yaw;
|
||||
filament::math::vec3<FLOAT> position;
|
||||
};
|
||||
Mode mode;
|
||||
MapParams map;
|
||||
OrbitParams orbit;
|
||||
FlightParams flight;
|
||||
friend class FreeFlightManipulator<FLOAT>;
|
||||
friend class OrbitManipulator<FLOAT>;
|
||||
friend class MapManipulator<FLOAT>;
|
||||
};
|
||||
|
||||
} // namespace camutils
|
||||
} // namespace filament
|
||||
|
||||
#endif // CAMUTILS_BOOKMARK_H
|
||||
298
ios/include/camutils/Manipulator.h
Normal file
298
ios/include/camutils/Manipulator.h
Normal file
@@ -0,0 +1,298 @@
|
||||
/*
|
||||
* 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_MANIPULATOR_H
|
||||
#define CAMUTILS_MANIPULATOR_H
|
||||
|
||||
#include <camutils/Bookmark.h>
|
||||
#include <camutils/compiler.h>
|
||||
|
||||
#include <math/vec2.h>
|
||||
#include <math/vec3.h>
|
||||
#include <math/vec4.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace filament {
|
||||
namespace camutils {
|
||||
|
||||
enum class Fov { VERTICAL, HORIZONTAL };
|
||||
|
||||
/**
|
||||
* Helper that enables camera interaction similar to sketchfab or Google Maps.
|
||||
*
|
||||
* Clients notify the camera manipulator of various mouse or touch events, then periodically call
|
||||
* its getLookAt() method so that they can adjust their camera(s). Three modes are supported: ORBIT,
|
||||
* MAP, and FREE_FLIGHT. To construct a manipulator instance, the desired mode is passed into the
|
||||
* create method.
|
||||
*
|
||||
* Usage example:
|
||||
*
|
||||
* using CameraManipulator = camutils::Manipulator<float>;
|
||||
* CameraManipulator* manip;
|
||||
*
|
||||
* void init() {
|
||||
* manip = CameraManipulator::Builder()
|
||||
* .viewport(1024, 768)
|
||||
* .build(camutils::Mode::ORBIT);
|
||||
* }
|
||||
*
|
||||
* void onMouseDown(int x, int y) {
|
||||
* manip->grabBegin(x, y, false);
|
||||
* }
|
||||
*
|
||||
* void onMouseMove(int x, int y) {
|
||||
* manip->grabUpdate(x, y);
|
||||
* }
|
||||
*
|
||||
* void onMouseUp(int x, int y) {
|
||||
* manip->grabEnd();
|
||||
* }
|
||||
*
|
||||
* void gameLoop() {
|
||||
* while (true) {
|
||||
* filament::math::float3 eye, center, up;
|
||||
* manip->getLookAt(&eye, ¢er, &up);
|
||||
* camera->lookAt(eye, center, up);
|
||||
* render();
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* @see Bookmark
|
||||
*/
|
||||
template <typename FLOAT>
|
||||
class CAMUTILS_PUBLIC Manipulator {
|
||||
public:
|
||||
using vec2 = filament::math::vec2<FLOAT>;
|
||||
using vec3 = filament::math::vec3<FLOAT>;
|
||||
using vec4 = filament::math::vec4<FLOAT>;
|
||||
|
||||
/** Opaque handle to a viewing position and orientation to facilitate camera animation. */
|
||||
using Bookmark = filament::camutils::Bookmark<FLOAT>;
|
||||
|
||||
/** Optional raycasting function to enable perspective-correct panning. */
|
||||
typedef bool (*RayCallback)(const vec3& origin, const vec3& dir, FLOAT* t, void* userdata);
|
||||
|
||||
/** Builder state, direct access is allowed but Builder methods are preferred. **/
|
||||
struct Config {
|
||||
int viewport[2];
|
||||
vec3 targetPosition;
|
||||
vec3 upVector;
|
||||
FLOAT zoomSpeed;
|
||||
vec3 orbitHomePosition;
|
||||
vec2 orbitSpeed;
|
||||
Fov fovDirection;
|
||||
FLOAT fovDegrees;
|
||||
FLOAT farPlane;
|
||||
vec2 mapExtent;
|
||||
FLOAT mapMinDistance;
|
||||
vec3 flightStartPosition;
|
||||
FLOAT flightStartPitch;
|
||||
FLOAT flightStartYaw;
|
||||
FLOAT flightMaxSpeed;
|
||||
FLOAT flightSpeedSteps;
|
||||
vec2 flightPanSpeed;
|
||||
FLOAT flightMoveDamping;
|
||||
vec4 groundPlane;
|
||||
RayCallback raycastCallback;
|
||||
void* raycastUserdata;
|
||||
};
|
||||
|
||||
struct Builder {
|
||||
// Common properties
|
||||
Builder& viewport(int width, int height); //! Width and height of the viewing area
|
||||
Builder& targetPosition(FLOAT x, FLOAT y, FLOAT z); //! World-space position of interest, defaults to (0,0,0)
|
||||
Builder& upVector(FLOAT x, FLOAT y, FLOAT z); //! Orientation for the home position, defaults to (0,1,0)
|
||||
Builder& zoomSpeed(FLOAT val); //! Multiplied with scroll delta, defaults to 0.01
|
||||
|
||||
// Orbit mode properties
|
||||
Builder& orbitHomePosition(FLOAT x, FLOAT y, FLOAT z); //! Initial eye position in world space, defaults to (0,0,1)
|
||||
Builder& orbitSpeed(FLOAT x, FLOAT y); //! Multiplied with viewport delta, defaults to 0.01
|
||||
|
||||
// Map mode properties
|
||||
Builder& fovDirection(Fov fov); //! The axis that's held constant when viewport changes
|
||||
Builder& fovDegrees(FLOAT degrees); //! The full FOV (not the half-angle)
|
||||
Builder& farPlane(FLOAT distance); //! The distance to the far plane
|
||||
Builder& mapExtent(FLOAT worldWidth, FLOAT worldHeight); //! The ground size for computing home position
|
||||
Builder& mapMinDistance(FLOAT mindist); //! Constrains the zoom-in level
|
||||
|
||||
// Free flight properties
|
||||
Builder& flightStartPosition(FLOAT x, FLOAT y, FLOAT z); //! Initial eye position in world space, defaults to (0,0,0)
|
||||
Builder& flightStartOrientation(FLOAT pitch, FLOAT yaw); //! Initial orientation in pitch and yaw, defaults to (0,0)
|
||||
Builder& flightMaxMoveSpeed(FLOAT maxSpeed); //! The maximum camera speed in world units per second, defaults to 10
|
||||
Builder& flightSpeedSteps(int steps); //! The number of speed steps adjustable with scroll wheel, defaults to 80
|
||||
Builder& flightPanSpeed(FLOAT x, FLOAT y); //! Multiplied with viewport delta, defaults to 0.01,0.01
|
||||
Builder& flightMoveDamping(FLOAT damping); //! Applies a deceleration to camera movement, defaults to 0 (no damping)
|
||||
//! Lower values give slower damping times, a good default is 15
|
||||
//! Too high a value may lead to instability
|
||||
|
||||
// Raycast properties
|
||||
Builder& groundPlane(FLOAT a, FLOAT b, FLOAT c, FLOAT d); //! Plane equation used as a raycast fallback
|
||||
Builder& raycastCallback(RayCallback cb, void* userdata); //! Raycast function for accurate grab-and-pan
|
||||
|
||||
/**
|
||||
* Creates a new camera manipulator, either ORBIT, MAP, or FREE_FLIGHT.
|
||||
*
|
||||
* Clients can simply use "delete" to destroy the manipulator.
|
||||
*/
|
||||
Manipulator* build(Mode mode);
|
||||
|
||||
Config details = {};
|
||||
};
|
||||
|
||||
virtual ~Manipulator() = default;
|
||||
|
||||
/**
|
||||
* Gets the immutable mode of the manipulator.
|
||||
*/
|
||||
Mode getMode() const { return mMode; }
|
||||
|
||||
/**
|
||||
* Sets the viewport dimensions. The manipulator uses this to process grab events and raycasts.
|
||||
*/
|
||||
void setViewport(int width, int height);
|
||||
|
||||
/**
|
||||
* Gets the current orthonormal basis; this is usually called once per frame.
|
||||
*/
|
||||
void getLookAt(vec3* eyePosition, vec3* targetPosition, vec3* upward) const;
|
||||
|
||||
/**
|
||||
* Given a viewport coordinate, picks a point in the ground plane, or in the actual scene if the
|
||||
* raycast callback was provided.
|
||||
*/
|
||||
bool raycast(int x, int y, vec3* result) const;
|
||||
|
||||
/**
|
||||
* Given a viewport coordinate, computes a picking ray (origin + direction).
|
||||
*/
|
||||
void getRay(int x, int y, vec3* origin, vec3* dir) const;
|
||||
|
||||
/**
|
||||
* Starts a grabbing session (i.e. the user is dragging around in the viewport).
|
||||
*
|
||||
* In MAP mode, this starts a panning session.
|
||||
* In ORBIT mode, this starts either rotating or strafing.
|
||||
* In FREE_FLIGHT mode, this starts a nodal panning session.
|
||||
*
|
||||
* @param x X-coordinate for point of interest in viewport space
|
||||
* @param y Y-coordinate for point of interest in viewport space
|
||||
* @param strafe ORBIT mode only; if true, starts a translation rather than a rotation
|
||||
*/
|
||||
virtual void grabBegin(int x, int y, bool strafe) = 0;
|
||||
|
||||
/**
|
||||
* Updates a grabbing session.
|
||||
*
|
||||
* This must be called at least once between grabBegin / grabEnd to dirty the camera.
|
||||
*/
|
||||
virtual void grabUpdate(int x, int y) = 0;
|
||||
|
||||
/**
|
||||
* Ends a grabbing session.
|
||||
*/
|
||||
virtual void grabEnd() = 0;
|
||||
|
||||
/**
|
||||
* Keys used to translate the camera in FREE_FLIGHT mode.
|
||||
* FORWARD and BACKWARD dolly the camera forwards and backwards.
|
||||
* LEFT and RIGHT strafe the camera left and right.
|
||||
* UP and DOWN boom the camera upwards and downwards.
|
||||
*/
|
||||
enum class Key {
|
||||
FORWARD,
|
||||
LEFT,
|
||||
BACKWARD,
|
||||
RIGHT,
|
||||
UP,
|
||||
DOWN,
|
||||
|
||||
COUNT
|
||||
};
|
||||
|
||||
/**
|
||||
* Signals that a key is now in the down state.
|
||||
*
|
||||
* In FREE_FLIGHT mode, the camera is translated forward and backward and strafed left and right
|
||||
* depending on the depressed keys. This allows WASD-style movement.
|
||||
*/
|
||||
virtual void keyDown(Key key);
|
||||
|
||||
/**
|
||||
* Signals that a key is now in the up state.
|
||||
*
|
||||
* @see keyDown
|
||||
*/
|
||||
virtual void keyUp(Key key);
|
||||
|
||||
/**
|
||||
* In MAP and ORBIT modes, dollys the camera along the viewing direction.
|
||||
* In FREE_FLIGHT mode, adjusts the move speed of the camera.
|
||||
*
|
||||
* @param x X-coordinate for point of interest in viewport space, ignored in FREE_FLIGHT mode
|
||||
* @param y Y-coordinate for point of interest in viewport space, ignored in FREE_FLIGHT mode
|
||||
* @param scrolldelta In MAP and ORBIT modes, negative means "zoom in", positive means "zoom out"
|
||||
* In FREE_FLIGHT mode, negative means "slower", positive means "faster"
|
||||
*/
|
||||
virtual void scroll(int x, int y, FLOAT scrolldelta) = 0;
|
||||
|
||||
/**
|
||||
* Processes input and updates internal state.
|
||||
*
|
||||
* This must be called once every frame before getLookAt is valid.
|
||||
*
|
||||
* @param deltaTime The amount of time, in seconds, passed since the previous call to update.
|
||||
*/
|
||||
virtual void update(FLOAT deltaTime);
|
||||
|
||||
/**
|
||||
* Gets a handle that can be used to reset the manipulator back to its current position.
|
||||
*
|
||||
* @see jumpToBookmark
|
||||
*/
|
||||
virtual Bookmark getCurrentBookmark() const = 0;
|
||||
|
||||
/**
|
||||
* Gets a handle that can be used to reset the manipulator back to its home position.
|
||||
*
|
||||
* @see jumpToBookmark
|
||||
*/
|
||||
virtual Bookmark getHomeBookmark() const = 0;
|
||||
|
||||
/**
|
||||
* Sets the manipulator position and orientation back to a stashed state.
|
||||
*
|
||||
* @see getCurrentBookmark, getHomeBookmark
|
||||
*/
|
||||
virtual void jumpToBookmark(const Bookmark& bookmark) = 0;
|
||||
|
||||
protected:
|
||||
Manipulator(Mode mode, const Config& props);
|
||||
|
||||
virtual void setProperties(const Config& props);
|
||||
|
||||
vec3 raycastFarPlane(int x, int y) const;
|
||||
|
||||
const Mode mMode;
|
||||
Config mProps;
|
||||
vec3 mEye;
|
||||
vec3 mTarget;
|
||||
};
|
||||
|
||||
} // namespace camutils
|
||||
} // namespace filament
|
||||
|
||||
#endif /* CAMUTILS_MANIPULATOR_H */
|
||||
26
ios/include/camutils/compiler.h
Normal file
26
ios/include/camutils/compiler.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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 CAMUTILS_COMPILER_H
|
||||
#define CAMUTILS_COMPILER_H
|
||||
|
||||
#if __has_attribute(visibility)
|
||||
# define CAMUTILS_PUBLIC __attribute__((visibility("default")))
|
||||
#else
|
||||
# define CAMUTILS_PUBLIC
|
||||
#endif
|
||||
|
||||
#endif // CAMUTILS_COMPILER_H
|
||||
6327
ios/include/cgltf.h
Normal file
6327
ios/include/cgltf.h
Normal file
File diff suppressed because it is too large
Load Diff
96
ios/include/filamat/Enums.h
Normal file
96
ios/include/filamat/Enums.h
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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
|
||||
71
ios/include/filamat/IncludeCallback.h
Normal file
71
ios/include/filamat/IncludeCallback.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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
|
||||
746
ios/include/filamat/MaterialBuilder.h
Normal file
746
ios/include/filamat/MaterialBuilder.h
Normal file
@@ -0,0 +1,746 @@
|
||||
/*
|
||||
* 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
|
||||
103
ios/include/filamat/Package.h
Normal file
103
ios/include/filamat/Package.h
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* 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
|
||||
242
ios/include/filament-iblprefilter/IBLPrefilterContext.h
Normal file
242
ios/include/filament-iblprefilter/IBLPrefilterContext.h
Normal file
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
* 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
|
||||
198
ios/include/filament/Box.h
Normal file
198
ios/include/filament/Box.h
Normal file
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef TNT_FILAMENT_BOX_H
|
||||
#define TNT_FILAMENT_BOX_H
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include <math/mat4.h>
|
||||
#include <math/vec3.h>
|
||||
|
||||
namespace filament {
|
||||
|
||||
/**
|
||||
* An axis aligned 3D box represented by its center and half-extent.
|
||||
*/
|
||||
class UTILS_PUBLIC Box {
|
||||
public:
|
||||
/** Center of the 3D box */
|
||||
math::float3 center = {};
|
||||
|
||||
/** Half extent from the center on all 3 axis */
|
||||
math::float3 halfExtent = {};
|
||||
|
||||
/**
|
||||
* Whether the box is empty, i.e.: it's volume is null.
|
||||
* @return true if the volume of the box is null
|
||||
*/
|
||||
constexpr bool isEmpty() const noexcept {
|
||||
return length2(halfExtent) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the lowest coordinates corner of the box.
|
||||
* @return center - halfExtent
|
||||
*/
|
||||
constexpr math::float3 getMin() const noexcept {
|
||||
return center - halfExtent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the largest coordinates corner of the box.
|
||||
* @return center + halfExtent
|
||||
*/
|
||||
constexpr math::float3 getMax() const noexcept {
|
||||
return center + halfExtent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the 3D box from its min / max coordinates on each axis
|
||||
* @param min lowest coordinates corner of the box
|
||||
* @param max largest coordinates corner of the box
|
||||
* @return This bounding box
|
||||
*/
|
||||
Box& set(const math::float3& min, const math::float3& max) noexcept {
|
||||
// float3 ctor needed for visual studio
|
||||
center = (max + min) * math::float3(0.5f);
|
||||
halfExtent = (max - min) * math::float3(0.5f);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the bounding box of the union of two boxes
|
||||
* @param box The box to be combined with
|
||||
* @return The bounding box of the union of *this and box
|
||||
*/
|
||||
Box& unionSelf(const Box& box) noexcept {
|
||||
set(min(getMin(), box.getMin()), max(getMax(), box.getMax()));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates the box *to* a given center position
|
||||
* @param tr position to translate the box to
|
||||
* @return A box centered in \p tr with the same extent than *this
|
||||
*/
|
||||
constexpr Box translateTo(const math::float3& tr) const noexcept {
|
||||
return Box{ tr, halfExtent };
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the smallest bounding sphere of the box.
|
||||
* @return The smallest sphere defined by its center (.xyz) and radius (.w) that contains *this
|
||||
*/
|
||||
math::float4 getBoundingSphere() const noexcept {
|
||||
return { center, length(halfExtent) };
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the bounding box of a box transformed by a rigid transform
|
||||
* @param box the box to transform
|
||||
* @param m a 4x4 matrix that must be a rigid transform
|
||||
* @return the bounding box of the transformed box.
|
||||
* Result is undefined if \p m is not a rigid transform
|
||||
*/
|
||||
friend Box rigidTransform(Box const& box, const math::mat4f& m) noexcept;
|
||||
|
||||
/**
|
||||
* Computes the bounding box of a box transformed by a rigid transform
|
||||
* @param box the box to transform
|
||||
* @param m a 3x3 matrix that must be a rigid transform
|
||||
* @return the bounding box of the transformed box.
|
||||
* Result is undefined if \p m is not a rigid transform
|
||||
*/
|
||||
friend Box rigidTransform(Box const& box, const math::mat3f& m) noexcept;
|
||||
};
|
||||
|
||||
/**
|
||||
* An axis aligned box represented by its min and max coordinates
|
||||
*/
|
||||
struct UTILS_PUBLIC Aabb {
|
||||
|
||||
/** min coordinates */
|
||||
math::float3 min = std::numeric_limits<float>::max();
|
||||
|
||||
/** max coordinates */
|
||||
math::float3 max = std::numeric_limits<float>::lowest();
|
||||
|
||||
/**
|
||||
* Computes the center of the box.
|
||||
* @return (max + min)/2
|
||||
*/
|
||||
math::float3 center() const noexcept {
|
||||
// float3 ctor needed for visual studio
|
||||
return (max + min) * math::float3(0.5f);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the half-extent of the box.
|
||||
* @return (max - min)/2
|
||||
*/
|
||||
math::float3 extent() const noexcept {
|
||||
// float3 ctor needed for visual studio
|
||||
return (max - min) * math::float3(0.5f);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the box is empty, i.e.: it's volume is null or negative.
|
||||
* @return true if min >= max, i.e: the volume of the box is null or negative
|
||||
*/
|
||||
bool isEmpty() const noexcept {
|
||||
return any(greaterThanEqual(min, max));
|
||||
}
|
||||
|
||||
struct Corners {
|
||||
using value_type = math::float3;
|
||||
value_type const* begin() const { return vertices; }
|
||||
value_type const* end() const { return vertices + 8; }
|
||||
value_type * begin() { return vertices; }
|
||||
value_type * end() { return vertices + 8; }
|
||||
value_type const* data() const { return vertices; }
|
||||
value_type * data() { return vertices; }
|
||||
size_t size() const { return 8; }
|
||||
value_type vertices[8];
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the 8 corner vertices of the AABB.
|
||||
*/
|
||||
Corners getCorners() const;
|
||||
|
||||
/**
|
||||
* Returns whether the box contains a given point.
|
||||
*
|
||||
* @param p the point to test
|
||||
* @return the maximum signed distance to the box. Negative if p is in the box
|
||||
*/
|
||||
float contains(math::float3 p) const noexcept;
|
||||
|
||||
/**
|
||||
* Applies an affine transformation to the AABB.
|
||||
*
|
||||
* @param m the 4x4 transformation to apply
|
||||
* @return the transformed box
|
||||
*/
|
||||
Aabb transform(const math::mat4f& m) const noexcept;
|
||||
};
|
||||
|
||||
} // namespace filament
|
||||
|
||||
#endif // TNT_FILAMENT_BOX_H
|
||||
117
ios/include/filament/BufferObject.h
Normal file
117
ios/include/filament/BufferObject.h
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef TNT_FILAMENT_BUFFEROBJECT_H
|
||||
#define TNT_FILAMENT_BUFFEROBJECT_H
|
||||
|
||||
#include <filament/FilamentAPI.h>
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
#include <backend/BufferDescriptor.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
namespace filament {
|
||||
|
||||
class FBufferObject;
|
||||
|
||||
class Engine;
|
||||
|
||||
/**
|
||||
* A generic GPU buffer containing data.
|
||||
*
|
||||
* Usage of this BufferObject is optional. For simple use cases it is not necessary. It is useful
|
||||
* only when you need to share data between multiple VertexBuffer instances. It also allows you to
|
||||
* efficiently swap-out the buffers in VertexBuffer.
|
||||
*
|
||||
* NOTE: For now this is only used for vertex data, but in the future we may use it for other things
|
||||
* (e.g. compute).
|
||||
*
|
||||
* @see VertexBuffer
|
||||
*/
|
||||
class UTILS_PUBLIC BufferObject : public FilamentAPI {
|
||||
struct BuilderDetails;
|
||||
|
||||
public:
|
||||
using BufferDescriptor = backend::BufferDescriptor;
|
||||
using BindingType = backend::BufferObjectBinding;
|
||||
|
||||
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 buffer in bytes.
|
||||
* @param byteCount Maximum number of bytes the BufferObject can hold.
|
||||
* @return A reference to this Builder for chaining calls.
|
||||
*/
|
||||
Builder& size(uint32_t byteCount) noexcept;
|
||||
|
||||
/**
|
||||
* The binding type for this buffer object. (defaults to VERTEX)
|
||||
* @param BindingType Distinguishes between SSBO, VBO, etc. For now this must be VERTEX.
|
||||
* @return A reference to this Builder for chaining calls.
|
||||
*/
|
||||
Builder& bindingType(BindingType bindingType) noexcept;
|
||||
|
||||
/**
|
||||
* Creates the BufferObject and returns a pointer to it. After creation, the buffer
|
||||
* object is uninitialized. Use BufferObject::setBuffer() to initialize it.
|
||||
*
|
||||
* @param engine Reference to the filament::Engine to associate this BufferObject 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.
|
||||
*
|
||||
* @see IndexBuffer::setBuffer
|
||||
*/
|
||||
BufferObject* build(Engine& engine);
|
||||
private:
|
||||
friend class FBufferObject;
|
||||
};
|
||||
|
||||
/**
|
||||
* Asynchronously copy-initializes a region of this BufferObject from the data provided.
|
||||
*
|
||||
* @param engine Reference to the filament::Engine associated with this BufferObject.
|
||||
* @param buffer A BufferDescriptor representing the data used to initialize the BufferObject.
|
||||
* @param byteOffset Offset in bytes into the BufferObject
|
||||
*/
|
||||
void setBuffer(Engine& engine, BufferDescriptor&& buffer, uint32_t byteOffset = 0);
|
||||
|
||||
/**
|
||||
* Returns the size of this BufferObject in elements.
|
||||
* @return The maximum capacity of the BufferObject.
|
||||
*/
|
||||
size_t getByteCount() const noexcept;
|
||||
};
|
||||
|
||||
} // namespace filament
|
||||
|
||||
#endif // TNT_FILAMENT_BUFFEROBJECT_H
|
||||
516
ios/include/filament/Camera.h
Normal file
516
ios/include/filament/Camera.h
Normal file
@@ -0,0 +1,516 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef TNT_FILAMENT_CAMERA_H
|
||||
#define TNT_FILAMENT_CAMERA_H
|
||||
|
||||
#include <filament/FilamentAPI.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <math/mathfwd.h>
|
||||
#include <math/vec2.h>
|
||||
#include <math/vec4.h>
|
||||
|
||||
namespace utils {
|
||||
class Entity;
|
||||
} // namespace utils
|
||||
|
||||
namespace filament {
|
||||
|
||||
/**
|
||||
* Camera represents the eye through which the scene is viewed.
|
||||
*
|
||||
* A Camera has a position and orientation and controls the projection and exposure parameters.
|
||||
*
|
||||
* Creation and destruction
|
||||
* ========================
|
||||
*
|
||||
* In Filament, Camera is a component that must be associated with an entity. To do so,
|
||||
* use Engine::createCamera(Entity). A Camera component is destroyed using
|
||||
* Engine::destroyCameraComponent(Entity).
|
||||
*
|
||||
* ~~~~~~~~~~~{.cpp}
|
||||
* filament::Engine* engine = filament::Engine::create();
|
||||
*
|
||||
* utils::Entity myCameraEntity = utils::EntityManager::get().create();
|
||||
* filament::Camera* myCamera = engine->createCamera(myCameraEntity);
|
||||
* myCamera->setProjection(45, 16.0/9.0, 0.1, 1.0);
|
||||
* myCamera->lookAt({0, 1.60, 1}, {0, 0, 0});
|
||||
* engine->destroyCameraComponent(myCamera);
|
||||
* ~~~~~~~~~~~
|
||||
*
|
||||
*
|
||||
* Coordinate system
|
||||
* =================
|
||||
*
|
||||
* The camera coordinate system defines the *view space*. The camera points towards its -z axis
|
||||
* and is oriented such that its top side is in the direction of +y, and its right side in the
|
||||
* direction of +x.
|
||||
*
|
||||
* @note
|
||||
* Since the *near* and *far* planes are defined by the distance from the camera,
|
||||
* their respective coordinates are -\p distance(near) and -\p distance(far).
|
||||
*
|
||||
* Clipping planes
|
||||
* ===============
|
||||
*
|
||||
* The camera defines six *clipping planes* which together create a *clipping volume*. The
|
||||
* geometry outside this volume is clipped.
|
||||
*
|
||||
* The clipping volume can either be a box or a frustum depending on which projection is used,
|
||||
* respectively Projection.ORTHO or Projection.PERSPECTIVE. The six planes are specified either
|
||||
* directly or indirectly using setProjection().
|
||||
*
|
||||
* The six planes are:
|
||||
* - left
|
||||
* - right
|
||||
* - bottom
|
||||
* - top
|
||||
* - near
|
||||
* - far
|
||||
*
|
||||
* @note
|
||||
* To increase the depth-buffer precision, the *far* clipping plane is always assumed to be at
|
||||
* infinity for rendering. That is, it is not used to clip geometry during rendering.
|
||||
* However, it is used during the culling phase (objects entirely behind the *far*
|
||||
* plane are culled).
|
||||
*
|
||||
*
|
||||
* Choosing the *near* plane distance
|
||||
* ==================================
|
||||
*
|
||||
* The *near* plane distance greatly affects the depth-buffer resolution.
|
||||
*
|
||||
* Example: Precision at 1m, 10m, 100m and 1Km for various near distances assuming a 32-bit float
|
||||
* depth-buffer
|
||||
*
|
||||
* near (m) | 1 m | 10 m | 100 m | 1 Km
|
||||
* -----------:|:------:|:-------:|:--------:|:--------:
|
||||
* 0.001 | 7.2e-5 | 0.0043 | 0.4624 | 48.58
|
||||
* 0.01 | 6.9e-6 | 0.0001 | 0.0430 | 4.62
|
||||
* 0.1 | 3.6e-7 | 7.0e-5 | 0.0072 | 0.43
|
||||
* 1.0 | 0 | 3.8e-6 | 0.0007 | 0.07
|
||||
*
|
||||
*
|
||||
* As can be seen in the table above, the depth-buffer precision drops rapidly with the
|
||||
* distance to the camera.
|
||||
* Make sure to pick the highest *near* plane distance possible.
|
||||
*
|
||||
*
|
||||
* Exposure
|
||||
* ========
|
||||
*
|
||||
* The Camera is also used to set the scene's exposure, just like with a real camera. The lights
|
||||
* intensity and the Camera exposure interact to produce the final scene's brightness.
|
||||
*
|
||||
*
|
||||
*
|
||||
* \see Frustum, View
|
||||
*/
|
||||
class UTILS_PUBLIC Camera : public FilamentAPI {
|
||||
public:
|
||||
//! Denotes the projection type used by this camera. \see setProjection
|
||||
enum class Projection : int {
|
||||
PERSPECTIVE, //!< perspective projection, objects get smaller as they are farther
|
||||
ORTHO //!< orthonormal projection, preserves distances
|
||||
};
|
||||
|
||||
//! Denotes a field-of-view direction. \see setProjection
|
||||
enum class Fov : int {
|
||||
VERTICAL, //!< the field-of-view angle is defined on the vertical axis
|
||||
HORIZONTAL //!< the field-of-view angle is defined on the horizontal axis
|
||||
};
|
||||
|
||||
/** Sets the projection matrix from a frustum defined by six planes.
|
||||
*
|
||||
* @param projection type of #Projection to use.
|
||||
*
|
||||
* @param left distance in world units from the camera to the left plane,
|
||||
* at the near plane.
|
||||
* Precondition: \p left != \p right.
|
||||
*
|
||||
* @param right distance in world units from the camera to the right plane,
|
||||
* at the near plane.
|
||||
* Precondition: \p left != \p right.
|
||||
*
|
||||
* @param bottom distance in world units from the camera to the bottom plane,
|
||||
* at the near plane.
|
||||
* Precondition: \p bottom != \p top.
|
||||
*
|
||||
* @param top distance in world units from the camera to the top plane,
|
||||
* at the near plane.
|
||||
* Precondition: \p left != \p right.
|
||||
*
|
||||
* @param near distance in world units from the camera to the near plane. The near plane's
|
||||
* position in view space is z = -\p near.
|
||||
* Precondition: \p near > 0 for PROJECTION::PERSPECTIVE or
|
||||
* \p near != far for PROJECTION::ORTHO
|
||||
*
|
||||
* @param far distance in world units from the camera to the far plane. The far plane's
|
||||
* position in view space is z = -\p far.
|
||||
* Precondition: \p far > near for PROJECTION::PERSPECTIVE or
|
||||
* \p far != near for PROJECTION::ORTHO
|
||||
*
|
||||
* @attention these parameters are silently modified to meet the preconditions above.
|
||||
*
|
||||
* @see Projection, Frustum
|
||||
*/
|
||||
void setProjection(Projection projection,
|
||||
double left, double right,
|
||||
double bottom, double top,
|
||||
double near, double far) noexcept;
|
||||
|
||||
/** Sets the projection matrix from the field-of-view.
|
||||
*
|
||||
* @param fovInDegrees full field-of-view in degrees. 0 < \p fov < 180.
|
||||
* @param aspect aspect ratio \f$ \frac{width}{height} \f$. \p aspect > 0.
|
||||
* @param near distance in world units from the camera to the near plane. \p near > 0.
|
||||
* @param far distance in world units from the camera to the far plane. \p far > \p near.
|
||||
* @param direction direction of the \p fovInDegrees parameter.
|
||||
*
|
||||
* @see Fov.
|
||||
*/
|
||||
void setProjection(double fovInDegrees, double aspect, double near, double far,
|
||||
Fov direction = Fov::VERTICAL) noexcept;
|
||||
|
||||
/** Sets the projection matrix from the focal length.
|
||||
*
|
||||
* @param focalLengthInMillimeters lens's focal length in millimeters. \p focalLength > 0.
|
||||
* @param aspect aspect ratio \f$ \frac{width}{height} \f$. \p aspect > 0.
|
||||
* @param near distance in world units from the camera to the near plane. \p near > 0.
|
||||
* @param far distance in world units from the camera to the far plane. \p far > \p near.
|
||||
*/
|
||||
void setLensProjection(double focalLengthInMillimeters,
|
||||
double aspect, double near, double far) noexcept;
|
||||
|
||||
/** Sets a custom projection matrix.
|
||||
*
|
||||
* The projection matrix must be of one of the following form:
|
||||
* a 0 tx 0 a 0 0 tx
|
||||
* 0 b ty 0 0 b 0 ty
|
||||
* 0 0 tz c 0 0 c tz
|
||||
* 0 0 -1 0 0 0 0 1
|
||||
*
|
||||
* The projection matrix must define an NDC system that must match the OpenGL convention,
|
||||
* that is all 3 axis are mapped to [-1, 1].
|
||||
*
|
||||
* @param projection custom projection matrix used for rendering and culling
|
||||
* @param near distance in world units from the camera to the near plane. \p near > 0.
|
||||
* @param far distance in world units from the camera to the far plane. \p far > \p near.
|
||||
*/
|
||||
void setCustomProjection(math::mat4 const& projection, double near, double far) noexcept;
|
||||
|
||||
/** Sets the projection matrix.
|
||||
*
|
||||
* The projection matrices must be of one of the following form:
|
||||
* a 0 tx 0 a 0 0 tx
|
||||
* 0 b ty 0 0 b 0 ty
|
||||
* 0 0 tz c 0 0 c tz
|
||||
* 0 0 -1 0 0 0 0 1
|
||||
*
|
||||
* The projection matrices must define an NDC system that must match the OpenGL convention,
|
||||
* that is all 3 axis are mapped to [-1, 1].
|
||||
*
|
||||
* @param projection custom projection matrix used for rendering
|
||||
* @param projectionForCulling custom projection matrix used for culling
|
||||
* @param near distance in world units from the camera to the near plane. \p near > 0.
|
||||
* @param far distance in world units from the camera to the far plane. \p far > \p near.
|
||||
*/
|
||||
void setCustomProjection(math::mat4 const& projection, math::mat4 const& projectionForCulling,
|
||||
double near, double far) noexcept;
|
||||
|
||||
/** Sets an additional matrix that scales the projection matrix.
|
||||
*
|
||||
* This is useful to adjust the aspect ratio of the camera independent from its projection.
|
||||
* First, pass an aspect of 1.0 to setProjection. Then set the scaling with the desired aspect
|
||||
* ratio:
|
||||
*
|
||||
* const double aspect = width / height;
|
||||
*
|
||||
* // with Fov::HORIZONTAL passed to setProjection:
|
||||
* camera->setScaling(double4 {1.0, aspect});
|
||||
*
|
||||
* // with Fov::VERTICAL passed to setProjection:
|
||||
* camera->setScaling(double4 {1.0 / aspect, 1.0});
|
||||
*
|
||||
*
|
||||
* By default, this is an identity matrix.
|
||||
*
|
||||
* @param scaling diagonal of the 2x2 scaling matrix to be applied after the projection matrix.
|
||||
*
|
||||
* @see setProjection, setLensProjection, setCustomProjection
|
||||
*/
|
||||
void setScaling(math::double2 scaling) noexcept;
|
||||
|
||||
/**
|
||||
* Sets an additional matrix that shifts the projection matrix.
|
||||
* By default, this is an identity matrix.
|
||||
*
|
||||
* @param shift x and y translation added to the projection matrix, specified in NDC
|
||||
* coordinates, that is, if the translation must be specified in pixels,
|
||||
* shift must be scaled by 1.0 / { viewport.width, viewport.height }.
|
||||
*
|
||||
* @see setProjection, setLensProjection, setCustomProjection
|
||||
*/
|
||||
void setShift(math::double2 shift) noexcept;
|
||||
|
||||
/** Returns the scaling amount used to scale the projection matrix.
|
||||
*
|
||||
* @return the diagonal of the scaling matrix applied after the projection matrix.
|
||||
*
|
||||
* @see setScaling
|
||||
*/
|
||||
math::double4 getScaling() const noexcept;
|
||||
|
||||
/** Returns the shift amount used to translate the projection matrix.
|
||||
*
|
||||
* @return the 2D translation x and y offsets applied after the projection matrix.
|
||||
*
|
||||
* @see setShift
|
||||
*/
|
||||
math::double2 getShift() const noexcept;
|
||||
|
||||
/** Returns the projection matrix used for rendering.
|
||||
*
|
||||
* The projection matrix used for rendering always has its far plane set to infinity. This
|
||||
* is why it may differ from the matrix set through setProjection() or setLensProjection().
|
||||
*
|
||||
* @return The projection matrix used for rendering
|
||||
*
|
||||
* @see setProjection, setLensProjection, setCustomProjection, getCullingProjectionMatrix
|
||||
*/
|
||||
math::mat4 getProjectionMatrix() const noexcept;
|
||||
|
||||
|
||||
/** Returns the projection matrix used for culling (far plane is finite).
|
||||
*
|
||||
* @return The projection matrix set by setProjection or setLensProjection.
|
||||
*
|
||||
* @see setProjection, setLensProjection, getProjectionMatrix
|
||||
*/
|
||||
math::mat4 getCullingProjectionMatrix() const noexcept;
|
||||
|
||||
|
||||
//! Returns the frustum's near plane
|
||||
float getNear() const noexcept;
|
||||
|
||||
//! Returns the frustum's far plane used for culling
|
||||
float getCullingFar() const noexcept;
|
||||
|
||||
/** Sets the camera's view matrix.
|
||||
*
|
||||
* Helper method to set the camera's entity transform component.
|
||||
* It has the same effect as calling:
|
||||
*
|
||||
* ~~~~~~~~~~~{.cpp}
|
||||
* engine.getTransformManager().setTransform(
|
||||
* engine.getTransformManager().getInstance(camera->getEntity()), view);
|
||||
* ~~~~~~~~~~~
|
||||
*
|
||||
* @param view The camera position and orientation provided as a rigid transform matrix.
|
||||
*
|
||||
* @note The Camera "looks" towards its -z axis
|
||||
*
|
||||
* @warning \p view must be a rigid transform
|
||||
*/
|
||||
void setModelMatrix(const math::mat4& view) noexcept;
|
||||
void setModelMatrix(const math::mat4f& view) noexcept; //!< \overload
|
||||
|
||||
/** Sets the camera's view matrix
|
||||
*
|
||||
* @param eye The position of the camera in world space.
|
||||
* @param center The point in world space the camera is looking at.
|
||||
* @param up A unit vector denoting the camera's "up" direction.
|
||||
*/
|
||||
void lookAt(const math::float3& eye,
|
||||
const math::float3& center,
|
||||
const math::float3& up) noexcept;
|
||||
|
||||
/** Sets the camera's view matrix, assuming up is along the y axis
|
||||
*
|
||||
* @param eye The position of the camera in world space.
|
||||
* @param center The point in world space the camera is looking at.
|
||||
*/
|
||||
void lookAt(const math::float3& eye,
|
||||
const math::float3& center) noexcept;
|
||||
|
||||
/** Returns the camera's model matrix
|
||||
*
|
||||
* Helper method to return the camera's entity transform component.
|
||||
* It has the same effect as calling:
|
||||
*
|
||||
* ~~~~~~~~~~~{.cpp}
|
||||
* engine.getTransformManager().getWorldTransform(
|
||||
* engine.getTransformManager().getInstance(camera->getEntity()));
|
||||
* ~~~~~~~~~~~
|
||||
*
|
||||
* @return The camera's pose in world space as a rigid transform. Parent transforms, if any,
|
||||
* are taken into account.
|
||||
*/
|
||||
math::mat4 getModelMatrix() const noexcept;
|
||||
|
||||
//! Returns the camera's view matrix (inverse of the model matrix)
|
||||
math::mat4 getViewMatrix() const noexcept;
|
||||
|
||||
//! Returns the camera's position in world space
|
||||
math::float3 getPosition() const noexcept;
|
||||
|
||||
//! Returns the camera's normalized left vector
|
||||
math::float3 getLeftVector() const noexcept;
|
||||
|
||||
//! Returns the camera's normalized up vector
|
||||
math::float3 getUpVector() const noexcept;
|
||||
|
||||
//! Returns the camera's forward vector
|
||||
math::float3 getForwardVector() const noexcept;
|
||||
|
||||
//! Returns the camera's field of view in degrees
|
||||
float getFieldOfViewInDegrees(Fov direction) const noexcept;
|
||||
|
||||
//! Returns a Frustum object in world space
|
||||
class Frustum getFrustum() const noexcept;
|
||||
|
||||
//! Returns the entity representing this camera
|
||||
utils::Entity getEntity() const noexcept;
|
||||
|
||||
/** Sets this camera's exposure (default is f/16, 1/125s, 100 ISO)
|
||||
*
|
||||
* The exposure ultimately controls the scene's brightness, just like with a real camera.
|
||||
* The default values provide adequate exposure for a camera placed outdoors on a sunny day
|
||||
* with the sun at the zenith.
|
||||
*
|
||||
* @param aperture Aperture in f-stops, clamped between 0.5 and 64.
|
||||
* A lower \p aperture value *increases* the exposure, leading to
|
||||
* a brighter scene. Realistic values are between 0.95 and 32.
|
||||
*
|
||||
* @param shutterSpeed Shutter speed in seconds, clamped between 1/25,000 and 60.
|
||||
* A lower shutter speed increases the exposure. Realistic values are
|
||||
* between 1/8000 and 30.
|
||||
*
|
||||
* @param sensitivity Sensitivity in ISO, clamped between 10 and 204,800.
|
||||
* A higher \p sensitivity increases the exposure. Realistic values are
|
||||
* between 50 and 25600.
|
||||
*
|
||||
* @note
|
||||
* With the default parameters, the scene must contain at least one Light of intensity
|
||||
* similar to the sun (e.g.: a 100,000 lux directional light).
|
||||
*
|
||||
* @see LightManager, Exposure
|
||||
*/
|
||||
void setExposure(float aperture, float shutterSpeed, float sensitivity) noexcept;
|
||||
|
||||
/** Sets this camera's exposure directly. Calling this method will set the aperture
|
||||
* to 1.0, the shutter speed to 1.2 and the sensitivity will be computed to match
|
||||
* the requested exposure (for a desired exposure of 1.0, the sensitivity will be
|
||||
* set to 100 ISO).
|
||||
*
|
||||
* This method is useful when trying to match the lighting of other engines or tools.
|
||||
* Many engines/tools use unit-less light intensities, which can be matched by setting
|
||||
* the exposure manually. This can be typically achieved by setting the exposure to
|
||||
* 1.0.
|
||||
*/
|
||||
void setExposure(float exposure) noexcept {
|
||||
setExposure(1.0f, 1.2f, 100.0f * (1.0f / exposure));
|
||||
}
|
||||
|
||||
//! returns this camera's aperture in f-stops
|
||||
float getAperture() const noexcept;
|
||||
|
||||
//! returns this camera's shutter speed in seconds
|
||||
float getShutterSpeed() const noexcept;
|
||||
|
||||
//! returns this camera's sensitivity in ISO
|
||||
float getSensitivity() const noexcept;
|
||||
|
||||
//! returns the focal length in meters [m] for a 35mm camera
|
||||
double getFocalLength() const noexcept;
|
||||
|
||||
/**
|
||||
* Sets the camera focus distance. This is used by the Depth-of-field PostProcessing effect.
|
||||
* @param distance Distance from the camera to the plane of focus in world units.
|
||||
* Must be positive and larger than the near clipping plane.
|
||||
*/
|
||||
void setFocusDistance(float distance) noexcept;
|
||||
|
||||
//! Returns the focus distance in world units
|
||||
float getFocusDistance() const noexcept;
|
||||
|
||||
/**
|
||||
* Returns the inverse of a projection matrix.
|
||||
*
|
||||
* \param p the projection matrix to inverse
|
||||
* \returns the inverse of the projection matrix \p p
|
||||
*
|
||||
* \warning the projection matrix to invert must have one of the form below:
|
||||
* - perspective projection
|
||||
*
|
||||
* \f$
|
||||
* \left(
|
||||
* \begin{array}{cccc}
|
||||
* a & 0 & tx & 0 \\
|
||||
* 0 & b & ty & 0 \\
|
||||
* 0 & 0 & tz & c \\
|
||||
* 0 & 0 & -1 & 0 \\
|
||||
* \end{array}
|
||||
* \right)
|
||||
* \f$
|
||||
*
|
||||
* - orthographic projection
|
||||
*
|
||||
* \f$
|
||||
* \left(
|
||||
* \begin{array}{cccc}
|
||||
* a & 0 & 0 & tx \\
|
||||
* 0 & b & 0 & ty \\
|
||||
* 0 & 0 & c & tz \\
|
||||
* 0 & 0 & 0 & 1 \\
|
||||
* \end{array}
|
||||
* \right)
|
||||
* \f$
|
||||
*/
|
||||
static math::mat4 inverseProjection(const math::mat4& p) noexcept;
|
||||
|
||||
/**
|
||||
* Returns the inverse of a projection matrix.
|
||||
* @see inverseProjection(const math::mat4&)
|
||||
*/
|
||||
static math::mat4f inverseProjection(const math::mat4f& p) noexcept;
|
||||
|
||||
/**
|
||||
* Helper to compute the effective focal length taking into account the focus distance
|
||||
*
|
||||
* @param focalLength focal length in any unit (e.g. [m] or [mm])
|
||||
* @param focusDistance focus distance in same unit as focalLength
|
||||
* @return the effective focal length in same unit as focalLength
|
||||
*/
|
||||
static double computeEffectiveFocalLength(double focalLength, double focusDistance) noexcept;
|
||||
|
||||
/**
|
||||
* Helper to compute the effective field-of-view taking into account the focus distance
|
||||
*
|
||||
* @param fovInDegrees full field of view in degrees
|
||||
* @param focusDistance focus distance in meters [m]
|
||||
* @return effective full field of view in degrees
|
||||
*/
|
||||
static double computeEffectiveFov(double fovInDegrees, double focusDistance) noexcept;
|
||||
};
|
||||
|
||||
} // namespace filament
|
||||
|
||||
#endif // TNT_FILAMENT_CAMERA_H
|
||||
210
ios/include/filament/Color.h
Normal file
210
ios/include/filament/Color.h
Normal file
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef TNT_FILAMENT_COLOR_H
|
||||
#define TNT_FILAMENT_COLOR_H
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <math/vec3.h>
|
||||
#include <math/vec4.h>
|
||||
|
||||
namespace filament {
|
||||
|
||||
//! RGB color in linear space
|
||||
using LinearColor = math::float3;
|
||||
|
||||
//! RGB color in sRGB space
|
||||
using sRGBColor = math::float3;
|
||||
|
||||
//! RGBA color in linear space, with alpha
|
||||
using LinearColorA = math::float4;
|
||||
|
||||
//! RGBA color in sRGB space, with alpha
|
||||
using sRGBColorA = math::float4;
|
||||
|
||||
//! types of RGB colors
|
||||
enum class RgbType : uint8_t {
|
||||
sRGB, //!< the color is defined in sRGB space
|
||||
LINEAR, //!< the color is defined in linear space
|
||||
};
|
||||
|
||||
//! types of RGBA colors
|
||||
enum class RgbaType : uint8_t {
|
||||
/**
|
||||
* the color is defined in sRGB space and the RGB values
|
||||
* have not been premultiplied by the alpha (for instance, a 50%
|
||||
* transparent red is <1,0,0,0.5>)
|
||||
*/
|
||||
sRGB,
|
||||
/**
|
||||
* the color is defined in linear space and the RGB values
|
||||
* have not been premultiplied by the alpha (for instance, a 50%
|
||||
* transparent red is <1,0,0,0.5>)
|
||||
*/
|
||||
LINEAR,
|
||||
/**
|
||||
* the color is defined in sRGB space and the RGB values
|
||||
* have been premultiplied by the alpha (for instance, a 50%
|
||||
* transparent red is <0.5,0,0,0.5>)
|
||||
*/
|
||||
PREMULTIPLIED_sRGB,
|
||||
/**
|
||||
* the color is defined in linear space and the RGB values
|
||||
* have been premultiplied by the alpha (for instance, a 50%
|
||||
* transparent red is <0.5,0,0,0.5>)
|
||||
*/
|
||||
PREMULTIPLIED_LINEAR
|
||||
};
|
||||
|
||||
//! type of color conversion to use when converting to/from sRGB and linear spaces
|
||||
enum ColorConversion {
|
||||
ACCURATE, //!< accurate conversion using the sRGB standard
|
||||
FAST //!< fast conversion using a simple gamma 2.2 curve
|
||||
};
|
||||
|
||||
/**
|
||||
* Utilities to manipulate and convert colors
|
||||
*/
|
||||
class UTILS_PUBLIC Color {
|
||||
public:
|
||||
//! converts an RGB color to linear space, the conversion depends on the specified type
|
||||
static LinearColor toLinear(RgbType type, math::float3 color);
|
||||
|
||||
//! converts an RGBA color to linear space, the conversion depends on the specified type
|
||||
static LinearColorA toLinear(RgbaType type, math::float4 color);
|
||||
|
||||
//! converts an RGB color in sRGB space to an RGB color in linear space
|
||||
template<ColorConversion = ACCURATE>
|
||||
static LinearColor toLinear(sRGBColor const& color);
|
||||
|
||||
//! converts an RGB color in linear space to an RGB color in sRGB space
|
||||
template<ColorConversion = ACCURATE>
|
||||
static sRGBColor toSRGB(LinearColor const& color);
|
||||
|
||||
/**
|
||||
* converts an RGBA color in sRGB space to an RGBA color in linear space
|
||||
* the alpha component is left unmodified
|
||||
*/
|
||||
template<ColorConversion = ACCURATE>
|
||||
static LinearColorA toLinear(sRGBColorA const& color);
|
||||
|
||||
/**
|
||||
* converts an RGBA color in linear space to an RGBA color in sRGB space
|
||||
* the alpha component is left unmodified
|
||||
*/
|
||||
template<ColorConversion = ACCURATE>
|
||||
static sRGBColorA toSRGB(LinearColorA const& color);
|
||||
|
||||
/**
|
||||
* converts a correlated color temperature to a linear RGB color in sRGB
|
||||
* space the temperature must be expressed in kelvin and must be in the
|
||||
* range 1,000K to 15,000K
|
||||
*/
|
||||
static LinearColor cct(float K);
|
||||
|
||||
/**
|
||||
* converts a CIE standard illuminant series D to a linear RGB color in
|
||||
* sRGB space the temperature must be expressed in kelvin and must be in
|
||||
* the range 4,000K to 25,000K
|
||||
*/
|
||||
static LinearColor illuminantD(float K);
|
||||
|
||||
/**
|
||||
* computes the Beer-Lambert absorption coefficients from the specified
|
||||
* transmittance color and distance. The computed absorption will guarantee
|
||||
* the white light will become the specified color at the specified distance.
|
||||
* The output of this function can be used as the absorption parameter of
|
||||
* materials that use refraction.
|
||||
*
|
||||
* @param color the desired linear RGB color in sRGB space
|
||||
* @param distance the distance at which white light should become the specified color
|
||||
*
|
||||
* @return absorption coefficients for the Beer-Lambert law
|
||||
*/
|
||||
static math::float3 absorptionAtDistance(LinearColor const& color, float distance);
|
||||
|
||||
private:
|
||||
static math::float3 sRGBToLinear(math::float3 color) noexcept;
|
||||
static math::float3 linearToSRGB(math::float3 color) noexcept;
|
||||
};
|
||||
|
||||
// Use the default implementation from the header
|
||||
template<>
|
||||
inline LinearColor Color::toLinear<FAST>(sRGBColor const& color) {
|
||||
return pow(color, 2.2f);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline LinearColorA Color::toLinear<FAST>(sRGBColorA const& color) {
|
||||
return LinearColorA{pow(color.rgb, 2.2f), color.a};
|
||||
}
|
||||
|
||||
template<>
|
||||
inline LinearColor Color::toLinear<ACCURATE>(sRGBColor const& color) {
|
||||
return sRGBToLinear(color);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline LinearColorA Color::toLinear<ACCURATE>(sRGBColorA const& color) {
|
||||
return LinearColorA{sRGBToLinear(color.rgb), color.a};
|
||||
}
|
||||
|
||||
// Use the default implementation from the header
|
||||
template<>
|
||||
inline sRGBColor Color::toSRGB<FAST>(LinearColor const& color) {
|
||||
return pow(color, 1.0f / 2.2f);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline sRGBColorA Color::toSRGB<FAST>(LinearColorA const& color) {
|
||||
return sRGBColorA{pow(color.rgb, 1.0f / 2.2f), color.a};
|
||||
}
|
||||
|
||||
template<>
|
||||
inline sRGBColor Color::toSRGB<ACCURATE>(LinearColor const& color) {
|
||||
return linearToSRGB(color);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline sRGBColorA Color::toSRGB<ACCURATE>(LinearColorA const& color) {
|
||||
return sRGBColorA{linearToSRGB(color.rgb), color.a};
|
||||
}
|
||||
|
||||
inline LinearColor Color::toLinear(RgbType type, math::float3 color) {
|
||||
return (type == RgbType::LINEAR) ? color : Color::toLinear<ACCURATE>(color);
|
||||
}
|
||||
|
||||
// converts an RGBA color to linear space
|
||||
// the conversion depends on the specified type
|
||||
inline LinearColorA Color::toLinear(RgbaType type, math::float4 color) {
|
||||
switch (type) {
|
||||
case RgbaType::sRGB:
|
||||
return Color::toLinear<ACCURATE>(color) * math::float4{color.a, color.a, color.a, 1.0f};
|
||||
case RgbaType::LINEAR:
|
||||
return color * math::float4{color.a, color.a, color.a, 1.0f};
|
||||
case RgbaType::PREMULTIPLIED_sRGB:
|
||||
return Color::toLinear<ACCURATE>(color);
|
||||
case RgbaType::PREMULTIPLIED_LINEAR:
|
||||
return color;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace filament
|
||||
|
||||
#endif // TNT_FILAMENT_COLOR_H
|
||||
405
ios/include/filament/ColorGrading.h
Normal file
405
ios/include/filament/ColorGrading.h
Normal file
@@ -0,0 +1,405 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef TNT_FILAMENT_COLOR_GRADING_H
|
||||
#define TNT_FILAMENT_COLOR_GRADING_H
|
||||
|
||||
#include <filament/FilamentAPI.h>
|
||||
#include <filament/ToneMapper.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <math/mathfwd.h>
|
||||
|
||||
namespace filament {
|
||||
|
||||
class Engine;
|
||||
class FColorGrading;
|
||||
|
||||
/**
|
||||
* ColorGrading is used to transform (either to modify or correct) the colors of the HDR buffer
|
||||
* rendered by Filament. Color grading transforms are applied after lighting, and after any lens
|
||||
* effects (bloom for instance), and include tone mapping.
|
||||
*
|
||||
* Creation, usage and destruction
|
||||
* ===============================
|
||||
*
|
||||
* A ColorGrading object is created using the ColorGrading::Builder and destroyed by calling
|
||||
* Engine::destroy(const ColorGrading*). A ColorGrading object is meant to be set on a View.
|
||||
*
|
||||
* ~~~~~~~~~~~{.cpp}
|
||||
* filament::Engine* engine = filament::Engine::create();
|
||||
*
|
||||
* filament::ColorGrading* colorGrading = filament::ColorGrading::Builder()
|
||||
* .toneMapping(filament::ColorGrading::ToneMapping::ACES)
|
||||
* .build(*engine);
|
||||
*
|
||||
* myView->setColorGrading(colorGrading);
|
||||
*
|
||||
* engine->destroy(colorGrading);
|
||||
* ~~~~~~~~~~~
|
||||
*
|
||||
* Performance
|
||||
* ===========
|
||||
*
|
||||
* Creating a new ColorGrading object may be more expensive than other Filament objects as a
|
||||
* 3D LUT may need to be generated. The generation of a 3D LUT, if necessary, may happen on
|
||||
* the CPU.
|
||||
*
|
||||
* Ordering
|
||||
* ========
|
||||
*
|
||||
* The various transforms held by ColorGrading are applied in the following order:
|
||||
* - Exposure
|
||||
* - White balance
|
||||
* - Channel mixer
|
||||
* - Shadows/mid-tones/highlights
|
||||
* - Slope/offset/power (CDL)
|
||||
* - Contrast
|
||||
* - Vibrance
|
||||
* - Saturation
|
||||
* - Curves
|
||||
* - Tone mapping
|
||||
* - Luminance scaling
|
||||
*
|
||||
* Defaults
|
||||
* ========
|
||||
*
|
||||
* Here are the default color grading options:
|
||||
* - Exposure: 0.0
|
||||
* - White balance: temperature 0, and tint 0
|
||||
* - Channel mixer: red {1,0,0}, green {0,1,0}, blue {0,0,1}
|
||||
* - Shadows/mid-tones/highlights: shadows {1,1,1,0}, mid-tones {1,1,1,0}, highlights {1,1,1,0},
|
||||
* ranges {0,0.333,0.550,1}
|
||||
* - Slope/offset/power: slope 1.0, offset 0.0, and power 1.0
|
||||
* - Contrast: 1.0
|
||||
* - Vibrance: 1.0
|
||||
* - Saturation: 1.0
|
||||
* - Curves: gamma {1,1,1}, midPoint {1,1,1}, and scale {1,1,1}
|
||||
* - Tone mapping: ACESLegacyToneMapper
|
||||
* - Luminance scaling: false
|
||||
*
|
||||
* @see View
|
||||
*/
|
||||
class UTILS_PUBLIC ColorGrading : public FilamentAPI {
|
||||
struct BuilderDetails;
|
||||
public:
|
||||
enum class QualityLevel : uint8_t {
|
||||
LOW,
|
||||
MEDIUM,
|
||||
HIGH,
|
||||
ULTRA
|
||||
};
|
||||
|
||||
/**
|
||||
* List of available tone-mapping operators.
|
||||
*
|
||||
* @deprecated Use Builder::toneMapper(ToneMapper*) instead
|
||||
*/
|
||||
enum class UTILS_DEPRECATED ToneMapping : uint8_t {
|
||||
LINEAR = 0, //!< Linear tone mapping (i.e. no tone mapping)
|
||||
ACES_LEGACY = 1, //!< ACES tone mapping, with a brightness modifier to match Filament's legacy tone mapper
|
||||
ACES = 2, //!< ACES tone mapping
|
||||
FILMIC = 3, //!< Filmic tone mapping, modelled after ACES but applied in sRGB space
|
||||
DISPLAY_RANGE = 4, //!< Tone mapping used to validate/debug scene exposure
|
||||
};
|
||||
|
||||
//! Use Builder to construct a ColorGrading object instance
|
||||
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;
|
||||
|
||||
/**
|
||||
* Sets the quality level of the color grading. When color grading is implemented using
|
||||
* a 3D LUT, the quality level may impact the resolution and bit depth of the backing
|
||||
* 3D texture. For instance, a low quality level will use a 16x16x16 10 bit LUT, a medium
|
||||
* quality level will use a 32x32x32 10 bit LUT, a high quality will use a 32x32x32 16 bit
|
||||
* LUT, and a ultra quality will use a 64x64x64 16 bit LUT.
|
||||
*
|
||||
* The default quality is medium.
|
||||
*
|
||||
* @param qualityLevel The desired quality of the color grading process
|
||||
*
|
||||
* @return This Builder, for chaining calls
|
||||
*/
|
||||
Builder& quality(QualityLevel qualityLevel) noexcept;
|
||||
|
||||
/**
|
||||
* Selects the tone mapping operator to apply to the HDR color buffer as the last
|
||||
* operation of the color grading post-processing step.
|
||||
*
|
||||
* The default tone mapping operator is ACESLegacyToneMapper.
|
||||
*
|
||||
* The specified tone mapper must have a lifecycle that exceeds the lifetime of
|
||||
* this builder. Since the build(Engine&) method is synchronous, it is safe to
|
||||
* delete the tone mapper object after that finishes executing.
|
||||
*
|
||||
* @param toneMapper The tone mapping operator to apply to the HDR color buffer
|
||||
*
|
||||
* @return This Builder, for chaining calls
|
||||
*/
|
||||
Builder& toneMapper(const ToneMapper* toneMapper) noexcept;
|
||||
|
||||
/**
|
||||
* Selects the tone mapping operator to apply to the HDR color buffer as the last
|
||||
* operation of the color grading post-processing step.
|
||||
*
|
||||
* The default tone mapping operator is ACES_LEGACY.
|
||||
*
|
||||
* @param toneMapping The tone mapping operator to apply to the HDR color buffer
|
||||
*
|
||||
* @return This Builder, for chaining calls
|
||||
*
|
||||
* @deprecated Use toneMapper(ToneMapper*) instead
|
||||
*/
|
||||
UTILS_DEPRECATED
|
||||
Builder& toneMapping(ToneMapping toneMapping) noexcept;
|
||||
|
||||
/**
|
||||
* Enables or disables the luminance scaling component (LICH) from the exposure value
|
||||
* invariant luminance system (EVILS). When this setting is enabled, pixels with high
|
||||
* chromatic values will roll-off to white to offer a more natural rendering. This step
|
||||
* also helps avoid undesirable hue skews caused by out of gamut colors clipped
|
||||
* to the destination color gamut.
|
||||
*
|
||||
* When luminance scaling is enabled, tone mapping is performed on the luminance of each
|
||||
* pixel instead of per-channel.
|
||||
*
|
||||
* @param luminanceScaling Enables or disables EVILS post-tone mapping
|
||||
*
|
||||
* @return This Builder, for chaining calls
|
||||
*/
|
||||
Builder& luminanceScaling(bool luminanceScaling) noexcept;
|
||||
|
||||
/**
|
||||
* Adjusts the exposure of this image. The exposure is specified in stops:
|
||||
* each stop brightens (positive values) or darkens (negative values) the image by
|
||||
* a factor of 2. This means that an exposure of 3 will brighten the image 8 times
|
||||
* more than an exposure of 0 (2^3 = 8 and 2^0 = 1). Contrary to the camera's exposure,
|
||||
* this setting is applied after all post-processing (bloom, etc.) are applied.
|
||||
*
|
||||
* @param exposure Value in EV stops. Can be negative, 0, or positive.
|
||||
*
|
||||
* @return This Builder, for chaining calls
|
||||
*/
|
||||
Builder& exposure(float exposure) noexcept;
|
||||
|
||||
/**
|
||||
* Adjusts the while balance of the image. This can be used to remove color casts
|
||||
* and correct the appearance of the white point in the scene, or to alter the
|
||||
* overall chromaticity of the image for artistic reasons (to make the image appear
|
||||
* cooler or warmer for instance).
|
||||
*
|
||||
* The while balance adjustment is defined with two values:
|
||||
* - Temperature, to modify the color temperature. This value will modify the colors
|
||||
* on a blue/yellow axis. Lower values apply a cool color temperature, and higher
|
||||
* values apply a warm color temperature. The lowest value, -1.0f, is equivalent to
|
||||
* a temperature of 50,000K. The highest value, 1.0f, is equivalent to a temperature
|
||||
* of 2,000K.
|
||||
* - Tint, to modify the colors on a green/magenta axis. The lowest value, -1.0f, will
|
||||
* apply a strong green cast, and the highest value, 1.0f, will apply a strong magenta
|
||||
* cast.
|
||||
*
|
||||
* Both values are expected to be in the range [-1.0..+1.0]. Values outside of that
|
||||
* range will be clipped to that range.
|
||||
*
|
||||
* @param temperature Modification on the blue/yellow axis, as a value between -1.0 and +1.0.
|
||||
* @param tint Modification on the green/magenta axis, as a value between -1.0 and +1.0.
|
||||
*
|
||||
* @return This Builder, for chaining calls
|
||||
*/
|
||||
Builder& whiteBalance(float temperature, float tint) noexcept;
|
||||
|
||||
/**
|
||||
* The channel mixer adjustment modifies each output color channel using the specified
|
||||
* mix of the source color channels.
|
||||
*
|
||||
* By default each output color channel is set to use 100% of the corresponding source
|
||||
* channel and 0% of the other channels. For instance, the output red channel is set to
|
||||
* {1.0, 0.0, 1.0} or 100% red, 0% green and 0% blue.
|
||||
*
|
||||
* Each output channel can add or subtract data from the source channel by using values
|
||||
* in the range [-2.0..+2.0]. Values outside of that range will be clipped to that range.
|
||||
*
|
||||
* Using the channel mixer adjustment you can for instance create a monochrome output
|
||||
* by setting all 3 output channels to the same mix. For instance: {0.4, 0.4, 0.2} for
|
||||
* all 3 output channels(40% red, 40% green and 20% blue).
|
||||
*
|
||||
* More complex mixes can be used to create more complex effects. For instance, here is
|
||||
* a mix that creates a sepia tone effect:
|
||||
* - outRed = {0.255, 0.858, 0.087}
|
||||
* - outGreen = {0.213, 0.715, 0.072}
|
||||
* - outBlue = {0.170, 0.572, 0.058}
|
||||
*
|
||||
* @param outRed The mix of source RGB for the output red channel, between -2.0 and +2.0
|
||||
* @param outGreen The mix of source RGB for the output green channel, between -2.0 and +2.0
|
||||
* @param outBlue The mix of source RGB for the output blue channel, between -2.0 and +2.0
|
||||
*
|
||||
* @return This Builder, for chaining calls
|
||||
*/
|
||||
Builder& channelMixer(
|
||||
math::float3 outRed, math::float3 outGreen, math::float3 outBlue) noexcept;
|
||||
|
||||
/**
|
||||
* Adjusts the colors separately in 3 distinct tonal ranges or zones: shadows, mid-tones,
|
||||
* and highlights.
|
||||
*
|
||||
* The tonal zones are by the ranges parameter: the x and y components define the beginning
|
||||
* and end of the transition from shadows to mid-tones, and the z and w components define
|
||||
* the beginning and end of the transition from mid-tones to highlights.
|
||||
*
|
||||
* A smooth transition is applied between the zones which means for instance that the
|
||||
* correction color of the shadows range will partially apply to the mid-tones, and the
|
||||
* other way around. This ensure smooth visual transitions in the final image.
|
||||
*
|
||||
* Each correction color is defined as a linear RGB color and a weight. The weight is a
|
||||
* value (which may be positive or negative) that is added to the linear RGB color before
|
||||
* mixing. This can be used to darken or brighten the selected tonal range.
|
||||
*
|
||||
* Shadows/mid-tones/highlights adjustment are performed linear space.
|
||||
*
|
||||
* @param shadows Linear RGB color (.rgb) and weight (.w) to apply to the shadows
|
||||
* @param midtones Linear RGB color (.rgb) and weight (.w) to apply to the mid-tones
|
||||
* @param highlights Linear RGB color (.rgb) and weight (.w) to apply to the highlights
|
||||
* @param ranges Range of the shadows (x and y), and range of the highlights (z and w)
|
||||
*
|
||||
* @return This Builder, for chaining calls
|
||||
*/
|
||||
Builder& shadowsMidtonesHighlights(
|
||||
math::float4 shadows, math::float4 midtones, math::float4 highlights,
|
||||
math::float4 ranges) noexcept;
|
||||
|
||||
/**
|
||||
* Applies a slope, offset, and power, as defined by the ASC CDL (American Society of
|
||||
* Cinematographers Color Decision List) to the image. The CDL can be used to adjust the
|
||||
* colors of different tonal ranges in the image.
|
||||
*
|
||||
* The ASC CDL is similar to the lift/gamma/gain controls found in many color grading tools.
|
||||
* Lift is equivalent to a combination of offset and slope, gain is equivalent to slope,
|
||||
* and gamma is equivalent to power.
|
||||
*
|
||||
* The slope and power values must be strictly positive. Values less than or equal to 0 will
|
||||
* be clamped to a small positive value, offset can be any positive or negative value.
|
||||
*
|
||||
* Version 1.2 of the ASC CDL adds saturation control, which is here provided as a separate
|
||||
* API. See the saturation() method for more information.
|
||||
*
|
||||
* Slope/offset/power adjustments are performed in log space.
|
||||
*
|
||||
* @param slope Multiplier of the input color, must be a strictly positive number
|
||||
* @param offset Added to the input color, can be a negative or positive number, including 0
|
||||
* @param power Power exponent of the input color, must be a strictly positive number
|
||||
*
|
||||
* @return This Builder, for chaining calls
|
||||
*/
|
||||
Builder& slopeOffsetPower(math::float3 slope, math::float3 offset, math::float3 power) noexcept;
|
||||
|
||||
/**
|
||||
* Adjusts the contrast of the image. Lower values decrease the contrast of the image
|
||||
* (the tonal range is narrowed), and higher values increase the contrast of the image
|
||||
* (the tonal range is widened). A value of 1.0 has no effect.
|
||||
*
|
||||
* The contrast is defined as a value in the range [0.0...2.0]. Values outside of that
|
||||
* range will be clipped to that range.
|
||||
*
|
||||
* Contrast adjustment is performed in log space.
|
||||
*
|
||||
* @param contrast Contrast expansion, between 0.0 and 2.0. 1.0 leaves contrast unaffected
|
||||
*
|
||||
* @return This Builder, for chaining calls
|
||||
*/
|
||||
Builder& contrast(float contrast) noexcept;
|
||||
|
||||
/**
|
||||
* Adjusts the saturation of the image based on the input color's saturation level.
|
||||
* Colors with a high level of saturation are less affected than colors with low saturation
|
||||
* levels.
|
||||
*
|
||||
* Lower vibrance values decrease intensity of the colors present in the image, and
|
||||
* higher values increase the intensity of the colors in the image. A value of 1.0 has
|
||||
* no effect.
|
||||
*
|
||||
* The vibrance is defined as a value in the range [0.0...2.0]. Values outside of that
|
||||
* range will be clipped to that range.
|
||||
*
|
||||
* Vibrance adjustment is performed in linear space.
|
||||
*
|
||||
* @param vibrance Vibrance, between 0.0 and 2.0. 1.0 leaves vibrance unaffected
|
||||
*
|
||||
* @return This Builder, for chaining calls
|
||||
*/
|
||||
Builder& vibrance(float vibrance) noexcept;
|
||||
|
||||
/**
|
||||
* Adjusts the saturation of the image. Lower values decrease intensity of the colors
|
||||
* present in the image, and higher values increase the intensity of the colors in the
|
||||
* image. A value of 1.0 has no effect.
|
||||
*
|
||||
* The saturation is defined as a value in the range [0.0...2.0]. Values outside of that
|
||||
* range will be clipped to that range.
|
||||
*
|
||||
* Saturation adjustment is performed in linear space.
|
||||
*
|
||||
* @param saturation Saturation, between 0.0 and 2.0. 1.0 leaves saturation unaffected
|
||||
*
|
||||
* @return This Builder, for chaining calls
|
||||
*/
|
||||
Builder& saturation(float saturation) noexcept;
|
||||
|
||||
/**
|
||||
* Applies a curve to each RGB channel of the image. Each curve is defined by 3 values:
|
||||
* a gamma value applied to the shadows only, a mid-point indicating where shadows stop
|
||||
* and highlights start, and a scale factor for the highlights.
|
||||
*
|
||||
* The gamma and mid-point must be strictly positive values. If they are not, they will be
|
||||
* clamped to a small positive value. The scale can be any negative of positive value.
|
||||
*
|
||||
* Curves are applied in linear space.
|
||||
*
|
||||
* @param shadowGamma Power value to apply to the shadows, must be strictly positive
|
||||
* @param midPoint Mid-point defining where shadows stop and highlights start, must be strictly positive
|
||||
* @param highlightScale Scale factor for the highlights, can be any negative or positive value
|
||||
*
|
||||
* @return This Builder, for chaining calls
|
||||
*/
|
||||
Builder& curves(math::float3 shadowGamma, math::float3 midPoint, math::float3 highlightScale) noexcept;
|
||||
|
||||
/**
|
||||
* Creates the ColorGrading object and returns a pointer to it.
|
||||
*
|
||||
* @param engine Reference to the filament::Engine to associate this ColorGrading with.
|
||||
*
|
||||
* @return pointer to the newly created object or nullptr if exceptions are disabled and
|
||||
* an error occurred.
|
||||
*/
|
||||
ColorGrading* build(Engine& engine);
|
||||
|
||||
private:
|
||||
friend class FColorGrading;
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace filament
|
||||
|
||||
#endif // TNT_FILAMENT_COLOR_GRADING_H
|
||||
131
ios/include/filament/DebugRegistry.h
Normal file
131
ios/include/filament/DebugRegistry.h
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
#ifndef TNT_FILAMENT_DEBUG_H
|
||||
#define TNT_FILAMENT_DEBUG_H
|
||||
|
||||
#include <filament/FilamentAPI.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <math/mathfwd.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace filament {
|
||||
|
||||
/**
|
||||
* A registry of runtime properties used exclusively for debugging
|
||||
*
|
||||
* Filament exposes a few properties that can be queried and set, which control certain debugging
|
||||
* features of the engine. These properties can be set at runtime at anytime.
|
||||
*
|
||||
*/
|
||||
class UTILS_PUBLIC DebugRegistry : public FilamentAPI {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Type of a property
|
||||
*/
|
||||
enum Type {
|
||||
BOOL, INT, FLOAT, FLOAT2, FLOAT3, FLOAT4
|
||||
};
|
||||
|
||||
/**
|
||||
* Information about a property
|
||||
*/
|
||||
struct Property {
|
||||
const char* name; //!< property name
|
||||
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
|
||||
* @param name The name of the property to query
|
||||
* @return true if the property exists, false otherwise
|
||||
*/
|
||||
bool hasProperty(const char* name) const noexcept;
|
||||
|
||||
/**
|
||||
* Queries the address of a property's data from its name
|
||||
* @param name Name of the property we want the data address of
|
||||
* @return Address of the data of the \p name property
|
||||
* @{
|
||||
*/
|
||||
void* getPropertyAddress(const char* name) noexcept;
|
||||
|
||||
template<typename T>
|
||||
inline T* getPropertyAddress(const char* name) noexcept {
|
||||
return static_cast<T*>(getPropertyAddress(name));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool getPropertyAddress(const char* name, T** p) noexcept {
|
||||
*p = getPropertyAddress<T>(name);
|
||||
return *p != nullptr;
|
||||
}
|
||||
/** @}*/
|
||||
|
||||
/**
|
||||
* Set the value of a property
|
||||
* @param name Name of the property to set the value of
|
||||
* @param v Value to set
|
||||
* @return true if the operation was successful, false otherwise.
|
||||
* @{
|
||||
*/
|
||||
bool setProperty(const char* name, bool v) noexcept;
|
||||
bool setProperty(const char* name, int v) noexcept;
|
||||
bool setProperty(const char* name, float v) noexcept;
|
||||
bool setProperty(const char* name, math::float2 v) noexcept;
|
||||
bool setProperty(const char* name, math::float3 v) noexcept;
|
||||
bool setProperty(const char* name, math::float4 v) noexcept;
|
||||
/** @}*/
|
||||
|
||||
/**
|
||||
* Get the value of a property
|
||||
* @param name Name of the property to get the value of
|
||||
* @param v A pointer to a variable which will hold the result
|
||||
* @return true if the call was successful and \p v was updated
|
||||
* @{
|
||||
*/
|
||||
bool getProperty(const char* name, bool* v) const noexcept;
|
||||
bool getProperty(const char* name, int* v) const noexcept;
|
||||
bool getProperty(const char* name, float* v) const noexcept;
|
||||
bool getProperty(const char* name, math::float2* v) const noexcept;
|
||||
bool getProperty(const char* name, math::float3* v) const noexcept;
|
||||
bool getProperty(const char* name, math::float4* v) const noexcept;
|
||||
/** @}*/
|
||||
|
||||
};
|
||||
|
||||
|
||||
} // namespace filament
|
||||
|
||||
#endif /* TNT_FILAMENT_DEBUG_H */
|
||||
543
ios/include/filament/Engine.h
Normal file
543
ios/include/filament/Engine.h
Normal file
@@ -0,0 +1,543 @@
|
||||
/*
|
||||
* 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 TNT_FILAMENT_ENGINE_H
|
||||
#define TNT_FILAMENT_ENGINE_H
|
||||
|
||||
#include <backend/Platform.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
namespace utils {
|
||||
class Entity;
|
||||
class EntityManager;
|
||||
class JobSystem;
|
||||
} // namespace utils
|
||||
|
||||
namespace filament {
|
||||
|
||||
class BufferObject;
|
||||
class Camera;
|
||||
class ColorGrading;
|
||||
class DebugRegistry;
|
||||
class Fence;
|
||||
class IndexBuffer;
|
||||
class IndirectLight;
|
||||
class Material;
|
||||
class MaterialInstance;
|
||||
class Renderer;
|
||||
class RenderTarget;
|
||||
class Scene;
|
||||
class Skybox;
|
||||
class Stream;
|
||||
class SwapChain;
|
||||
class Texture;
|
||||
class VertexBuffer;
|
||||
class View;
|
||||
|
||||
class LightManager;
|
||||
class RenderableManager;
|
||||
class TransformManager;
|
||||
|
||||
/**
|
||||
* Engine is filament's main entry-point.
|
||||
*
|
||||
* An Engine instance main function is to keep track of all resources created by the user and
|
||||
* manage the rendering thread as well as the hardware renderer.
|
||||
*
|
||||
* To use filament, an Engine instance must be created first:
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* #include <filament/Engine.h>
|
||||
* using namespace filament;
|
||||
*
|
||||
* Engine* engine = Engine::create();
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* Engine essentially represents (or is associated to) a hardware context
|
||||
* (e.g. an OpenGL ES context).
|
||||
*
|
||||
* Rendering typically happens in an operating system's window (which can be full screen), such
|
||||
* window is managed by a filament.Renderer.
|
||||
*
|
||||
* A typical filament render loop looks like this:
|
||||
*
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* #include <filament/Engine.h>
|
||||
* #include <filament/Renderer.h>
|
||||
* #include <filament/Scene.h>
|
||||
* #include <filament/View.h>
|
||||
* using namespace filament;
|
||||
*
|
||||
* Engine* engine = Engine::create();
|
||||
* SwapChain* swapChain = engine->createSwapChain(nativeWindow);
|
||||
* Renderer* renderer = engine->createRenderer();
|
||||
* Scene* scene = engine->createScene();
|
||||
* View* view = engine->createView();
|
||||
*
|
||||
* view->setScene(scene);
|
||||
*
|
||||
* do {
|
||||
* // typically we wait for VSYNC and user input events
|
||||
* if (renderer->beginFrame(swapChain)) {
|
||||
* renderer->render(view);
|
||||
* renderer->endFrame();
|
||||
* }
|
||||
* } while (!quit);
|
||||
*
|
||||
* engine->destroy(view);
|
||||
* engine->destroy(scene);
|
||||
* engine->destroy(renderer);
|
||||
* engine->destroy(swapChain);
|
||||
* Engine::destroy(&engine); // clears engine*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* Resource Tracking
|
||||
* =================
|
||||
*
|
||||
* Each Engine instance keeps track of all objects created by the user, such as vertex and index
|
||||
* buffers, lights, cameras, etc...
|
||||
* The user is expected to free those resources, however, leaked resources are freed when the
|
||||
* engine instance is destroyed and a warning is emitted in the console.
|
||||
*
|
||||
* Thread safety
|
||||
* =============
|
||||
*
|
||||
* An Engine instance is not thread-safe. The implementation makes no attempt to synchronize
|
||||
* calls to an Engine instance methods.
|
||||
* If multi-threading is needed, synchronization must be external.
|
||||
*
|
||||
* Multi-threading
|
||||
* ===============
|
||||
*
|
||||
* When created, the Engine instance starts a render thread as well as multiple worker threads,
|
||||
* these threads have an elevated priority appropriate for rendering, based on the platform's
|
||||
* best practices. The number of worker threads depends on the platform and is automatically
|
||||
* chosen for best performance.
|
||||
*
|
||||
* On platforms with asymmetric cores (e.g. ARM's Big.Little), Engine makes some educated guesses
|
||||
* as to which cores to use for the render thread and worker threads. For example, it'll try to
|
||||
* keep an OpenGL ES thread on a Big core.
|
||||
*
|
||||
* Swap Chains
|
||||
* ===========
|
||||
*
|
||||
* A swap chain represents an Operating System's *native* renderable surface. Typically it's a window
|
||||
* or a view. Because a SwapChain is initialized from a native object, it is given to filament
|
||||
* as a `void*`, which must be of the proper type for each platform filament is running on.
|
||||
*
|
||||
* @see SwapChain
|
||||
*
|
||||
*
|
||||
* @see Renderer
|
||||
*/
|
||||
class UTILS_PUBLIC Engine {
|
||||
public:
|
||||
using Platform = backend::Platform;
|
||||
using Backend = backend::Backend;
|
||||
|
||||
/**
|
||||
* Creates an instance of Engine
|
||||
*
|
||||
* @param backend Which driver backend to use.
|
||||
*
|
||||
* @param platform A pointer to an object that implements Platform. If this is
|
||||
* provided, then this object is used to create the hardware context
|
||||
* and expose platform features to it.
|
||||
*
|
||||
* If not provided (or nullptr is used), an appropriate Platform
|
||||
* is created automatically.
|
||||
*
|
||||
* All methods of this interface are called from filament's
|
||||
* render thread, which is different from the main thread.
|
||||
*
|
||||
* The lifetime of \p platform must exceed the lifetime of
|
||||
* the Engine object.
|
||||
*
|
||||
* @param sharedGLContext A platform-dependant OpenGL context used as a shared context
|
||||
* when creating filament's internal context.
|
||||
* Setting this parameter will force filament to use the OpenGL
|
||||
* implementation (instead of Vulkan for instance).
|
||||
*
|
||||
*
|
||||
* @return A pointer to the newly created Engine, or nullptr if the Engine couldn't be created.
|
||||
*
|
||||
* nullptr if the GPU driver couldn't be initialized, for instance if it doesn't
|
||||
* support the right version of OpenGL or OpenGL ES.
|
||||
*
|
||||
* @exception utils::PostConditionPanic can be thrown if there isn't enough memory to
|
||||
* allocate the command buffer. If exceptions are disabled, this condition if fatal and
|
||||
* this function will abort.
|
||||
*
|
||||
* \remark
|
||||
* This method is thread-safe.
|
||||
*/
|
||||
static Engine* create(Backend backend = Backend::DEFAULT,
|
||||
Platform* platform = nullptr, void* sharedGLContext = nullptr);
|
||||
|
||||
#if UTILS_HAS_THREADING
|
||||
/**
|
||||
* A callback used with Engine::createAsync() called once the engine is initialized and it is
|
||||
* safe to call Engine::getEngine(token). This callback is invoked from an arbitrary worker
|
||||
* thread. Engine::getEngine() CANNOT be called from that thread, instead it must be called
|
||||
* from the same thread than Engine::createAsync() was called from.
|
||||
*
|
||||
* @param user User provided parameter given in createAsync().
|
||||
*
|
||||
* @param token An opaque token used to call Engine::getEngine().
|
||||
*/
|
||||
using CreateCallback = void(void* user, void* token);
|
||||
|
||||
/**
|
||||
* Creates an instance of Engine asynchronously
|
||||
*
|
||||
* @param callback Callback called once the engine is initialized and it is safe to
|
||||
* call Engine::getEngine.
|
||||
*
|
||||
* @param user A user provided pointer that is given back to callback unmodified.
|
||||
*
|
||||
* @param backend Which driver backend to use.
|
||||
*
|
||||
* @param platform A pointer to an object that implements Platform. If this is
|
||||
* provided, then this object is used to create the hardware context
|
||||
* and expose platform features to it.
|
||||
*
|
||||
* If not provided (or nullptr is used), an appropriate Platform
|
||||
* is created automatically.
|
||||
*
|
||||
* All methods of this interface are called from filament's
|
||||
* render thread, which is different from the main thread.
|
||||
*
|
||||
* The lifetime of \p platform must exceed the lifetime of
|
||||
* the Engine object.
|
||||
*
|
||||
* @param sharedGLContext A platform-dependant OpenGL context used as a shared context
|
||||
* when creating filament's internal context.
|
||||
* Setting this parameter will force filament to use the OpenGL
|
||||
* implementation (instead of Vulkan for instance).
|
||||
*/
|
||||
static void createAsync(CreateCallback callback, void* user,
|
||||
Backend backend = Backend::DEFAULT,
|
||||
Platform* platform = nullptr, void* sharedGLContext = nullptr);
|
||||
|
||||
/**
|
||||
* Retrieve an Engine* from createAsync(). This must be called from the same thread than
|
||||
* Engine::createAsync() was called from.
|
||||
*
|
||||
* @param token An opaque token given in the createAsync() callback function.
|
||||
*
|
||||
* @return A pointer to the newly created Engine, or nullptr if the Engine couldn't be created.
|
||||
*
|
||||
* @exception utils::PostConditionPanic can be thrown if there isn't enough memory to
|
||||
* allocate the command buffer. If exceptions are disabled, this condition if fatal and
|
||||
* this function will abort.
|
||||
*/
|
||||
static Engine* getEngine(void* token);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Destroy the Engine instance and all associated resources.
|
||||
*
|
||||
* Engine.destroy() should be called last and after all other resources have been destroyed,
|
||||
* it ensures all filament resources are freed.
|
||||
*
|
||||
* Destroy performs the following tasks:
|
||||
* 1. Destroy all internal software and hardware resources.
|
||||
* 2. Free all user allocated resources that are not already destroyed and logs a warning.
|
||||
* This indicates a "leak" in the user's code.
|
||||
* 3. Terminate the rendering engine's thread.
|
||||
*
|
||||
* @param engine A pointer to the filament.Engine* to be destroyed.
|
||||
* \p engine is cleared upon return.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* #include <filament/Engine.h>
|
||||
* using namespace filament;
|
||||
*
|
||||
* Engine* engine = Engine::create();
|
||||
* Engine::destroy(&engine); // clears engine*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* \remark
|
||||
* This method is thread-safe.
|
||||
*/
|
||||
static void destroy(Engine** engine);
|
||||
|
||||
/**
|
||||
* Destroy the Engine instance and all associated resources.
|
||||
*
|
||||
* Engine.destroy() should be called last and after all other resources have been destroyed,
|
||||
* it ensures all filament resources are freed.
|
||||
*
|
||||
* Destroy performs the following tasks:
|
||||
* 1. Destroy all internal software and hardware resources.
|
||||
* 2. Free all user allocated resources that are not already destroyed and logs a warning.
|
||||
* This indicates a "leak" in the user's code.
|
||||
* 3. Terminate the rendering engine's thread.
|
||||
*
|
||||
* @param engine A pointer to the filament.Engine to be destroyed.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* #include <filament/Engine.h>
|
||||
* using namespace filament;
|
||||
*
|
||||
* Engine* engine = Engine::create();
|
||||
* Engine::destroy(engine);
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* \remark
|
||||
* This method is thread-safe.
|
||||
*/
|
||||
static void destroy(Engine* engine);
|
||||
|
||||
/**
|
||||
* @return EntityManager used by filament
|
||||
*/
|
||||
utils::EntityManager& getEntityManager() noexcept;
|
||||
|
||||
/**
|
||||
* @return RenderableManager reference
|
||||
*/
|
||||
RenderableManager& getRenderableManager() noexcept;
|
||||
|
||||
/**
|
||||
* @return LightManager reference
|
||||
*/
|
||||
LightManager& getLightManager() noexcept;
|
||||
|
||||
/**
|
||||
* @return TransformManager reference
|
||||
*/
|
||||
TransformManager& getTransformManager() noexcept;
|
||||
|
||||
/**
|
||||
* Helper to enable accurate translations.
|
||||
* If you need this Engine to handle a very large world space, one way to achieve this
|
||||
* automatically is to enable accurate translations in the TransformManager. This helper
|
||||
* provides a convenient way of doing that.
|
||||
* This is typically called once just after creating the Engine.
|
||||
*/
|
||||
void enableAccurateTranslations() noexcept;
|
||||
|
||||
/**
|
||||
* Creates a SwapChain from the given Operating System's native window handle.
|
||||
*
|
||||
* @param nativeWindow An opaque native window handle. e.g.: on Android this is an
|
||||
* `ANativeWindow*`.
|
||||
* @param flags One or more configuration flags as defined in `SwapChain`.
|
||||
*
|
||||
* @return A pointer to the newly created SwapChain or nullptr if it couldn't be created.
|
||||
*
|
||||
* @see Renderer.beginFrame()
|
||||
*/
|
||||
SwapChain* createSwapChain(void* nativeWindow, uint64_t flags = 0) noexcept;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a headless SwapChain.
|
||||
*
|
||||
* @param width Width of the drawing buffer in pixels.
|
||||
* @param height Height of the drawing buffer in pixels.
|
||||
* @param flags One or more configuration flags as defined in `SwapChain`.
|
||||
*
|
||||
* @return A pointer to the newly created SwapChain or nullptr if it couldn't be created.
|
||||
*
|
||||
* @see Renderer.beginFrame()
|
||||
*/
|
||||
SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t flags = 0) noexcept;
|
||||
|
||||
/**
|
||||
* Creates a renderer associated to this engine.
|
||||
*
|
||||
* A Renderer is intended to map to a *window* on screen.
|
||||
*
|
||||
* @return A pointer to the newly created Renderer or nullptr if it couldn't be created.
|
||||
*/
|
||||
Renderer* createRenderer() noexcept;
|
||||
|
||||
/**
|
||||
* Creates a View.
|
||||
*
|
||||
* @return A pointer to the newly created View or nullptr if it couldn't be created.
|
||||
*/
|
||||
View* createView() noexcept;
|
||||
|
||||
/**
|
||||
* Creates a Scene.
|
||||
*
|
||||
* @return A pointer to the newly created Scene or nullptr if it couldn't be created.
|
||||
*/
|
||||
Scene* createScene() noexcept;
|
||||
|
||||
/**
|
||||
* Creates a Camera component.
|
||||
*
|
||||
* @param entity Entity to add the camera component to.
|
||||
* @return A pointer to the newly created Camera or nullptr if it couldn't be created.
|
||||
*/
|
||||
Camera* createCamera(utils::Entity entity) noexcept;
|
||||
|
||||
/**
|
||||
* Returns the Camera component of the given entity.
|
||||
*
|
||||
* @param entity An entity.
|
||||
* @return A pointer to the Camera component for this entity or nullptr if the entity didn't
|
||||
* have a Camera component. The pointer is valid until destroyCameraComponent()
|
||||
* is called or the entity itself is destroyed.
|
||||
*/
|
||||
Camera* getCameraComponent(utils::Entity entity) noexcept;
|
||||
|
||||
/**
|
||||
* Destroys the Camera component associated with the given entity.
|
||||
*
|
||||
* @param entity An entity.
|
||||
*/
|
||||
void destroyCameraComponent(utils::Entity entity) noexcept;
|
||||
|
||||
/**
|
||||
* Creates a Fence.
|
||||
*
|
||||
* @return A pointer to the newly created Fence or nullptr if it couldn't be created.
|
||||
*/
|
||||
Fence* createFence() noexcept;
|
||||
|
||||
bool destroy(const BufferObject* p); //!< Destroys a BufferObject object.
|
||||
bool destroy(const VertexBuffer* p); //!< Destroys an VertexBuffer object.
|
||||
bool destroy(const Fence* p); //!< Destroys a Fence object.
|
||||
bool destroy(const IndexBuffer* p); //!< Destroys an IndexBuffer object.
|
||||
bool destroy(const IndirectLight* p); //!< Destroys an IndirectLight object.
|
||||
|
||||
/**
|
||||
* Destroys a Material object
|
||||
* @param p the material object to destroy
|
||||
* @attention All MaterialInstance of the specified material must be destroyed before
|
||||
* destroying it.
|
||||
* @exception utils::PreConditionPanic is thrown if some MaterialInstances remain.
|
||||
* no-op if exceptions are disabled and some MaterialInstances remain.
|
||||
*/
|
||||
bool destroy(const Material* p);
|
||||
bool destroy(const MaterialInstance* p); //!< Destroys a MaterialInstance object.
|
||||
bool destroy(const Renderer* p); //!< Destroys a Renderer object.
|
||||
bool destroy(const Scene* p); //!< Destroys a Scene object.
|
||||
bool destroy(const Skybox* p); //!< Destroys a SkyBox object.
|
||||
bool destroy(const ColorGrading* p); //!< Destroys a ColorGrading object.
|
||||
bool destroy(const SwapChain* p); //!< Destroys a SwapChain object.
|
||||
bool destroy(const Stream* p); //!< Destroys a Stream object.
|
||||
bool destroy(const Texture* p); //!< Destroys a Texture object.
|
||||
bool destroy(const RenderTarget* p); //!< Destroys a RenderTarget object.
|
||||
bool destroy(const View* p); //!< Destroys a View object.
|
||||
void destroy(utils::Entity e); //!< Destroys all filament-known components from this entity
|
||||
|
||||
/**
|
||||
* Kicks the hardware thread (e.g. the OpenGL, Vulkan or Metal thread) and blocks until
|
||||
* all commands to this point are executed. Note that this doesn't guarantee that the
|
||||
* hardware is actually finished.
|
||||
*
|
||||
* <p>This is typically used right after destroying the <code>SwapChain</code>,
|
||||
* in cases where a guarantee about the <code>SwapChain</code> destruction is needed in a
|
||||
* timely fashion, such as when responding to Android's
|
||||
* <code>android.view.SurfaceHolder.Callback.surfaceDestroyed</code></p>
|
||||
*/
|
||||
void flushAndWait();
|
||||
|
||||
void flush();
|
||||
|
||||
/**
|
||||
* Returns the default Material.
|
||||
*
|
||||
* The default material is 80% white and uses the Material.Shading.LIT shading.
|
||||
*
|
||||
* @return A pointer to the default Material instance (a singleton).
|
||||
*/
|
||||
const Material* getDefaultMaterial() const noexcept;
|
||||
|
||||
/**
|
||||
* Returns the resolved backend.
|
||||
*/
|
||||
Backend getBackend() const noexcept;
|
||||
|
||||
/**
|
||||
* Returns the Platform object that belongs to this Engine.
|
||||
*
|
||||
* When Engine::create is called with no platform argument, Filament creates an appropriate
|
||||
* Platform subclass automatically. The specific subclass created depends on the backend and
|
||||
* OS. For example, when the OpenGL backend is used, the Platform object will be a descendant of
|
||||
* OpenGLPlatform.
|
||||
*
|
||||
* dynamic_cast should be used to cast the returned Platform object into a specific subclass.
|
||||
* Note that RTTI must be available to use dynamic_cast.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Platform* platform = engine->getPlatform();
|
||||
* // static_cast also works, but more dangerous.
|
||||
* SpecificPlatform* specificPlatform = dynamic_cast<SpecificPlatform*>(platform);
|
||||
* specificPlatform->platformSpecificMethod();
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* When a custom Platform is passed to Engine::create, Filament will use it instead, and this
|
||||
* method will return it.
|
||||
*
|
||||
* @return A pointer to the Platform object that was provided to Engine::create, or the
|
||||
* Filament-created one.
|
||||
*/
|
||||
Platform* getPlatform() const noexcept;
|
||||
|
||||
/**
|
||||
* Allocate a small amount of memory directly in the command stream. The allocated memory is
|
||||
* guaranteed to be preserved until the current command buffer is executed
|
||||
*
|
||||
* @param size size to allocate in bytes. This should be small (e.g. < 1 KB)
|
||||
* @param alignment alignment requested
|
||||
* @return a pointer to the allocated buffer or nullptr if no memory was available.
|
||||
*
|
||||
* @note there is no need to destroy this buffer, it will be freed automatically when
|
||||
* the current command buffer is executed.
|
||||
*/
|
||||
void* streamAlloc(size_t size, size_t alignment = alignof(double)) noexcept;
|
||||
|
||||
/**
|
||||
* Invokes one iteration of the render loop, used only on single-threaded platforms.
|
||||
*
|
||||
* This should be called every time the windowing system needs to paint (e.g. at 60 Hz).
|
||||
*/
|
||||
void execute();
|
||||
|
||||
/**
|
||||
* Retrieves the job system that the Engine has ownership over.
|
||||
*
|
||||
* @return JobSystem used by filament
|
||||
*/
|
||||
utils::JobSystem& getJobSystem() noexcept;
|
||||
|
||||
DebugRegistry& getDebugRegistry() noexcept;
|
||||
|
||||
protected:
|
||||
//! \privatesection
|
||||
Engine() noexcept = default;
|
||||
~Engine() = default;
|
||||
|
||||
public:
|
||||
//! \privatesection
|
||||
Engine(Engine const&) = delete;
|
||||
Engine(Engine&&) = delete;
|
||||
Engine& operator=(Engine const&) = delete;
|
||||
Engine& operator=(Engine&&) = delete;
|
||||
};
|
||||
|
||||
} // namespace filament
|
||||
|
||||
#endif // TNT_FILAMENT_ENGINE_H
|
||||
129
ios/include/filament/Exposure.h
Normal file
129
ios/include/filament/Exposure.h
Normal file
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef TNT_FILAMENT_EXPOSURE_H
|
||||
#define TNT_FILAMENT_EXPOSURE_H
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
namespace filament {
|
||||
|
||||
class Camera;
|
||||
|
||||
/**
|
||||
* A series of utilities to compute exposure, exposure value at ISO 100 (EV100),
|
||||
* luminance and illuminance using a physically-based camera model.
|
||||
*/
|
||||
namespace Exposure {
|
||||
|
||||
/**
|
||||
* Returns the exposure value (EV at ISO 100) of the specified camera.
|
||||
*/
|
||||
UTILS_PUBLIC
|
||||
float ev100(const Camera& camera) noexcept;
|
||||
|
||||
/**
|
||||
* Returns the exposure value (EV at ISO 100) of the specified exposure parameters.
|
||||
*/
|
||||
UTILS_PUBLIC
|
||||
float ev100(float aperture, float shutterSpeed, float sensitivity) noexcept;
|
||||
|
||||
/**
|
||||
* Returns the exposure value (EV at ISO 100) for the given average luminance (in @f$ \frac{cd}{m^2} @f$).
|
||||
*/
|
||||
UTILS_PUBLIC
|
||||
float ev100FromLuminance(float luminance) noexcept;
|
||||
|
||||
/**
|
||||
* Returns the exposure value (EV at ISO 100) for the given illuminance (in lux).
|
||||
*/
|
||||
UTILS_PUBLIC
|
||||
float ev100FromIlluminance(float illuminance) noexcept;
|
||||
|
||||
/**
|
||||
* Returns the photometric exposure for the specified camera.
|
||||
*/
|
||||
UTILS_PUBLIC
|
||||
float exposure(const Camera& camera) noexcept;
|
||||
|
||||
/**
|
||||
* Returns the photometric exposure for the specified exposure parameters.
|
||||
* This function is equivalent to calling `exposure(ev100(aperture, shutterSpeed, sensitivity))`
|
||||
* but is slightly faster and offers higher precision.
|
||||
*/
|
||||
UTILS_PUBLIC
|
||||
float exposure(float aperture, float shutterSpeed, float sensitivity) noexcept;
|
||||
|
||||
/**
|
||||
* Returns the photometric exposure for the given EV100.
|
||||
*/
|
||||
UTILS_PUBLIC
|
||||
float exposure(float ev100) noexcept;
|
||||
|
||||
/**
|
||||
* Returns the incident luminance in @f$ \frac{cd}{m^2} @f$ for the specified camera acting as a spot meter.
|
||||
*/
|
||||
UTILS_PUBLIC
|
||||
float luminance(const Camera& camera) noexcept;
|
||||
|
||||
/**
|
||||
* Returns the incident luminance in @f$ \frac{cd}{m^2} @f$ for the specified exposure parameters of
|
||||
* a camera acting as a spot meter.
|
||||
* This function is equivalent to calling `luminance(ev100(aperture, shutterSpeed, sensitivity))`
|
||||
* but is slightly faster and offers higher precision.
|
||||
*/
|
||||
UTILS_PUBLIC
|
||||
float luminance(float aperture, float shutterSpeed, float sensitivity) noexcept;
|
||||
|
||||
/**
|
||||
* Converts the specified EV100 to luminance in @f$ \frac{cd}{m^2} @f$.
|
||||
* EV100 is not a measure of luminance, but an EV100 can be used to denote a
|
||||
* luminance for which a camera would use said EV100 to obtain the nominally
|
||||
* correct exposure
|
||||
*/
|
||||
UTILS_PUBLIC
|
||||
float luminance(float ev100) noexcept;
|
||||
|
||||
/**
|
||||
* Returns the illuminance in lux for the specified camera acting as an incident light meter.
|
||||
*/
|
||||
UTILS_PUBLIC
|
||||
float illuminance(const Camera& camera) noexcept;
|
||||
|
||||
/**
|
||||
* Returns the illuminance in lux for the specified exposure parameters of
|
||||
* a camera acting as an incident light meter.
|
||||
* This function is equivalent to calling `illuminance(ev100(aperture, shutterSpeed, sensitivity))`
|
||||
* but is slightly faster and offers higher precision.
|
||||
*/
|
||||
UTILS_PUBLIC
|
||||
float illuminance(float aperture, float shutterSpeed, float sensitivity) noexcept;
|
||||
|
||||
/**
|
||||
* Converts the specified EV100 to illuminance in lux.
|
||||
* EV100 is not a measure of illuminance, but an EV100 can be used to denote an
|
||||
* illuminance for which a camera would use said EV100 to obtain the nominally
|
||||
* correct exposure.
|
||||
*/
|
||||
UTILS_PUBLIC
|
||||
float illuminance(float ev100) noexcept;
|
||||
|
||||
} // namespace exposure
|
||||
} // namespace filament
|
||||
|
||||
#endif // TNT_FILAMENT_EXPOSURE_H
|
||||
86
ios/include/filament/Fence.h
Normal file
86
ios/include/filament/Fence.h
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef TNT_FILAMENT_FENCE_H
|
||||
#define TNT_FILAMENT_FENCE_H
|
||||
|
||||
#include <filament/FilamentAPI.h>
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
namespace filament {
|
||||
|
||||
/**
|
||||
* Fence is used to synchronize rendering operations together, with the CPU or with compute.
|
||||
*
|
||||
* \note
|
||||
* Currently Fence only provide client-side synchronization.
|
||||
*
|
||||
*/
|
||||
class UTILS_PUBLIC Fence : public FilamentAPI {
|
||||
public:
|
||||
//! Special \p timeout value to disable wait()'s timeout.
|
||||
static constexpr uint64_t FENCE_WAIT_FOR_EVER = backend::FENCE_WAIT_FOR_EVER;
|
||||
|
||||
//! Error codes for Fence::wait()
|
||||
using FenceStatus = backend::FenceStatus;
|
||||
|
||||
/** Mode controls the behavior of the command stream when calling wait()
|
||||
*
|
||||
* @attention
|
||||
* It would be unwise to call `wait(..., Mode::DONT_FLUSH)` from the same thread
|
||||
* the Fence was created, as it would most certainly create a dead-lock.
|
||||
*/
|
||||
enum class Mode : uint8_t {
|
||||
FLUSH, //!< The command stream is flushed
|
||||
DONT_FLUSH //!< The command stream is not flushed
|
||||
};
|
||||
|
||||
/**
|
||||
* Client-side wait on the Fence.
|
||||
*
|
||||
* Blocks the current thread until the Fence signals.
|
||||
*
|
||||
* @param mode Whether the command stream is flushed before waiting or not.
|
||||
* @param timeout Wait time out. Using a \p timeout of 0 is a way to query the state of the fence.
|
||||
* A \p timeout value of FENCE_WAIT_FOR_EVER is used to disable the timeout.
|
||||
* @return FenceStatus::CONDITION_SATISFIED on success,
|
||||
* FenceStatus::TIMEOUT_EXPIRED if the time out expired or
|
||||
* FenceStatus::ERROR in other cases.
|
||||
* @see #Mode
|
||||
*/
|
||||
FenceStatus wait(Mode mode = Mode::FLUSH, uint64_t timeout = FENCE_WAIT_FOR_EVER);
|
||||
|
||||
/**
|
||||
* Client-side wait on a Fence and destroy the Fence.
|
||||
*
|
||||
* @param fence Fence object to wait on.
|
||||
*
|
||||
* @param mode Whether the command stream is flushed before waiting or not.
|
||||
*
|
||||
* @return FenceStatus::CONDITION_SATISFIED on success,
|
||||
* FenceStatus::ERROR otherwise.
|
||||
*/
|
||||
static FenceStatus waitAndDestroy(Fence* fence, Mode mode = Mode::FLUSH);
|
||||
};
|
||||
|
||||
} // namespace filament
|
||||
|
||||
#endif // TNT_FILAMENT_FENCE_H
|
||||
91
ios/include/filament/FilamentAPI.h
Normal file
91
ios/include/filament/FilamentAPI.h
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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 TNT_FILAMENT_FILAMENT_API_H
|
||||
#define TNT_FILAMENT_FILAMENT_API_H
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
namespace filament {
|
||||
|
||||
/**
|
||||
* \privatesection
|
||||
* FilamentAPI is used to define an API in filament.
|
||||
* It ensures the class defining the API can't be created, destroyed
|
||||
* or copied by the caller.
|
||||
*/
|
||||
class UTILS_PUBLIC FilamentAPI {
|
||||
protected:
|
||||
// disallow creation on the stack
|
||||
FilamentAPI() noexcept = default;
|
||||
~FilamentAPI() = default;
|
||||
|
||||
public:
|
||||
// disallow copy and assignment
|
||||
FilamentAPI(FilamentAPI const&) = delete;
|
||||
FilamentAPI(FilamentAPI&&) = delete;
|
||||
FilamentAPI& operator=(FilamentAPI const&) = delete;
|
||||
FilamentAPI& operator=(FilamentAPI&&) = delete;
|
||||
|
||||
// allow placement-new allocation, don't use "noexcept", to avoid compiler null check
|
||||
static void *operator new (size_t, void* p) { return p; }
|
||||
|
||||
// prevent heap allocation
|
||||
static void *operator new (size_t) = delete;
|
||||
static void *operator new[] (size_t) = delete;
|
||||
static void operator delete (void*) = delete;
|
||||
static void operator delete[](void*) = delete;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \privatesection
|
||||
* BuilderBase is used to hide the implementation details of builders and ensure a higher
|
||||
* level of backward binary compatibility.
|
||||
* The actual implementation is in src/FilamentAPI-impl.h"
|
||||
*/
|
||||
template <typename T>
|
||||
class BuilderBase {
|
||||
public:
|
||||
// none of these methods must be implemented inline because it's important that their
|
||||
// implementation be hidden from the public headers.
|
||||
template<typename ... ARGS>
|
||||
explicit BuilderBase(ARGS&& ...) noexcept;
|
||||
BuilderBase() noexcept;
|
||||
~BuilderBase() noexcept;
|
||||
BuilderBase(BuilderBase const& rhs) noexcept;
|
||||
BuilderBase& operator = (BuilderBase const& rhs) noexcept;
|
||||
|
||||
// move ctor and copy operator can be implemented inline and don't need to be exported
|
||||
BuilderBase(BuilderBase&& rhs) noexcept : mImpl(rhs.mImpl) { rhs.mImpl = nullptr; }
|
||||
BuilderBase& operator = (BuilderBase&& rhs) noexcept {
|
||||
auto temp = mImpl;
|
||||
mImpl = rhs.mImpl;
|
||||
rhs.mImpl = temp;
|
||||
return *this;
|
||||
}
|
||||
|
||||
protected:
|
||||
T* mImpl = nullptr;
|
||||
inline T* operator->() noexcept { return mImpl; }
|
||||
inline T const* operator->() const noexcept { return mImpl; }
|
||||
};
|
||||
|
||||
} // namespace filament
|
||||
|
||||
#endif // TNT_FILAMENT_FILAMENT_API_H
|
||||
144
ios/include/filament/Frustum.h
Normal file
144
ios/include/filament/Frustum.h
Normal file
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef TNT_FILAMENT_FRUSTUM_H
|
||||
#define TNT_FILAMENT_FRUSTUM_H
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <math/mat4.h>
|
||||
#include <math/vec3.h>
|
||||
|
||||
#include <utils/unwindows.h> // Because we define NEAR and FAR in the Plane enum.
|
||||
|
||||
namespace filament {
|
||||
|
||||
class Box;
|
||||
class Culler;
|
||||
|
||||
/**
|
||||
* A frustum defined by six planes
|
||||
*/
|
||||
class UTILS_PUBLIC Frustum {
|
||||
public:
|
||||
enum class Plane : uint8_t {
|
||||
LEFT,
|
||||
RIGHT,
|
||||
BOTTOM,
|
||||
TOP,
|
||||
FAR,
|
||||
NEAR
|
||||
};
|
||||
|
||||
Frustum() = default;
|
||||
Frustum(const Frustum& rhs) = default;
|
||||
Frustum(Frustum&& rhs) noexcept = default;
|
||||
Frustum& operator=(const Frustum& rhs) = default;
|
||||
Frustum& operator=(Frustum&& rhs) noexcept = default;
|
||||
|
||||
/**
|
||||
* Creates a frustum from a projection matrix (usually the projection * view matrix)
|
||||
* @param pv a 4x4 projection matrix
|
||||
*/
|
||||
explicit Frustum(const math::mat4f& pv);
|
||||
|
||||
/**
|
||||
* Creates a frustum from 8 corner coordinates.
|
||||
* @param corners the corners of the frustum
|
||||
*
|
||||
* The corners should be specified in this order:
|
||||
* 0. far bottom left
|
||||
* 1. far bottom right
|
||||
* 2. far top left
|
||||
* 3. far top right
|
||||
* 4. near bottom left
|
||||
* 5. near bottom right
|
||||
* 6. near top left
|
||||
* 7. near top right
|
||||
*
|
||||
* 2----3
|
||||
* /| /|
|
||||
* 6----7 |
|
||||
* | 0--|-1 far
|
||||
* |/ |/ /
|
||||
* 4----5 near
|
||||
*
|
||||
*/
|
||||
explicit Frustum(const math::float3 corners[8]);
|
||||
|
||||
/**
|
||||
* Sets the frustum from the given projection matrix
|
||||
* @param pv a 4x4 projection matrix
|
||||
*/
|
||||
void setProjection(const math::mat4f& pv);
|
||||
|
||||
/**
|
||||
* Returns the plane equation parameters with normalized normals
|
||||
* @param plane Identifier of the plane to retrieve the equation of
|
||||
* @return A plane equation encoded a float4 R such as R.x*x + R.y*y + R.z*z + R.w = 0
|
||||
*/
|
||||
math::float4 getNormalizedPlane(Plane plane) const noexcept;
|
||||
|
||||
/**
|
||||
* Returns a copy of all six frustum planes in left, right, bottom, top, far, near order
|
||||
* @param planes six plane equations encoded as in getNormalizedPlane() in
|
||||
* left, right, bottom, top, far, near order
|
||||
*/
|
||||
void getNormalizedPlanes(math::float4 planes[6]) const noexcept;
|
||||
|
||||
/**
|
||||
* Returns all six frustum planes in left, right, bottom, top, far, near order
|
||||
* @return six plane equations encoded as in getNormalizedPlane() in
|
||||
* left, right, bottom, top, far, near order
|
||||
*/
|
||||
math::float4 const* getNormalizedPlanes() const noexcept { return mPlanes; }
|
||||
|
||||
/**
|
||||
* Returns whether a box intersects the frustum (i.e. is visible)
|
||||
* @param box The box to test against the frustum
|
||||
* @return true if the box may intersects the frustum, false otherwise. In some situations
|
||||
* a box that doesn't intersect the frustum might be reported as though it does. However,
|
||||
* a box that does intersect the frustum is always reported correctly (true).
|
||||
*/
|
||||
bool intersects(const Box& box) const noexcept;
|
||||
|
||||
/**
|
||||
* Returns whether a sphere intersects the frustum (i.e. is visible)
|
||||
* @param sphere A sphere encoded as a center + radius.
|
||||
* @return true if the sphere may intersects the frustum, false otherwise. In some situations
|
||||
* a sphere that doesn't intersect the frustum might be reported as though it does. However,
|
||||
* a sphere that does intersect the frustum is always reported correctly (true).
|
||||
*/
|
||||
bool intersects(const math::float4& sphere) const noexcept;
|
||||
|
||||
/**
|
||||
* Returns whether the frustum contains a given point.
|
||||
* @param p the point to test
|
||||
* @return the maximum signed distance to the frustum. Negative if p is inside.
|
||||
*/
|
||||
float contains(math::float3 p) const noexcept;
|
||||
|
||||
private:
|
||||
friend class Culler;
|
||||
math::float4 mPlanes[6];
|
||||
};
|
||||
|
||||
|
||||
} // namespace filament
|
||||
|
||||
#endif // TNT_FILAMENT_FRUSTUM_H
|
||||
125
ios/include/filament/IndexBuffer.h
Normal file
125
ios/include/filament/IndexBuffer.h
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef TNT_FILAMENT_INDEXBUFFER_H
|
||||
#define TNT_FILAMENT_INDEXBUFFER_H
|
||||
|
||||
#include <filament/FilamentAPI.h>
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
#include <backend/BufferDescriptor.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
namespace filament {
|
||||
|
||||
class FIndexBuffer;
|
||||
|
||||
class Engine;
|
||||
|
||||
/**
|
||||
* A buffer containing vertex indices into a VertexBuffer. Indices can be 16 or 32 bit.
|
||||
* The buffer itself is a GPU resource, therefore mutating the data can be relatively slow.
|
||||
* Typically these buffers are constant.
|
||||
*
|
||||
* It is possible, and even encouraged, to use a single index buffer for several Renderables.
|
||||
*
|
||||
* @see VertexBuffer, RenderableManager
|
||||
*/
|
||||
class UTILS_PUBLIC IndexBuffer : public FilamentAPI {
|
||||
struct BuilderDetails;
|
||||
|
||||
public:
|
||||
using BufferDescriptor = backend::BufferDescriptor;
|
||||
|
||||
/**
|
||||
* Type of the index buffer
|
||||
*/
|
||||
enum class IndexType : uint8_t {
|
||||
USHORT = uint8_t(backend::ElementType::USHORT), //!< 16-bit indices
|
||||
UINT = uint8_t(backend::ElementType::UINT), //!< 32-bit indices
|
||||
};
|
||||
|
||||
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 index buffer in elements.
|
||||
* @param indexCount Number of indices the IndexBuffer can hold.
|
||||
* @return A reference to this Builder for chaining calls.
|
||||
*/
|
||||
Builder& indexCount(uint32_t indexCount) noexcept;
|
||||
|
||||
/**
|
||||
* Type of the index buffer, 16-bit or 32-bit.
|
||||
* @param indexType Type of indices stored in the IndexBuffer.
|
||||
* @return A reference to this Builder for chaining calls.
|
||||
*/
|
||||
Builder& bufferType(IndexType indexType) noexcept;
|
||||
|
||||
/**
|
||||
* Creates the IndexBuffer object and returns a pointer to it. After creation, the index
|
||||
* buffer is uninitialized. Use IndexBuffer::setBuffer() to initialize the IndexBuffer.
|
||||
*
|
||||
* @param engine Reference to the filament::Engine to associate this IndexBuffer 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.
|
||||
*
|
||||
* @see IndexBuffer::setBuffer
|
||||
*/
|
||||
IndexBuffer* build(Engine& engine);
|
||||
private:
|
||||
friend class FIndexBuffer;
|
||||
};
|
||||
|
||||
/**
|
||||
* Asynchronously copy-initializes a region of this IndexBuffer from the data provided.
|
||||
*
|
||||
* @param engine Reference to the filament::Engine to associate this IndexBuffer with.
|
||||
* @param buffer A BufferDescriptor representing the data used to initialize the IndexBuffer.
|
||||
* BufferDescriptor points to raw, untyped data that will be interpreted as
|
||||
* either 16-bit or 32-bits indices based on the Type of this IndexBuffer.
|
||||
* @param byteOffset Offset in *bytes* into the IndexBuffer
|
||||
*/
|
||||
void setBuffer(Engine& engine, BufferDescriptor&& buffer, uint32_t byteOffset = 0);
|
||||
|
||||
/**
|
||||
* Returns the size of this IndexBuffer in elements.
|
||||
* @return The number of indices the IndexBuffer holds.
|
||||
*/
|
||||
size_t getIndexCount() const noexcept;
|
||||
};
|
||||
|
||||
} // namespace filament
|
||||
|
||||
#endif // TNT_FILAMENT_INDEXBUFFER_H
|
||||
349
ios/include/filament/IndirectLight.h
Normal file
349
ios/include/filament/IndirectLight.h
Normal file
@@ -0,0 +1,349 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef TNT_FILAMENT_INDIRECT_LIGHT_H
|
||||
#define TNT_FILAMENT_INDIRECT_LIGHT_H
|
||||
|
||||
#include <filament/FilamentAPI.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <math/mathfwd.h>
|
||||
|
||||
namespace filament {
|
||||
|
||||
class Engine;
|
||||
class Texture;
|
||||
|
||||
class FIndirectLight;
|
||||
|
||||
/**
|
||||
* IndirectLight is used to simulate environment lighting, a form of global illumination.
|
||||
*
|
||||
* Environment lighting has a two components:
|
||||
* 1. irradiance
|
||||
* 2. reflections (specular component)
|
||||
*
|
||||
* Environments are usually captured as high-resolution HDR equirectangular images and processed
|
||||
* by the **cmgen** tool to generate the data needed by IndirectLight.
|
||||
*
|
||||
* @note
|
||||
* Currently IndirectLight is intended to be used for "distant probes", that is, to represent
|
||||
* global illumination from a distant (i.e. at infinity) environment, such as the sky or distant
|
||||
* mountains. Only a single IndirectLight can be used in a Scene. This limitation will be lifted
|
||||
* in the future.
|
||||
*
|
||||
* Creation and destruction
|
||||
* ========================
|
||||
*
|
||||
* An IndirectLight object is created using the IndirectLight::Builder and destroyed by calling
|
||||
* Engine::destroy(const IndirectLight*).
|
||||
*
|
||||
* ~~~~~~~~~~~{.cpp}
|
||||
* filament::Engine* engine = filament::Engine::create();
|
||||
*
|
||||
* filament::IndirectLight* environment = filament::IndirectLight::Builder()
|
||||
* .reflections(cubemap)
|
||||
* .build(*engine);
|
||||
*
|
||||
* engine->destroy(environment);
|
||||
* ~~~~~~~~~~~
|
||||
*
|
||||
*
|
||||
* Irradiance
|
||||
* ==========
|
||||
*
|
||||
* The irradiance represents the light that comes from the environment and shines an
|
||||
* object's surface.
|
||||
*
|
||||
* The irradiance is calculated automatically from the Reflections (see below), and generally
|
||||
* doesn't need to be provided explicitly. However, it can be provided separately from the
|
||||
* Reflections as
|
||||
* [spherical harmonics](https://en.wikipedia.org/wiki/Spherical_harmonics) (SH) of 1, 2 or
|
||||
* 3 bands, respectively 1, 4 or 9 coefficients.
|
||||
*
|
||||
* @note
|
||||
* Use the **cmgen** tool to generate the `SH` for a given environment.
|
||||
*
|
||||
* Reflections
|
||||
* ===========
|
||||
*
|
||||
* The reflections on object surfaces (specular component) is calculated from a specially
|
||||
* filtered cubemap pyramid generated by the **cmgen** tool.
|
||||
*
|
||||
*
|
||||
* @see Scene, Light, Texture, Skybox
|
||||
*/
|
||||
class UTILS_PUBLIC IndirectLight : public FilamentAPI {
|
||||
struct BuilderDetails;
|
||||
|
||||
public:
|
||||
|
||||
//! Use Builder to construct an IndirectLight object instance
|
||||
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;
|
||||
|
||||
/**
|
||||
* Set the reflections cubemap mipmap chain.
|
||||
*
|
||||
* @param cubemap A mip-mapped cubemap generated by **cmgen**. Each cubemap level
|
||||
* encodes a the irradiance for a roughness level.
|
||||
*
|
||||
* @return This Builder, for chaining calls.
|
||||
*
|
||||
*/
|
||||
Builder& reflections(Texture const* cubemap) noexcept;
|
||||
|
||||
/**
|
||||
* Sets the irradiance as Spherical Harmonics.
|
||||
*
|
||||
* The irradiance must be pre-convolved by \f$ \langle n \cdot l \rangle \f$ and
|
||||
* pre-multiplied by the Lambertian diffuse BRDF \f$ \frac{1}{\pi} \f$ and
|
||||
* specified as Spherical Harmonics coefficients.
|
||||
*
|
||||
* Additionally, these Spherical Harmonics coefficients must be pre-scaled by the
|
||||
* reconstruction factors \f$ A_{l}^{m} \f$ below.
|
||||
*
|
||||
* The final coefficients can be generated using the `cmgen` tool.
|
||||
*
|
||||
* The index in the \p sh array is given by:
|
||||
*
|
||||
* `index(l, m) = l * (l + 1) + m`
|
||||
*
|
||||
* \f$ sh[index(l,m)] = L_{l}^{m} \frac{1}{\pi} A_{l}^{m} \hat{C_{l}} \f$
|
||||
*
|
||||
* index | l | m | \f$ A_{l}^{m} \f$ | \f$ \hat{C_{l}} \f$ | \f$ \frac{1}{\pi} A_{l}^{m}\hat{C_{l}} \f$ |
|
||||
* :-----:|:---:|:---:|:------------------:|:---------------------:|:--------------------------------------------:
|
||||
* 0 | 0 | 0 | 0.282095 | 3.1415926 | 0.282095
|
||||
* 1 | 1 | -1 | -0.488602 | 2.0943951 | -0.325735
|
||||
* 2 | ^ | 0 | 0.488602 | ^ | 0.325735
|
||||
* 3 | ^ | 1 | -0.488602 | ^ | -0.325735
|
||||
* 4 | 2 | -2 | 1.092548 | 0.785398 | 0.273137
|
||||
* 5 | ^ | -1 | -1.092548 | ^ | -0.273137
|
||||
* 6 | ^ | 0 | 0.315392 | ^ | 0.078848
|
||||
* 7 | ^ | 1 | -1.092548 | ^ | -0.273137
|
||||
* 8 | ^ | 2 | 0.546274 | ^ | 0.136569
|
||||
*
|
||||
*
|
||||
* Only 1, 2 or 3 bands are allowed.
|
||||
*
|
||||
* @param bands Number of spherical harmonics bands. Must be 1, 2 or 3.
|
||||
* @param sh Array containing the spherical harmonics coefficients.
|
||||
* The size of the array must be \f$ bands^{2} \f$.
|
||||
* (i.e. 1, 4 or 9 coefficients respectively).
|
||||
*
|
||||
* @return This Builder, for chaining calls.
|
||||
*
|
||||
* @note
|
||||
* Because the coefficients are pre-scaled, `sh[0]` is the environment's
|
||||
* average irradiance.
|
||||
*/
|
||||
Builder& irradiance(uint8_t bands, math::float3 const* sh) noexcept;
|
||||
|
||||
/**
|
||||
* Sets the irradiance from the radiance expressed as Spherical Harmonics.
|
||||
*
|
||||
* The radiance must be specified as Spherical Harmonics coefficients \f$ L_{l}^{m} \f$
|
||||
*
|
||||
* The index in the \p sh array is given by:
|
||||
*
|
||||
* `index(l, m) = l * (l + 1) + m`
|
||||
*
|
||||
* \f$ sh[index(l,m)] = L_{l}^{m} \f$
|
||||
*
|
||||
* index | l | m
|
||||
* :-----:|:---:|:---:
|
||||
* 0 | 0 | 0
|
||||
* 1 | 1 | -1
|
||||
* 2 | ^ | 0
|
||||
* 3 | ^ | 1
|
||||
* 4 | 2 | -2
|
||||
* 5 | ^ | -1
|
||||
* 6 | ^ | 0
|
||||
* 7 | ^ | 1
|
||||
* 8 | ^ | 2
|
||||
*
|
||||
* @param bands Number of spherical harmonics bands. Must be 1, 2 or 3.
|
||||
* @param sh Array containing the spherical harmonics coefficients.
|
||||
* The size of the array must be \f$ bands^{2} \f$.
|
||||
* (i.e. 1, 4 or 9 coefficients respectively).
|
||||
*
|
||||
* @return This Builder, for chaining calls.
|
||||
*/
|
||||
Builder& radiance(uint8_t bands, math::float3 const* sh) noexcept;
|
||||
|
||||
/**
|
||||
* Sets the irradiance as a cubemap.
|
||||
*
|
||||
* The irradiance can alternatively be specified as a cubemap instead of Spherical
|
||||
* Harmonics coefficients. It may or may not be more efficient, depending on your
|
||||
* hardware (essentially, it's trading ALU for bandwidth).
|
||||
*
|
||||
* @param cubemap Cubemap representing the Irradiance pre-convolved by
|
||||
* \f$ \langle n \cdot l \rangle \f$.
|
||||
*
|
||||
* @return This Builder, for chaining calls.
|
||||
*
|
||||
* @note
|
||||
* This irradiance cubemap can be generated with the **cmgen** tool.
|
||||
*
|
||||
* @see irradiance(uint8_t bands, math::float3 const* sh)
|
||||
*/
|
||||
Builder& irradiance(Texture const* cubemap) noexcept;
|
||||
|
||||
/**
|
||||
* (optional) Environment intensity.
|
||||
*
|
||||
* Because the environment is encoded usually relative to some reference, the
|
||||
* range can be adjusted with this method.
|
||||
*
|
||||
* @param envIntensity Scale factor applied to the environment and irradiance such that
|
||||
* the result is in lux, or lumen/m^2 (default = 30000)
|
||||
*
|
||||
* @return This Builder, for chaining calls.
|
||||
*/
|
||||
Builder& intensity(float envIntensity) noexcept;
|
||||
|
||||
/**
|
||||
* Specifies the rigid-body transformation to apply to the IBL.
|
||||
*
|
||||
* @param rotation 3x3 rotation matrix. Must be a rigid-body transform.
|
||||
*
|
||||
* @return This Builder, for chaining calls.
|
||||
*/
|
||||
Builder& rotation(math::mat3f const& rotation) noexcept;
|
||||
|
||||
/**
|
||||
* Creates the IndirectLight object and returns a pointer to it.
|
||||
*
|
||||
* @param engine Reference to the filament::Engine to associate this IndirectLight 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.
|
||||
*/
|
||||
IndirectLight* build(Engine& engine);
|
||||
|
||||
private:
|
||||
friend class FIndirectLight;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the environment's intensity.
|
||||
*
|
||||
* Because the environment is encoded usually relative to some reference, the
|
||||
* range can be adjusted with this method.
|
||||
*
|
||||
* @param intensity Scale factor applied to the environment and irradiance such that
|
||||
* the result is in lux, or <i>lumen/m^2(default = 30000)
|
||||
*/
|
||||
void setIntensity(float intensity) noexcept;
|
||||
|
||||
/**
|
||||
* Returns the environment's intensity in <i>lux</i>, or <i>lumen/m^2</i>.
|
||||
*/
|
||||
float getIntensity() const noexcept;
|
||||
|
||||
/**
|
||||
* Sets the rigid-body transformation to apply to the IBL.
|
||||
*
|
||||
* @param rotation 3x3 rotation matrix. Must be a rigid-body transform.
|
||||
*/
|
||||
void setRotation(math::mat3f const& rotation) noexcept;
|
||||
|
||||
/**
|
||||
* Returns the rigid-body transformation applied to the IBL.
|
||||
*/
|
||||
const math::mat3f& getRotation() const noexcept;
|
||||
|
||||
/**
|
||||
* Returns the associated reflection map, or null if it does not exist.
|
||||
*/
|
||||
Texture const* getReflectionsTexture() const noexcept;
|
||||
|
||||
/**
|
||||
* Returns the associated irradiance map, or null if it does not exist.
|
||||
*/
|
||||
Texture const* getIrradianceTexture() const noexcept;
|
||||
|
||||
/**
|
||||
* Helper to estimate the direction of the dominant light in the environment represented by
|
||||
* spherical harmonics.
|
||||
*
|
||||
* This assumes that there is only a single dominant light (such as the sun in outdoors
|
||||
* environments), if it's not the case the direction returned will be an average of the
|
||||
* various lights based on their intensity.
|
||||
*
|
||||
* If there are no clear dominant light, as is often the case with low dynamic range (LDR)
|
||||
* environments, this method may return a wrong or unexpected direction.
|
||||
*
|
||||
* The dominant light direction can be used to set a directional light's direction,
|
||||
* for instance to produce shadows that match the environment.
|
||||
*
|
||||
* @param sh 3-band spherical harmonics
|
||||
*
|
||||
* @return A unit vector representing the direction of the dominant light
|
||||
*
|
||||
* @see LightManager::Builder::direction()
|
||||
* @see getColorEstimate()
|
||||
*/
|
||||
static math::float3 getDirectionEstimate(const math::float3 sh[9]) noexcept;
|
||||
|
||||
/**
|
||||
* Helper to estimate the color and relative intensity of the environment represented by
|
||||
* spherical harmonics in a given direction.
|
||||
*
|
||||
* This can be used to set the color and intensity of a directional light. In this case
|
||||
* make sure to multiply this relative intensity by the the intensity of this indirect light.
|
||||
*
|
||||
* @param sh 3-band spherical harmonics
|
||||
* @param direction a unit vector representing the direction of the light to estimate the
|
||||
* color of. Typically this the value returned by getDirectionEstimate().
|
||||
*
|
||||
* @return A vector of 4 floats where the first 3 components represent the linear color and
|
||||
* the 4th component represents the intensity of the dominant light
|
||||
*
|
||||
* @see LightManager::Builder::color()
|
||||
* @see LightManager::Builder::intensity()
|
||||
* @see getDirectionEstimate, getIntensity, setIntensity
|
||||
*/
|
||||
static math::float4 getColorEstimate(const math::float3 sh[9], math::float3 direction) noexcept;
|
||||
|
||||
|
||||
/** @deprecated use static versions instead */
|
||||
UTILS_DEPRECATED
|
||||
math::float3 getDirectionEstimate() const noexcept;
|
||||
|
||||
/** @deprecated use static versions instead */
|
||||
UTILS_DEPRECATED
|
||||
math::float4 getColorEstimate(math::float3 direction) const noexcept;
|
||||
};
|
||||
|
||||
} // namespace filament
|
||||
|
||||
#endif // TNT_FILAMENT_INDIRECT_LIGHT_H
|
||||
938
ios/include/filament/LightManager.h
Normal file
938
ios/include/filament/LightManager.h
Normal file
@@ -0,0 +1,938 @@
|
||||
/*
|
||||
* 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_FILAMENT_LIGHTMANAGER_H
|
||||
#define TNT_FILAMENT_LIGHTMANAGER_H
|
||||
|
||||
#include <filament/FilamentAPI.h>
|
||||
#include <filament/Color.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/Entity.h>
|
||||
#include <utils/EntityInstance.h>
|
||||
|
||||
#include <math/mathfwd.h>
|
||||
|
||||
namespace utils {
|
||||
class Entity;
|
||||
} // namespace utils
|
||||
|
||||
namespace filament {
|
||||
|
||||
class Engine;
|
||||
class FEngine;
|
||||
class FLightManager;
|
||||
|
||||
/**
|
||||
* LightManager allows to create a light source in the scene, such as a sun or street lights.
|
||||
*
|
||||
* At least one light must be added to a scene in order to see anything
|
||||
* (unless the Material.Shading.UNLIT is used).
|
||||
*
|
||||
*
|
||||
* Creation and destruction
|
||||
* ========================
|
||||
*
|
||||
* A Light component is created using the LightManager::Builder and destroyed by calling
|
||||
* LightManager::destroy(utils::Entity).
|
||||
*
|
||||
* ~~~~~~~~~~~{.cpp}
|
||||
* filament::Engine* engine = filament::Engine::create();
|
||||
* utils::Entity sun = utils::EntityManager.get().create();
|
||||
*
|
||||
* filament::LightManager::Builder(Type::SUN)
|
||||
* .castShadows(true)
|
||||
* .build(*engine, sun);
|
||||
*
|
||||
* engine->getLightManager().destroy(sun);
|
||||
* ~~~~~~~~~~~
|
||||
*
|
||||
*
|
||||
* Light types
|
||||
* ===========
|
||||
*
|
||||
* Lights come in three flavors:
|
||||
* - directional lights
|
||||
* - point lights
|
||||
* - spot lights
|
||||
*
|
||||
*
|
||||
* Directional lights
|
||||
* ------------------
|
||||
*
|
||||
* Directional lights have a direction, but don't have a position. All light rays are
|
||||
* parallel and come from infinitely far away and from everywhere. Typically a directional light
|
||||
* is used to simulate the sun.
|
||||
*
|
||||
* Directional lights and spot lights are able to cast shadows.
|
||||
*
|
||||
* To create a directional light use Type.DIRECTIONAL or Type.SUN, both are similar, but the later
|
||||
* also draws a sun's disk in the sky and its reflection on glossy objects.
|
||||
*
|
||||
* @warning Currently, only a single directional light is supported. If several directional lights
|
||||
* are added to the scene, the dominant one will be used.
|
||||
*
|
||||
* @see Builder.direction(), Builder.sunAngularRadius()
|
||||
*
|
||||
* Point lights
|
||||
* ------------
|
||||
*
|
||||
* Unlike directional lights, point lights have a position but emit light in all directions.
|
||||
* The intensity of the light diminishes with the inverse square of the distance to the light.
|
||||
* Builder.falloff() controls distance beyond which the light has no more influence.
|
||||
*
|
||||
* A scene can have multiple point lights.
|
||||
*
|
||||
* @see Builder.position(), Builder.falloff()
|
||||
*
|
||||
* Spot lights
|
||||
* -----------
|
||||
*
|
||||
* Spot lights are similar to point lights but the light it emits is limited to a cone defined by
|
||||
* Builder.spotLightCone() and the light's direction.
|
||||
*
|
||||
* A spot light is therefore defined by a position, a direction and inner and outer cones. The
|
||||
* spot light's influence is limited to inside the outer cone. The inner cone defines the light's
|
||||
* falloff attenuation.
|
||||
*
|
||||
* A physically correct spot light is a little difficult to use because changing the outer angle
|
||||
* of the cone changes the illumination levels, as the same amount of light is spread over a
|
||||
* changing volume. The coupling of illumination and the outer cone means that an artist cannot
|
||||
* tweak the influence cone of a spot light without also changing the perceived illumination.
|
||||
* It therefore makes sense to provide artists with a parameter to disable this coupling. This
|
||||
* is the difference between Type.FOCUSED_SPOT and Type.SPOT.
|
||||
*
|
||||
* @see Builder.position(), Builder.direction(), Builder.falloff(), Builder.spotLightCone()
|
||||
*
|
||||
* Performance considerations
|
||||
* ==========================
|
||||
*
|
||||
* Generally, adding lights to the scene hurts performance, however filament is designed to be
|
||||
* able to handle hundreds of lights in a scene under certain conditions. Here are some tips
|
||||
* to keep performances high.
|
||||
*
|
||||
* 1. Prefer spot lights to point lights and use the smallest outer cone angle possible.
|
||||
*
|
||||
* 2. Use the smallest possible falloff distance for point and spot lights.
|
||||
* Performance is very sensitive to overlapping lights. The falloff distance essentially
|
||||
* defines a sphere of influence for the light, so try to position point and spot lights
|
||||
* such that they don't overlap too much.
|
||||
*
|
||||
* On the other hand, a scene can contain hundreds of non overlapping lights without
|
||||
* incurring a significant overhead.
|
||||
*
|
||||
*/
|
||||
class UTILS_PUBLIC LightManager : public FilamentAPI {
|
||||
struct BuilderDetails;
|
||||
|
||||
public:
|
||||
using Instance = utils::EntityInstance<LightManager>;
|
||||
|
||||
/**
|
||||
* Returns the number of component in the LightManager, not that component are not
|
||||
* guaranteed to be active. Use the EntityManager::isAlive() before use if needed.
|
||||
*
|
||||
* @return number of component in the LightManager
|
||||
*/
|
||||
size_t getComponentCount() const noexcept;
|
||||
|
||||
/**
|
||||
* Returns the list of Entity for all components. Use getComponentCount() to know the size
|
||||
* of the list.
|
||||
* @return a pointer to Entity
|
||||
*/
|
||||
utils::Entity const* getEntities() const noexcept;
|
||||
|
||||
/**
|
||||
* Returns whether a particular Entity is associated with a component of this LightManager
|
||||
* @param e An Entity.
|
||||
* @return true if this Entity has a component associated with this manager.
|
||||
*/
|
||||
bool hasComponent(utils::Entity e) const noexcept;
|
||||
|
||||
/**
|
||||
* Gets an Instance representing the Light component associated with the given Entity.
|
||||
* @param e An Entity.
|
||||
* @return An Instance object, which represents the Light component associated with the Entity e.
|
||||
* @note Use Instance::isValid() to make sure the component exists.
|
||||
* @see hasComponent()
|
||||
*/
|
||||
Instance getInstance(utils::Entity e) const noexcept;
|
||||
|
||||
// destroys this component from the given entity
|
||||
void destroy(utils::Entity e) noexcept;
|
||||
|
||||
|
||||
//! Denotes the type of the light being created.
|
||||
enum class Type : uint8_t {
|
||||
SUN, //!< Directional light that also draws a sun's disk in the sky.
|
||||
DIRECTIONAL, //!< Directional light, emits light in a given direction.
|
||||
POINT, //!< Point light, emits light from a position, in all directions.
|
||||
FOCUSED_SPOT, //!< Physically correct spot light.
|
||||
SPOT, //!< Spot light with coupling of outer cone and illumination disabled.
|
||||
};
|
||||
|
||||
/**
|
||||
* Control the quality / performance of the shadow map associated to this light
|
||||
*/
|
||||
struct ShadowOptions {
|
||||
/** Size of the shadow map in texels. Must be a power-of-two and larger or equal to 8. */
|
||||
uint32_t mapSize = 1024;
|
||||
|
||||
/**
|
||||
* Number of shadow cascades to use for this light. Must be between 1 and 4 (inclusive).
|
||||
* A value greater than 1 turns on cascaded shadow mapping (CSM).
|
||||
* Only applicable to Type.SUN or Type.DIRECTIONAL lights.
|
||||
*
|
||||
* When using shadow cascades, cascadeSplitPositions must also be set.
|
||||
*
|
||||
* @see ShadowOptions::cascadeSplitPositions
|
||||
*/
|
||||
uint8_t shadowCascades = 1;
|
||||
|
||||
/**
|
||||
* The split positions for shadow cascades.
|
||||
*
|
||||
* Cascaded shadow mapping (CSM) partitions the camera frustum into cascades. These values
|
||||
* determine the planes along the camera's Z axis to split the frustum. The camera near
|
||||
* plane is represented by 0.0f and the far plane represented by 1.0f.
|
||||
*
|
||||
* For example, if using 4 cascades, these values would set a uniform split scheme:
|
||||
* { 0.25f, 0.50f, 0.75f }
|
||||
*
|
||||
* For N cascades, N - 1 split positions will be read from this array.
|
||||
*
|
||||
* Filament provides utility methods inside LightManager::ShadowCascades to help set these
|
||||
* values. For example, to use a uniform split scheme:
|
||||
*
|
||||
* ~~~~~~~~~~~{.cpp}
|
||||
* LightManager::ShadowCascades::computeUniformSplits(options.splitPositions, 4);
|
||||
* ~~~~~~~~~~~
|
||||
*
|
||||
* @see ShadowCascades::computeUniformSplits
|
||||
* @see ShadowCascades::computeLogSplits
|
||||
* @see ShadowCascades::computePracticalSplits
|
||||
*/
|
||||
float cascadeSplitPositions[3] = { 0.25f, 0.50f, 0.75f };
|
||||
|
||||
/** Constant bias in world units (e.g. meters) by which shadows are moved away from the
|
||||
* light. 1mm by default.
|
||||
* This is ignored when the View's ShadowType is set to VSM.
|
||||
*/
|
||||
float constantBias = 0.001f;
|
||||
|
||||
/** Amount by which the maximum sampling error is scaled. The resulting value is used
|
||||
* to move the shadow away from the fragment normal. Should be 1.0.
|
||||
* This is ignored when the View's ShadowType is set to VSM.
|
||||
*/
|
||||
float normalBias = 1.0f;
|
||||
|
||||
/** Distance from the camera after which shadows are clipped. This is used to clip
|
||||
* shadows that are too far and wouldn't contribute to the scene much, improving
|
||||
* performance and quality. This value is always positive.
|
||||
* Use 0.0f to use the camera far distance.
|
||||
*/
|
||||
float shadowFar = 0.0f;
|
||||
|
||||
/** Optimize the quality of shadows from this distance from the camera. Shadows will
|
||||
* be rendered in front of this distance, but the quality may not be optimal.
|
||||
* This value is always positive. Use 0.0f to use the camera near distance.
|
||||
* The default of 1m works well with many scenes. The quality of shadows may drop
|
||||
* rapidly when this value decreases.
|
||||
*/
|
||||
float shadowNearHint = 1.0f;
|
||||
|
||||
/** Optimize the quality of shadows in front of this distance from the camera. Shadows
|
||||
* will be rendered behind this distance, but the quality may not be optimal.
|
||||
* This value is always positive. Use std::numerical_limits<float>::infinity() to
|
||||
* use the camera far distance.
|
||||
*/
|
||||
float shadowFarHint = 100.0f;
|
||||
|
||||
/**
|
||||
* Controls whether the shadow map should be optimized for resolution or stability.
|
||||
* When set to true, all resolution enhancing features that can affect stability are
|
||||
* disabling, resulting in significantly lower resolution shadows, albeit stable ones.
|
||||
*/
|
||||
bool stable = false;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* Generally this value shouldn't be changed or at least be small and positive.
|
||||
*/
|
||||
float polygonOffsetConstant = 0.5f;
|
||||
|
||||
/**
|
||||
* Bias based on the change in depth in depth-resolution units by which shadows are moved
|
||||
* 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.
|
||||
* Setting this value correctly is essential for LISPSM shadow-maps.
|
||||
*/
|
||||
float polygonOffsetSlope = 2.0f;
|
||||
|
||||
/**
|
||||
* Whether screen-space contact shadows are used. This applies regardless of whether a
|
||||
* Renderable is a shadow caster.
|
||||
* Screen-space contact shadows are typically useful in large scenes.
|
||||
* (off by default)
|
||||
*/
|
||||
bool screenSpaceContactShadows = false;
|
||||
|
||||
/**
|
||||
* Number of ray-marching steps for screen-space contact shadows (8 by default).
|
||||
*
|
||||
* CAUTION: this parameter is ignored for all lights except the directional/sun light,
|
||||
* all other lights use the same value set for the directional/sun light.
|
||||
*
|
||||
*/
|
||||
uint8_t stepCount = 8;
|
||||
|
||||
/**
|
||||
* Maximum shadow-occluder distance for screen-space contact shadows (world units).
|
||||
* (30 cm by default)
|
||||
*
|
||||
* CAUTION: this parameter is ignored for all lights except the directional/sun light,
|
||||
* all other lights use the same value set for the directional/sun light.
|
||||
*
|
||||
*/
|
||||
float maxShadowDistance = 0.3f;
|
||||
|
||||
/**
|
||||
* Options available when the View's ShadowType is set to VSM.
|
||||
*
|
||||
* @warning This API is still experimental and subject to change.
|
||||
* @see View::setShadowType
|
||||
*/
|
||||
struct Vsm {
|
||||
/**
|
||||
* The number of MSAA samples to use when rendering VSM shadow maps.
|
||||
* Must be a power-of-two and greater than or equal to 1. A value of 1 effectively turns
|
||||
* off MSAA.
|
||||
* Higher values may not be available depending on the underlying hardware.
|
||||
*/
|
||||
uint8_t msaaSamples = 1;
|
||||
|
||||
/**
|
||||
* Blur width for the VSM blur. Zero do disable.
|
||||
* The maximum value is 125.
|
||||
*/
|
||||
float blurWidth = 0.0f;
|
||||
} vsm;
|
||||
};
|
||||
|
||||
struct ShadowCascades {
|
||||
/**
|
||||
* Utility method to compute ShadowOptions::cascadeSplitPositions according to a uniform
|
||||
* split scheme.
|
||||
*
|
||||
* @param splitPositions a float array of at least size (cascades - 1) to write the split
|
||||
* positions into
|
||||
* @param cascades the number of shadow cascades, at most 4
|
||||
*/
|
||||
static void computeUniformSplits(float* splitPositions, uint8_t cascades);
|
||||
|
||||
/**
|
||||
* Utility method to compute ShadowOptions::cascadeSplitPositions according to a logarithmic
|
||||
* split scheme.
|
||||
*
|
||||
* @param splitPositions a float array of at least size (cascades - 1) to write the split
|
||||
* positions into
|
||||
* @param cascades the number of shadow cascades, at most 4
|
||||
* @param near the camera near plane
|
||||
* @param far the camera far plane
|
||||
*/
|
||||
static void computeLogSplits(float* splitPositions, uint8_t cascades,
|
||||
float near, float far);
|
||||
|
||||
/**
|
||||
* Utility method to compute ShadowOptions::cascadeSplitPositions according to a practical
|
||||
* split scheme.
|
||||
*
|
||||
* The practical split scheme uses uses a lambda value to interpolate between the logarithmic
|
||||
* and uniform split schemes. Start with a lambda value of 0.5f and adjust for your scene.
|
||||
*
|
||||
* See: Zhang et al 2006, "Parallel-split shadow maps for large-scale virtual environments"
|
||||
*
|
||||
* @param splitPositions a float array of at least size (cascades - 1) to write the split
|
||||
* positions into
|
||||
* @param cascades the number of shadow cascades, at most 4
|
||||
* @param near the camera near plane
|
||||
* @param far the camera far plane
|
||||
* @param lambda a float in the range [0, 1] that interpolates between log and
|
||||
* uniform split schemes
|
||||
*/
|
||||
static void computePracticalSplits(float* splitPositions, uint8_t cascades,
|
||||
float near, float far, float lambda);
|
||||
};
|
||||
|
||||
//! Use Builder to construct a Light object instance
|
||||
class Builder : public BuilderBase<BuilderDetails> {
|
||||
friend struct BuilderDetails;
|
||||
public:
|
||||
/**
|
||||
* Creates a light builder and set the light's #Type.
|
||||
*
|
||||
* @param type #Type of Light object to create.
|
||||
*/
|
||||
explicit Builder(Type type) noexcept;
|
||||
Builder(Builder const& rhs) noexcept;
|
||||
Builder(Builder&& rhs) noexcept;
|
||||
~Builder() noexcept;
|
||||
Builder& operator=(Builder const& rhs) noexcept;
|
||||
Builder& operator=(Builder&& rhs) noexcept;
|
||||
|
||||
/**
|
||||
* Enables or disables a light channel. Light channel 0 is enabled by default.
|
||||
*
|
||||
* @param channel Light channel to enable or disable, between 0 and 7.
|
||||
* @param enable Whether to enable or disable the light channel.
|
||||
* @return This Builder, for chaining calls.
|
||||
*/
|
||||
Builder& lightChannel(unsigned int channel, bool enable = true) noexcept;
|
||||
|
||||
/**
|
||||
* Whether this Light casts shadows (disabled by default)
|
||||
*
|
||||
* @param enable Enables or disables casting shadows from this Light.
|
||||
*
|
||||
* @return This Builder, for chaining calls.
|
||||
*
|
||||
* @warning
|
||||
* - Only a Type.DIRECTIONAL, Type.SUN, Type.SPOT, or Type.FOCUSED_SPOT light can cast shadows
|
||||
*/
|
||||
Builder& castShadows(bool enable) noexcept;
|
||||
|
||||
/**
|
||||
* Sets the shadow-map options for this light.
|
||||
*
|
||||
* @return This Builder, for chaining calls.
|
||||
*/
|
||||
Builder& shadowOptions(const ShadowOptions& options) noexcept;
|
||||
|
||||
/**
|
||||
* Whether this light casts light (enabled by default)
|
||||
*
|
||||
* @param enable Enables or disables lighting from this Light.
|
||||
*
|
||||
* @return This Builder, for chaining calls.
|
||||
*
|
||||
* @note
|
||||
* In some situations it can be useful to have a light in the scene that doesn't
|
||||
* actually emit light, but does cast shadows.
|
||||
*/
|
||||
Builder& castLight(bool enable) noexcept;
|
||||
|
||||
/**
|
||||
* Sets the initial position of the light in world space.
|
||||
*
|
||||
* @param position Light's position in world space. The default is at the origin.
|
||||
*
|
||||
* @return This Builder, for chaining calls.
|
||||
*
|
||||
* @note
|
||||
* The Light's position is ignored for directional lights (Type.DIRECTIONAL or Type.SUN)
|
||||
*/
|
||||
Builder& position(const math::float3& position) noexcept;
|
||||
|
||||
/**
|
||||
* Sets the initial direction of a light in world space.
|
||||
*
|
||||
* @param direction Light's direction in world space. Should be a unit vector.
|
||||
* The default is {0,-1,0}.
|
||||
*
|
||||
* @return This Builder, for chaining calls.
|
||||
*
|
||||
* @note
|
||||
* The Light's direction is ignored for Type.POINT lights.
|
||||
*/
|
||||
Builder& direction(const math::float3& direction) noexcept;
|
||||
|
||||
/**
|
||||
* Sets the initial color of a light.
|
||||
*
|
||||
* @param color Color of the light specified in the linear sRGB color-space.
|
||||
* The default is white {1,1,1}.
|
||||
*
|
||||
* @return This Builder, for chaining calls.
|
||||
*/
|
||||
Builder& color(const LinearColor& color) noexcept;
|
||||
|
||||
/**
|
||||
* Sets the initial intensity of a light.
|
||||
* @param intensity This parameter depends on the Light.Type:
|
||||
* - For directional lights, it specifies the illuminance in *lux*
|
||||
* (or *lumen/m^2*).
|
||||
* - For point lights and spot lights, it specifies the luminous power
|
||||
* in *lumen*.
|
||||
*
|
||||
* @return This Builder, for chaining calls.
|
||||
*
|
||||
* For example, the sun's illuminance is about 100,000 lux.
|
||||
*
|
||||
* This method overrides any prior calls to intensity or intensityCandela.
|
||||
*
|
||||
*/
|
||||
Builder& intensity(float intensity) noexcept;
|
||||
|
||||
/**
|
||||
* Sets the initial intensity of a spot or point light in candela.
|
||||
*
|
||||
* @param intensity Luminous intensity in *candela*.
|
||||
*
|
||||
* @return This Builder, for chaining calls.
|
||||
*
|
||||
* @note
|
||||
* This method is equivalent to calling intensity(float intensity) for directional lights
|
||||
* (Type.DIRECTIONAL or Type.SUN).
|
||||
*
|
||||
* This method overrides any prior calls to intensity or intensityCandela.
|
||||
*/
|
||||
Builder& intensityCandela(float intensity) noexcept;
|
||||
|
||||
/**
|
||||
* Sets the initial intensity of a light in watts.
|
||||
*
|
||||
* @param watts Energy consumed by a lightbulb. It is related to the energy produced
|
||||
* and ultimately the brightness by the \p efficiency parameter.
|
||||
* This value is often available on the packaging of commercial
|
||||
* lightbulbs.
|
||||
*
|
||||
* @param efficiency Efficiency in percent. This depends on the type of lightbulb used.
|
||||
*
|
||||
* Lightbulb type | Efficiency
|
||||
* ----------------:|-----------:
|
||||
* Incandescent | 2.2%
|
||||
* Halogen | 7.0%
|
||||
* LED | 8.7%
|
||||
* Fluorescent | 10.7%
|
||||
*
|
||||
* @return This Builder, for chaining calls.
|
||||
*
|
||||
*
|
||||
* @note
|
||||
* This call is equivalent to `Builder::intensity(efficiency * 683 * watts);`
|
||||
*
|
||||
* This method overrides any prior calls to intensity or intensityCandela.
|
||||
*/
|
||||
Builder& intensity(float watts, float efficiency) noexcept;
|
||||
|
||||
/**
|
||||
* Set the falloff distance for point lights and spot lights.
|
||||
*
|
||||
* At the falloff distance, the light has no more effect on objects.
|
||||
*
|
||||
* The falloff distance essentially defines a *sphere of influence* around the light, and
|
||||
* therefore has an impact on performance. Larger falloffs might reduce performance
|
||||
* significantly, especially when many lights are used.
|
||||
*
|
||||
* Try to avoid having a large number of light's spheres of influence overlap.
|
||||
*
|
||||
* @param radius Falloff distance in world units. Default is 1 meter.
|
||||
*
|
||||
* @return This Builder, for chaining calls.
|
||||
*
|
||||
* @note
|
||||
* The Light's falloff is ignored for directional lights (Type.DIRECTIONAL or Type.SUN)
|
||||
*/
|
||||
Builder& falloff(float radius) noexcept;
|
||||
|
||||
/**
|
||||
* Defines a spot light'st angular falloff attenuation.
|
||||
*
|
||||
* A spot light is defined by a position, a direction and two cones, \p inner and \p outer.
|
||||
* These two cones are used to define the angular falloff attenuation of the spot light
|
||||
* and are defined by the angle from the center axis to where the falloff begins (i.e.
|
||||
* cones are defined by their half-angle).
|
||||
*
|
||||
* @param inner inner cone angle in *radians* between 0 and @f$ \pi/2 @f$
|
||||
*
|
||||
* @param outer outer cone angle in *radians* between \p inner and @f$ \pi/2 @f$
|
||||
*
|
||||
* @return This Builder, for chaining calls.
|
||||
*
|
||||
* @note
|
||||
* The spot light cone is ignored for directional and point lights.
|
||||
*
|
||||
* @see Type.SPOT, Type.FOCUSED_SPOT
|
||||
*/
|
||||
Builder& spotLightCone(float inner, float outer) noexcept;
|
||||
|
||||
/**
|
||||
* Defines the angular radius of the sun, in degrees, between 0.25° and 20.0°
|
||||
*
|
||||
* The Sun as seen from Earth has an angular size of 0.526° to 0.545°
|
||||
*
|
||||
* @param angularRadius sun's radius in degree. Default is 0.545°.
|
||||
*
|
||||
* @return This Builder, for chaining calls.
|
||||
*/
|
||||
Builder& sunAngularRadius(float angularRadius) noexcept;
|
||||
|
||||
/**
|
||||
* Defines the halo radius of the sun. The radius of the halo is defined as a
|
||||
* multiplier of the sun angular radius.
|
||||
*
|
||||
* @param haloSize radius multiplier. Default is 10.0.
|
||||
*
|
||||
* @return This Builder, for chaining calls.
|
||||
*/
|
||||
Builder& sunHaloSize(float haloSize) noexcept;
|
||||
|
||||
/**
|
||||
* Defines the halo falloff of the sun. The falloff is a dimensionless number
|
||||
* used as an exponent.
|
||||
*
|
||||
* @param haloFalloff halo falloff. Default is 80.0.
|
||||
*
|
||||
* @return This Builder, for chaining calls.
|
||||
*/
|
||||
Builder& sunHaloFalloff(float haloFalloff) noexcept;
|
||||
|
||||
enum Result { Error = -1, Success = 0 };
|
||||
|
||||
/**
|
||||
* Adds the Light component to an entity.
|
||||
*
|
||||
* @param engine Reference to the filament::Engine to associate this light with.
|
||||
* @param entity Entity to add the light component to.
|
||||
* @return Success if the component was created successfully, Error otherwise.
|
||||
*
|
||||
* If exceptions are disabled and an error occurs, this function is a no-op.
|
||||
* Success can be checked by looking at the return value.
|
||||
*
|
||||
* If this component already exists on the given entity, it is first destroyed as if
|
||||
* destroy(utils::Entity e) was called.
|
||||
*
|
||||
* @warning
|
||||
* Currently, only 2048 lights can be created on a given Engine.
|
||||
*
|
||||
* @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.
|
||||
*/
|
||||
Result build(Engine& engine, utils::Entity entity);
|
||||
|
||||
private:
|
||||
friend class FEngine;
|
||||
friend class FLightManager;
|
||||
};
|
||||
|
||||
static constexpr float EFFICIENCY_INCANDESCENT = 0.0220f; //!< Typical efficiency of an incandescent light bulb (2.2%)
|
||||
static constexpr float EFFICIENCY_HALOGEN = 0.0707f; //!< Typical efficiency of an halogen light bulb (7.0%)
|
||||
static constexpr float EFFICIENCY_FLUORESCENT = 0.0878f; //!< Typical efficiency of a fluorescent light bulb (8.7%)
|
||||
static constexpr float EFFICIENCY_LED = 0.1171f; //!< Typical efficiency of a LED light bulb (11.7%)
|
||||
|
||||
Type getType(Instance i) const noexcept;
|
||||
|
||||
/**
|
||||
* Helper function that returns if a light is a directional light
|
||||
*
|
||||
* @param i Instance of the component obtained from getInstance().
|
||||
* @return true is this light is a type of directional light
|
||||
*/
|
||||
inline bool isDirectional(Instance i) const noexcept {
|
||||
Type type = getType(i);
|
||||
return type == Type::DIRECTIONAL || type == Type::SUN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function that returns if a light is a point light
|
||||
*
|
||||
* @param i Instance of the component obtained from getInstance().
|
||||
* @return true is this light is a type of point light
|
||||
*/
|
||||
inline bool isPointLight(Instance i) const noexcept {
|
||||
return getType(i) == Type::POINT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function that returns if a light is a spot light
|
||||
*
|
||||
* @param i Instance of the component obtained from getInstance().
|
||||
* @return true is this light is a type of spot light
|
||||
*/
|
||||
inline bool isSpotLight(Instance i) const noexcept {
|
||||
Type type = getType(i);
|
||||
return type == Type::SPOT || type == Type::FOCUSED_SPOT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables a light channel. Light channel 0 is enabled by default.
|
||||
* @param channel light channel to enable or disable, between 0 and 7.
|
||||
* @param enable whether to enable (true) or disable (false) the specified light channel.
|
||||
*/
|
||||
void setLightChannel(Instance i, unsigned int channel, bool enable = true) noexcept;
|
||||
|
||||
/**
|
||||
* Returns whether a light channel is enabled on a specified light.
|
||||
* @param i Instance of the component obtained from getInstance().
|
||||
* @param channel Light channel to query
|
||||
* @return true if the light channel is enabled, false otherwise
|
||||
*/
|
||||
bool getLightChannel(Instance i, unsigned int channel) const noexcept;
|
||||
|
||||
/**
|
||||
* Dynamically updates the light's position.
|
||||
*
|
||||
* @param i Instance of the component obtained from getInstance().
|
||||
* @param position Light's position in world space. The default is at the origin.
|
||||
*
|
||||
* @see Builder.position()
|
||||
*/
|
||||
void setPosition(Instance i, const math::float3& position) noexcept;
|
||||
|
||||
//! returns the light's position in world space
|
||||
const math::float3& getPosition(Instance i) const noexcept;
|
||||
|
||||
/**
|
||||
* Dynamically updates the light's direction
|
||||
*
|
||||
* @param i Instance of the component obtained from getInstance().
|
||||
* @param direction Light's direction in world space. Should be a unit vector.
|
||||
* The default is {0,-1,0}.
|
||||
*
|
||||
* @see Builder.direction()
|
||||
*/
|
||||
void setDirection(Instance i, const math::float3& direction) noexcept;
|
||||
|
||||
//! returns the light's direction in world space
|
||||
const math::float3& getDirection(Instance i) const noexcept;
|
||||
|
||||
/**
|
||||
* Dynamically updates the light's hue as linear sRGB
|
||||
*
|
||||
* @param i Instance of the component obtained from getInstance().
|
||||
* @param color Color of the light specified in the linear sRGB color-space.
|
||||
* The default is white {1,1,1}.
|
||||
*
|
||||
* @see Builder.color(), getInstance()
|
||||
*/
|
||||
void setColor(Instance i, const LinearColor& color) noexcept;
|
||||
|
||||
/**
|
||||
* @param i Instance of the component obtained from getInstance().
|
||||
* @return the light's color in linear sRGB
|
||||
*/
|
||||
const math::float3& getColor(Instance i) const noexcept;
|
||||
|
||||
/**
|
||||
* Dynamically updates the light's intensity. The intensity can be negative.
|
||||
*
|
||||
* @param i Instance of the component obtained from getInstance().
|
||||
* @param intensity This parameter depends on the Light.Type:
|
||||
* - For directional lights, it specifies the illuminance in *lux*
|
||||
* (or *lumen/m^2*).
|
||||
* - For point lights and spot lights, it specifies the luminous power
|
||||
* in *lumen*.
|
||||
*
|
||||
* @see Builder.intensity()
|
||||
*/
|
||||
void setIntensity(Instance i, float intensity) noexcept;
|
||||
|
||||
/**
|
||||
* Dynamically updates the light's intensity. The intensity can be negative.
|
||||
*
|
||||
* @param i Instance of the component obtained from getInstance().
|
||||
* @param watts Energy consumed by a lightbulb. It is related to the energy produced
|
||||
* and ultimately the brightness by the \p efficiency parameter.
|
||||
* This value is often available on the packaging of commercial
|
||||
* lightbulbs.
|
||||
* @param efficiency Efficiency in percent. This depends on the type of lightbulb used.
|
||||
*
|
||||
* Lightbulb type | Efficiency
|
||||
* ----------------:|-----------:
|
||||
* Incandescent | 2.2%
|
||||
* Halogen | 7.0%
|
||||
* LED | 8.7%
|
||||
* Fluorescent | 10.7%
|
||||
*
|
||||
* @see Builder.intensity(float watts, float efficiency)
|
||||
*/
|
||||
void setIntensity(Instance i, float watts, float efficiency) noexcept {
|
||||
setIntensity(i, watts * 683.0f * efficiency);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dynamically updates the light's intensity in candela. The intensity can be negative.
|
||||
*
|
||||
* @param i Instance of the component obtained from getInstance().
|
||||
* @param intensity Luminous intensity in *candela*.
|
||||
*
|
||||
* @note
|
||||
* This method is equivalent to calling setIntensity(float intensity) for directional lights
|
||||
* (Type.DIRECTIONAL or Type.SUN).
|
||||
*
|
||||
* @see Builder.intensityCandela(float intensity)
|
||||
*/
|
||||
void setIntensityCandela(Instance i, float intensity) noexcept;
|
||||
|
||||
/**
|
||||
* returns the light's luminous intensity in candela.
|
||||
*
|
||||
* @param i Instance of the component obtained from getInstance().
|
||||
*
|
||||
* @note for Type.FOCUSED_SPOT lights, the returned value depends on the \p outer cone angle.
|
||||
*
|
||||
* @return luminous intensity in candela.
|
||||
*/
|
||||
float getIntensity(Instance i) const noexcept;
|
||||
|
||||
/**
|
||||
* Set the falloff distance for point lights and spot lights.
|
||||
*
|
||||
* @param i Instance of the component obtained from getInstance().
|
||||
* @param radius falloff distance in world units. Default is 1 meter.
|
||||
*
|
||||
* @see Builder.falloff()
|
||||
*/
|
||||
void setFalloff(Instance i, float radius) noexcept;
|
||||
|
||||
/**
|
||||
* returns the falloff distance of this light.
|
||||
* @param i Instance of the component obtained from getInstance().
|
||||
* @return the falloff distance of this light.
|
||||
*/
|
||||
float getFalloff(Instance i) const noexcept;
|
||||
|
||||
/**
|
||||
* Dynamically updates a spot light's cone as angles
|
||||
*
|
||||
* @param i Instance of the component obtained from getInstance().
|
||||
* @param inner inner cone angle in *radians* between 0 and pi/2
|
||||
* @param outer outer cone angle in *radians* between inner and pi/2
|
||||
*
|
||||
* @see Builder.spotLightCone()
|
||||
*/
|
||||
void setSpotLightCone(Instance i, float inner, float outer) noexcept;
|
||||
|
||||
/**
|
||||
* returns the outer cone angle in *radians* between inner and pi/2.
|
||||
* @param i Instance of the component obtained from getInstance().
|
||||
* @return the outer cone angle of this light.
|
||||
*/
|
||||
float getSpotLightOuterCone(Instance i) const noexcept;
|
||||
|
||||
/**
|
||||
* returns the inner cone angle in *radians* between 0 and pi/2.
|
||||
*
|
||||
* The value is recomputed from the initial values, thus is not precisely
|
||||
* the same as the one passed to setSpotLightCone() or Builder.spotLightCone().
|
||||
*
|
||||
* @param i Instance of the component obtained from getInstance().
|
||||
* @return the inner cone angle of this light.
|
||||
*/
|
||||
float getSpotLightInnerCone(Instance i) const noexcept;
|
||||
|
||||
/**
|
||||
* Dynamically updates the angular radius of a Type.SUN light
|
||||
*
|
||||
* The Sun as seen from Earth has an angular size of 0.526° to 0.545°
|
||||
*
|
||||
* @param i Instance of the component obtained from getInstance().
|
||||
* @param angularRadius sun's radius in degrees. Default is 0.545°.
|
||||
*/
|
||||
void setSunAngularRadius(Instance i, float angularRadius) noexcept;
|
||||
|
||||
/**
|
||||
* returns the angular radius if the sun in degrees.
|
||||
* @param i Instance of the component obtained from getInstance().
|
||||
* @return the angular radius if the sun in degrees.
|
||||
*/
|
||||
float getSunAngularRadius(Instance i) const noexcept;
|
||||
|
||||
/**
|
||||
* Dynamically updates the halo radius of a Type.SUN light. The radius
|
||||
* of the halo is defined as a multiplier of the sun angular radius.
|
||||
*
|
||||
* @param i Instance of the component obtained from getInstance().
|
||||
* @param haloSize radius multiplier. Default is 10.0.
|
||||
*/
|
||||
void setSunHaloSize(Instance i, float haloSize) noexcept;
|
||||
|
||||
/**
|
||||
* returns the halo size of a Type.SUN light as a multiplier of the
|
||||
* sun angular radius.
|
||||
* @param i Instance of the component obtained from getInstance().
|
||||
* @return the halo size
|
||||
*/
|
||||
float getSunHaloSize(Instance i) const noexcept;
|
||||
|
||||
/**
|
||||
* Dynamically updates the halo falloff of a Type.SUN light. The falloff
|
||||
* is a dimensionless number used as an exponent.
|
||||
*
|
||||
* @param i Instance of the component obtained from getInstance().
|
||||
* @param haloFalloff halo falloff. Default is 80.0.
|
||||
*/
|
||||
void setSunHaloFalloff(Instance i, float haloFalloff) noexcept;
|
||||
|
||||
/**
|
||||
* returns the halo falloff of a Type.SUN light as a dimensionless value.
|
||||
* @param i Instance of the component obtained from getInstance().
|
||||
* @return the halo falloff
|
||||
*/
|
||||
float getSunHaloFalloff(Instance i) const noexcept;
|
||||
|
||||
/**
|
||||
* returns the shadow-map options for a given light
|
||||
* @param i Instance of the component obtained from getInstance().
|
||||
* @return A ShadowOption structure
|
||||
*/
|
||||
ShadowOptions const& getShadowOptions(Instance i) const noexcept;
|
||||
|
||||
/**
|
||||
* sets the shadow-map options for a given light
|
||||
* @param i Instance of the component obtained from getInstance().
|
||||
* @param options A ShadowOption structure
|
||||
*/
|
||||
void setShadowOptions(Instance i, ShadowOptions const& options) noexcept;
|
||||
|
||||
/**
|
||||
* Whether this Light casts shadows (disabled by default)
|
||||
*
|
||||
* @param i Instance of the component obtained from getInstance().
|
||||
* @param shadowCaster Enables or disables casting shadows from this Light.
|
||||
*
|
||||
* @warning
|
||||
* - Only a Type.DIRECTIONAL, Type.SUN, Type.SPOT, or Type.FOCUSED_SPOT light can cast shadows
|
||||
*/
|
||||
void setShadowCaster(Instance i, bool shadowCaster) noexcept;
|
||||
|
||||
/**
|
||||
* returns whether this light casts shadows.
|
||||
* @param i Instance of the component obtained from getInstance().
|
||||
*/
|
||||
bool isShadowCaster(Instance i) const noexcept;
|
||||
|
||||
/**
|
||||
* Helper to process all components with a given function
|
||||
* @tparam F a void(Entity entity, Instance instance)
|
||||
* @param func a function of type F
|
||||
*/
|
||||
template<typename F>
|
||||
void forEachComponent(F func) noexcept {
|
||||
utils::Entity const* const pEntity = getEntities();
|
||||
for (size_t i = 0, c = getComponentCount(); i < c; i++) {
|
||||
// Instance 0 is the invalid instance
|
||||
func(pEntity[i], Instance(i + 1));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace filament
|
||||
|
||||
#endif // TNT_FILAMENT_LIGHTMANAGER_H
|
||||
284
ios/include/filament/Material.h
Normal file
284
ios/include/filament/Material.h
Normal file
@@ -0,0 +1,284 @@
|
||||
/*
|
||||
* 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 TNT_FILAMENT_MATERIAL_H
|
||||
#define TNT_FILAMENT_MATERIAL_H
|
||||
|
||||
#include <filament/Color.h>
|
||||
#include <filament/FilamentAPI.h>
|
||||
#include <filament/MaterialEnums.h>
|
||||
#include <filament/MaterialInstance.h>
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <math/mathfwd.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace utils {
|
||||
class CString;
|
||||
} // namespace utils
|
||||
|
||||
namespace filament {
|
||||
|
||||
class Texture;
|
||||
class TextureSampler;
|
||||
|
||||
class FEngine;
|
||||
class FMaterial;
|
||||
|
||||
class Engine;
|
||||
|
||||
class UTILS_PUBLIC Material : public FilamentAPI {
|
||||
struct BuilderDetails;
|
||||
|
||||
public:
|
||||
using BlendingMode = BlendingMode;
|
||||
using Shading = Shading;
|
||||
using Interpolation = Interpolation;
|
||||
using VertexDomain = VertexDomain;
|
||||
using TransparencyMode = TransparencyMode;
|
||||
|
||||
using ParameterType = backend::UniformType;
|
||||
using Precision = backend::Precision;
|
||||
using SamplerType = backend::SamplerType;
|
||||
using SamplerFormat = backend::SamplerFormat;
|
||||
using CullingMode = backend::CullingMode;
|
||||
using ShaderModel = backend::ShaderModel;
|
||||
using SubpassType = backend::SubpassType;
|
||||
|
||||
/**
|
||||
* Holds information about a material parameter.
|
||||
*/
|
||||
struct ParameterInfo {
|
||||
//! Name of the parameter.
|
||||
const char* name;
|
||||
//! Whether the parameter is a sampler (texture).
|
||||
bool isSampler;
|
||||
//! Whether the parameter is a subpass type.
|
||||
bool isSubpass;
|
||||
union {
|
||||
//! Type of the parameter if the parameter is not a sampler.
|
||||
ParameterType type;
|
||||
//! Type of the parameter if the parameter is a sampler.
|
||||
SamplerType samplerType;
|
||||
//! Type of the parameter if the parameter is a subpass.
|
||||
SubpassType subpassType;
|
||||
};
|
||||
//! Size of the parameter when the parameter is an array.
|
||||
uint32_t count;
|
||||
//! Requested precision of the parameter.
|
||||
Precision precision;
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* Specifies the material data. The material data is a binary blob produced by
|
||||
* libfilamat or by matc.
|
||||
*
|
||||
* @param payload Pointer to the material data, must stay valid until build() is called.
|
||||
* @param size Size of the material data pointed to by "payload" in bytes.
|
||||
*/
|
||||
Builder& package(const void* payload, size_t size);
|
||||
|
||||
/**
|
||||
* Creates the Material object and returns a pointer to it.
|
||||
*
|
||||
* @param engine Reference to the filament::Engine to associate this Material 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.
|
||||
*/
|
||||
Material* build(Engine& engine);
|
||||
private:
|
||||
friend class FMaterial;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new instance of this material. Material instances should be freed using
|
||||
* Engine::destroy(const MaterialInstance*).
|
||||
*
|
||||
* @param name Optional name to associate with the given material instance. If this is null,
|
||||
* then the instance inherits the material's name.
|
||||
*
|
||||
* @return A pointer to the new instance.
|
||||
*/
|
||||
MaterialInstance* createInstance(const char* name = nullptr) const noexcept;
|
||||
|
||||
//! Returns the name of this material as a null-terminated string.
|
||||
const char* getName() const noexcept;
|
||||
|
||||
//! Returns the shading model of this material.
|
||||
Shading getShading() const noexcept;
|
||||
|
||||
//! Returns the interpolation mode of this material. This affects how variables are interpolated.
|
||||
Interpolation getInterpolation() const noexcept;
|
||||
|
||||
//! Returns the blending mode of this material.
|
||||
BlendingMode getBlendingMode() const noexcept;
|
||||
|
||||
//! Returns the vertex domain of this material.
|
||||
VertexDomain getVertexDomain() const noexcept;
|
||||
|
||||
//! Returns the material domain of this material.
|
||||
//! The material domain determines how the material is used.
|
||||
MaterialDomain getMaterialDomain() const noexcept;
|
||||
|
||||
//! Returns the default culling mode of this material.
|
||||
CullingMode getCullingMode() const noexcept;
|
||||
|
||||
//! Returns the transparency mode of this material.
|
||||
//! This value only makes sense when the blending mode is transparent or fade.
|
||||
TransparencyMode getTransparencyMode() const noexcept;
|
||||
|
||||
//! Indicates whether instances of this material will, by default, write to the color buffer.
|
||||
bool isColorWriteEnabled() const noexcept;
|
||||
|
||||
//! Indicates whether instances of this material will, by default, write to the depth buffer.
|
||||
bool isDepthWriteEnabled() const noexcept;
|
||||
|
||||
//! Indicates whether instances of this material will, by default, use depth testing.
|
||||
bool isDepthCullingEnabled() const noexcept;
|
||||
|
||||
//! Indicates whether this material is double-sided.
|
||||
bool isDoubleSided() const noexcept;
|
||||
|
||||
//! Returns the alpha mask threshold used when the blending mode is set to masked.
|
||||
float getMaskThreshold() const noexcept;
|
||||
|
||||
//! Indicates whether this material uses the shadowing factor as a color multiplier.
|
||||
//! This values only makes sense when the shading mode is unlit.
|
||||
bool hasShadowMultiplier() const noexcept;
|
||||
|
||||
//! Indicates whether this material has specular anti-aliasing enabled
|
||||
bool hasSpecularAntiAliasing() const noexcept;
|
||||
|
||||
//! Returns the screen-space variance for specular-antialiasing, this value is between 0 and 1.
|
||||
float getSpecularAntiAliasingVariance() const noexcept;
|
||||
|
||||
//! Returns the clamping threshold for specular-antialiasing, this value is between 0 and 1.
|
||||
float getSpecularAntiAliasingThreshold() const noexcept;
|
||||
|
||||
//! Returns the list of vertex attributes required by this material.
|
||||
AttributeBitset getRequiredAttributes() const noexcept;
|
||||
|
||||
//! Returns the refraction mode used by this material.
|
||||
RefractionMode getRefractionMode() const noexcept;
|
||||
|
||||
// Return the refraction type used by this material.
|
||||
RefractionType getRefractionType() const noexcept;
|
||||
|
||||
/**
|
||||
* Returns the number of parameters declared by this material.
|
||||
* The returned value can be 0.
|
||||
*/
|
||||
size_t getParameterCount() const noexcept;
|
||||
|
||||
/**
|
||||
* Gets information about this material's parameters.
|
||||
*
|
||||
* @param parameters A pointer to a list of ParameterInfo.
|
||||
* The list must be at least "count" large
|
||||
* @param count The number of parameters to retrieve. Must be >= 0 and can be > count.
|
||||
*
|
||||
* @return The number of parameters written to the parameters pointer.
|
||||
*/
|
||||
size_t getParameters(ParameterInfo* parameters, size_t count) const noexcept;
|
||||
|
||||
//! Indicates whether a parameter of the given name exists on this material.
|
||||
bool hasParameter(const char* name) const noexcept;
|
||||
|
||||
//! Indicates whether an existing parameter is a sampler or not.
|
||||
bool isSampler(const char* name) const noexcept;
|
||||
|
||||
/**
|
||||
* Sets the value of the given parameter on this material's default instance.
|
||||
*
|
||||
* @param name The name of the material parameter
|
||||
* @param value The value of the material parameter
|
||||
*
|
||||
* @see getDefaultInstance()
|
||||
*/
|
||||
template <typename T>
|
||||
void setDefaultParameter(const char* name, T value) noexcept {
|
||||
getDefaultInstance()->setParameter(name, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a texture and sampler parameters on this material's default instance.
|
||||
*
|
||||
* @param name The name of the material texture parameter
|
||||
* @param texture The texture to set as parameter
|
||||
* @param sampler The sampler to be used with this texture
|
||||
*
|
||||
* @see getDefaultInstance()
|
||||
*/
|
||||
void setDefaultParameter(const char* name, Texture const* texture,
|
||||
TextureSampler const& sampler) noexcept {
|
||||
getDefaultInstance()->setParameter(name, texture, sampler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the color of the given parameter on this material's default instance.
|
||||
*
|
||||
* @param name The name of the material color parameter
|
||||
* @param type Whether the color is specified in the linear or sRGB space
|
||||
* @param color The color as a floating point red, green, blue tuple
|
||||
*
|
||||
* @see getDefaultInstance()
|
||||
*/
|
||||
void setDefaultParameter(const char* name, RgbType type, math::float3 color) noexcept {
|
||||
getDefaultInstance()->setParameter(name, type, color);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the color of the given parameter on this material's default instance.
|
||||
*
|
||||
* @param name The name of the material color parameter
|
||||
* @param type Whether the color is specified in the linear or sRGB space
|
||||
* @param color The color as a floating point red, green, blue, alpha tuple
|
||||
*
|
||||
* @see getDefaultInstance()
|
||||
*/
|
||||
void setDefaultParameter(const char* name, RgbaType type, math::float4 color) noexcept {
|
||||
getDefaultInstance()->setParameter(name, type, color);
|
||||
}
|
||||
|
||||
//! Returns this material's default instance.
|
||||
MaterialInstance* getDefaultInstance() noexcept;
|
||||
|
||||
//! Returns this material's default instance.
|
||||
MaterialInstance const* getDefaultInstance() const noexcept;
|
||||
};
|
||||
|
||||
} // namespace filament
|
||||
|
||||
#endif // TNT_FILAMENT_MATERIAL_H
|
||||
87
ios/include/filament/MaterialChunkType.h
Normal file
87
ios/include/filament/MaterialChunkType.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* 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_MATERIAL_CHUNK_TYPES_H
|
||||
#define TNT_FILAMAT_MATERIAL_CHUNK_TYPES_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
namespace filamat {
|
||||
|
||||
// Pack an eight character string into a 64 bit integer.
|
||||
constexpr inline uint64_t charTo64bitNum(const char str[9]) noexcept {
|
||||
return
|
||||
( (static_cast<uint64_t >(str[0]) << 56))
|
||||
| ((static_cast<uint64_t >(str[1]) << 48) & 0x00FF000000000000U)
|
||||
| ((static_cast<uint64_t >(str[2]) << 40) & 0x0000FF0000000000U)
|
||||
| ((static_cast<uint64_t >(str[3]) << 32) & 0x000000FF00000000U)
|
||||
| ((static_cast<uint64_t >(str[4]) << 24) & 0x00000000FF000000U)
|
||||
| ((static_cast<uint64_t >(str[5]) << 16) & 0x0000000000FF0000U)
|
||||
| ((static_cast<uint64_t >(str[6]) << 8) & 0x000000000000FF00U)
|
||||
| ( static_cast<uint64_t >(str[7]) & 0x00000000000000FFU);
|
||||
}
|
||||
|
||||
enum UTILS_PUBLIC ChunkType : uint64_t {
|
||||
Unknown = charTo64bitNum("UNKNOWN "),
|
||||
MaterialUib = charTo64bitNum("MAT_UIB "),
|
||||
MaterialSib = charTo64bitNum("MAT_SIB "),
|
||||
MaterialSubpass = charTo64bitNum("MAT_SUB "),
|
||||
MaterialGlsl = charTo64bitNum("MAT_GLSL"),
|
||||
MaterialSpirv = charTo64bitNum("MAT_SPIR"),
|
||||
MaterialMetal = charTo64bitNum("MAT_METL"),
|
||||
MaterialShaderModels = charTo64bitNum("MAT_SMDL"),
|
||||
MaterialSamplerBindings = charTo64bitNum("MAT_SAMP"), // no longer used
|
||||
MaterialProperties = charTo64bitNum("MAT_PROP"),
|
||||
|
||||
MaterialName = charTo64bitNum("MAT_NAME"),
|
||||
MaterialVersion = charTo64bitNum("MAT_VERS"),
|
||||
MaterialShading = charTo64bitNum("MAT_SHAD"),
|
||||
MaterialBlendingMode = charTo64bitNum("MAT_BLEN"),
|
||||
MaterialTransparencyMode = charTo64bitNum("MAT_TRMD"),
|
||||
MaterialMaskThreshold = charTo64bitNum("MAT_THRS"),
|
||||
MaterialShadowMultiplier = charTo64bitNum("MAT_SHML"),
|
||||
MaterialSpecularAntiAliasing = charTo64bitNum("MAT_SPAA"),
|
||||
MaterialSpecularAntiAliasingVariance = charTo64bitNum("MAT_SVAR"),
|
||||
MaterialSpecularAntiAliasingThreshold = charTo64bitNum("MAT_STHR"),
|
||||
MaterialClearCoatIorChange = charTo64bitNum("MAT_CIOR"),
|
||||
MaterialDomain = charTo64bitNum("MAT_DOMN"),
|
||||
MaterialRefraction = charTo64bitNum("MAT_REFM"),
|
||||
MaterialRefractionType = charTo64bitNum("MAT_REFT"),
|
||||
|
||||
MaterialRequiredAttributes = charTo64bitNum("MAT_REQA"),
|
||||
MaterialDepthWriteSet = charTo64bitNum("MAT_DEWS"),
|
||||
MaterialDoubleSidedSet = charTo64bitNum("MAT_DOSS"),
|
||||
MaterialDoubleSided = charTo64bitNum("MAT_DOSI"),
|
||||
|
||||
MaterialColorWrite = charTo64bitNum("MAT_CWRIT"),
|
||||
MaterialDepthWrite = charTo64bitNum("MAT_DWRIT"),
|
||||
MaterialDepthTest = charTo64bitNum("MAT_DTEST"),
|
||||
MaterialCullingMode = charTo64bitNum("MAT_CUMO"),
|
||||
|
||||
MaterialHasCustomDepthShader =charTo64bitNum("MAT_CSDP"),
|
||||
|
||||
MaterialVertexDomain = charTo64bitNum("MAT_VEDO"),
|
||||
MaterialInterpolation = charTo64bitNum("MAT_INTR"),
|
||||
|
||||
DictionaryText = charTo64bitNum("DIC_TEXT"),
|
||||
DictionarySpirv = charTo64bitNum("DIC_SPIR"),
|
||||
};
|
||||
|
||||
} // namespace filamat
|
||||
|
||||
#endif // TNT_FILAMAT_MATERIAL_CHUNK_TYPES_H
|
||||
226
ios/include/filament/MaterialEnums.h
Normal file
226
ios/include/filament/MaterialEnums.h
Normal file
@@ -0,0 +1,226 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef TNT_FILAMENT_MATERIAL_ENUM_H
|
||||
#define TNT_FILAMENT_MATERIAL_ENUM_H
|
||||
|
||||
#include <utils/bitset.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace filament {
|
||||
|
||||
// update this when a new version of filament wouldn't work with older materials
|
||||
static constexpr size_t MATERIAL_VERSION = 12;
|
||||
|
||||
/**
|
||||
* Supported shading models
|
||||
*/
|
||||
enum class Shading : uint8_t {
|
||||
UNLIT, //!< no lighting applied, emissive possible
|
||||
LIT, //!< default, standard lighting
|
||||
SUBSURFACE, //!< subsurface lighting model
|
||||
CLOTH, //!< cloth lighting model
|
||||
SPECULAR_GLOSSINESS, //!< legacy lighting model
|
||||
};
|
||||
|
||||
/**
|
||||
* Attribute interpolation types in the fragment shader
|
||||
*/
|
||||
enum class Interpolation : uint8_t {
|
||||
SMOOTH, //!< default, smooth interpolation
|
||||
FLAT //!< flat interpolation
|
||||
};
|
||||
|
||||
/**
|
||||
* Shader quality, affect some global quality parameters
|
||||
*/
|
||||
enum class ShaderQuality : int8_t {
|
||||
DEFAULT = -1, // LOW on mobile, HIGH on desktop
|
||||
LOW = 0, // enable optimizations that can slightly affect correctness
|
||||
NORMAL = 1, // normal quality, correctness honored
|
||||
HIGH = 2 // higher quality (e.g. better upscaling, etc...)
|
||||
};
|
||||
|
||||
/**
|
||||
* Supported blending modes
|
||||
*/
|
||||
enum class BlendingMode : uint8_t {
|
||||
//! material is opaque
|
||||
OPAQUE,
|
||||
//! material is transparent and color is alpha-pre-multiplied, affects diffuse lighting only
|
||||
TRANSPARENT,
|
||||
//! material is additive (e.g.: hologram)
|
||||
ADD,
|
||||
//! material is masked (i.e. alpha tested)
|
||||
MASKED,
|
||||
/**
|
||||
* material is transparent and color is alpha-pre-multiplied, affects specular lighting
|
||||
* when adding more entries, change the size of FRenderer::CommandKey::blending
|
||||
*/
|
||||
FADE,
|
||||
//! material darkens what's behind it
|
||||
MULTIPLY,
|
||||
//! material brightens what's behind it
|
||||
SCREEN,
|
||||
};
|
||||
|
||||
/**
|
||||
* How transparent objects are handled
|
||||
*/
|
||||
enum class TransparencyMode : uint8_t {
|
||||
//! the transparent object is drawn honoring the raster state
|
||||
DEFAULT,
|
||||
/**
|
||||
* the transparent object is first drawn in the depth buffer,
|
||||
* then in the color buffer, honoring the culling mode, but ignoring the depth test function
|
||||
*/
|
||||
TWO_PASSES_ONE_SIDE,
|
||||
|
||||
/**
|
||||
* the transparent object is drawn twice in the color buffer,
|
||||
* first with back faces only, then with front faces; the culling
|
||||
* mode is ignored. Can be combined with two-sided lighting
|
||||
*/
|
||||
TWO_PASSES_TWO_SIDES
|
||||
};
|
||||
|
||||
/**
|
||||
* Supported types of vertex domains.
|
||||
*/
|
||||
enum class VertexDomain : uint8_t {
|
||||
OBJECT, //!< vertices are in object space, default
|
||||
WORLD, //!< vertices are in world space
|
||||
VIEW, //!< vertices are in view space
|
||||
DEVICE //!< vertices are in normalized device space
|
||||
// when adding more entries, make sure to update VERTEX_DOMAIN_COUNT
|
||||
};
|
||||
|
||||
/**
|
||||
* Vertex attribute types
|
||||
*/
|
||||
enum VertexAttribute : uint8_t {
|
||||
// Update hasIntegerTarget() in VertexBuffer when adding an attribute that will
|
||||
// be read as integers in the shaders
|
||||
|
||||
POSITION = 0, //!< XYZ position (float3)
|
||||
TANGENTS = 1, //!< tangent, bitangent and normal, encoded as a quaternion (float4)
|
||||
COLOR = 2, //!< vertex color (float4)
|
||||
UV0 = 3, //!< texture coordinates (float2)
|
||||
UV1 = 4, //!< texture coordinates (float2)
|
||||
BONE_INDICES = 5, //!< indices of 4 bones, as unsigned integers (uvec4)
|
||||
BONE_WEIGHTS = 6, //!< weights of the 4 bones (normalized float4)
|
||||
// -- we have 1 unused slot here --
|
||||
CUSTOM0 = 8,
|
||||
CUSTOM1 = 9,
|
||||
CUSTOM2 = 10,
|
||||
CUSTOM3 = 11,
|
||||
CUSTOM4 = 12,
|
||||
CUSTOM5 = 13,
|
||||
CUSTOM6 = 14,
|
||||
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
|
||||
};
|
||||
|
||||
static constexpr size_t MAX_MORPH_TARGETS = 4;
|
||||
static constexpr size_t MAX_CUSTOM_ATTRIBUTES = 8;
|
||||
|
||||
/**
|
||||
* Material domains
|
||||
*/
|
||||
enum class MaterialDomain : uint8_t {
|
||||
SURFACE = 0, //!< shaders applied to renderables
|
||||
POST_PROCESS = 1, //!< shaders applied to rendered buffers
|
||||
};
|
||||
|
||||
/**
|
||||
* Specular occlusion
|
||||
*/
|
||||
enum class SpecularAmbientOcclusion : uint8_t {
|
||||
NONE = 0, //!< no specular occlusion
|
||||
SIMPLE = 1, //!< simple specular occlusion
|
||||
BENT_NORMALS = 2, //!< more accurate specular occlusion, requires bent normals
|
||||
};
|
||||
|
||||
/**
|
||||
* Refraction
|
||||
*/
|
||||
enum class RefractionMode : uint8_t {
|
||||
NONE = 0, //!< no refraction
|
||||
CUBEMAP = 1, //!< refracted rays go to the ibl cubemap
|
||||
SCREEN_SPACE = 2, //!< refracted rays go to screen space
|
||||
};
|
||||
|
||||
/**
|
||||
* Refraction type
|
||||
*/
|
||||
enum class RefractionType : uint8_t {
|
||||
SOLID = 0, //!< refraction through solid objects (e.g. a sphere)
|
||||
THIN = 1, //!< refraction through thin objects (e.g. window)
|
||||
};
|
||||
|
||||
// can't really use std::underlying_type<AttributeIndex>::type because the driver takes a uint32_t
|
||||
using AttributeBitset = utils::bitset32;
|
||||
|
||||
static constexpr size_t MATERIAL_PROPERTIES_COUNT = 26;
|
||||
enum class Property : uint8_t {
|
||||
BASE_COLOR, //!< float4, all shading models
|
||||
ROUGHNESS, //!< float, lit shading models only
|
||||
METALLIC, //!< float, all shading models, except unlit and cloth
|
||||
REFLECTANCE, //!< float, all shading models, except unlit and cloth
|
||||
AMBIENT_OCCLUSION, //!< float, lit shading models only, except subsurface and cloth
|
||||
CLEAR_COAT, //!< float, lit shading models only, except subsurface and cloth
|
||||
CLEAR_COAT_ROUGHNESS, //!< float, lit shading models only, except subsurface and cloth
|
||||
CLEAR_COAT_NORMAL, //!< float, lit shading models only, except subsurface and cloth
|
||||
ANISOTROPY, //!< float, lit shading models only, except subsurface and cloth
|
||||
ANISOTROPY_DIRECTION, //!< float3, lit shading models only, except subsurface and cloth
|
||||
THICKNESS, //!< float, subsurface shading model only
|
||||
SUBSURFACE_POWER, //!< float, subsurface shading model only
|
||||
SUBSURFACE_COLOR, //!< float3, subsurface and cloth shading models only
|
||||
SHEEN_COLOR, //!< float3, lit shading models only, except subsurface
|
||||
SHEEN_ROUGHNESS, //!< float3, lit shading models only, except subsurface and cloth
|
||||
SPECULAR_COLOR, //!< float3, specular-glossiness shading model only
|
||||
GLOSSINESS, //!< float, specular-glossiness shading model only
|
||||
EMISSIVE, //!< float4, all shading models
|
||||
NORMAL, //!< float3, all shading models only, except unlit
|
||||
POST_LIGHTING_COLOR, //!< float4, all shading models
|
||||
CLIP_SPACE_TRANSFORM, //!< mat4, vertex shader only
|
||||
ABSORPTION, //!< float3, how much light is absorbed by the material
|
||||
TRANSMISSION, //!< float, how much light is refracted through the material
|
||||
IOR, //!< float, material's index of refraction
|
||||
MICRO_THICKNESS, //!< float, thickness of the thin layer
|
||||
BENT_NORMAL, //!< float3, all shading models only, except unlit
|
||||
|
||||
// when adding new Properties, make sure to update MATERIAL_PROPERTIES_COUNT
|
||||
};
|
||||
|
||||
} // namespace filament
|
||||
|
||||
#endif
|
||||
223
ios/include/filament/MaterialInstance.h
Normal file
223
ios/include/filament/MaterialInstance.h
Normal file
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
* 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 TNT_FILAMENT_MATERIALINSTANCE_H
|
||||
#define TNT_FILAMENT_MATERIALINSTANCE_H
|
||||
|
||||
#include <filament/FilamentAPI.h>
|
||||
#include <filament/Color.h>
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <math/mathfwd.h>
|
||||
|
||||
namespace filament {
|
||||
|
||||
class Material;
|
||||
class Texture;
|
||||
class TextureSampler;
|
||||
class UniformBuffer;
|
||||
class UniformInterfaceBlock;
|
||||
|
||||
class UTILS_PUBLIC MaterialInstance : public FilamentAPI {
|
||||
public:
|
||||
using CullingMode = filament::backend::CullingMode;
|
||||
|
||||
template<typename T>
|
||||
using is_supported_parameter_t = typename std::enable_if<
|
||||
std::is_same<float, T>::value ||
|
||||
std::is_same<int32_t, T>::value ||
|
||||
std::is_same<uint32_t, T>::value ||
|
||||
std::is_same<math::int2, T>::value ||
|
||||
std::is_same<math::int3, T>::value ||
|
||||
std::is_same<math::int4, T>::value ||
|
||||
std::is_same<math::uint2, T>::value ||
|
||||
std::is_same<math::uint3, T>::value ||
|
||||
std::is_same<math::uint4, T>::value ||
|
||||
std::is_same<math::float2, T>::value ||
|
||||
std::is_same<math::float3, T>::value ||
|
||||
std::is_same<math::float4, T>::value ||
|
||||
std::is_same<math::mat4f, T>::value ||
|
||||
// these types are slower as they need a layout conversion
|
||||
std::is_same<bool, T>::value ||
|
||||
std::is_same<math::bool2, T>::value ||
|
||||
std::is_same<math::bool3, T>::value ||
|
||||
std::is_same<math::bool4, T>::value ||
|
||||
std::is_same<math::mat3f, T>::value
|
||||
>::type;
|
||||
|
||||
/**
|
||||
* Creates a new MaterialInstance using another MaterialInstance as a template for initialization.
|
||||
* The new MaterialInstance is an instance of the same Material of the template instance and
|
||||
* must be destroyed just like any other MaterialInstance.
|
||||
*
|
||||
* @param other A MaterialInstance to use as a template for initializing a new instance
|
||||
* @param name A name for the new MaterialInstance or nullptr to use the template's name
|
||||
* @return A new MaterialInstance
|
||||
*/
|
||||
static MaterialInstance* duplicate(MaterialInstance const* other, const char* name = nullptr) noexcept;
|
||||
|
||||
/**
|
||||
* @return the Material associated with this instance
|
||||
*/
|
||||
Material const* getMaterial() const noexcept;
|
||||
|
||||
/**
|
||||
* @return the name associated with this instance
|
||||
*/
|
||||
const char* getName() const noexcept;
|
||||
|
||||
/**
|
||||
* Set a uniform by name
|
||||
*
|
||||
* @param name Name of the parameter as defined by Material. Cannot be nullptr.
|
||||
* @param value Value of the parameter to set.
|
||||
* @throws utils::PreConditionPanic if name doesn't exist or no-op if exceptions are disabled.
|
||||
*/
|
||||
template<typename T, typename = is_supported_parameter_t<T>>
|
||||
void setParameter(const char* name, T const& value) noexcept;
|
||||
|
||||
/**
|
||||
* Set a uniform array by name
|
||||
*
|
||||
* @param name Name of the parameter array as defined by Material. Cannot be nullptr.
|
||||
* @param values Array of values to set to the named parameter array.
|
||||
* @param count Size of the array to set.
|
||||
* @throws utils::PreConditionPanic if name doesn't exist or no-op if exceptions are disabled.
|
||||
*/
|
||||
template<typename T, typename = is_supported_parameter_t<T>>
|
||||
void setParameter(const char* name, const T* values, size_t count) noexcept;
|
||||
|
||||
/**
|
||||
* Set a texture as the named parameter
|
||||
*
|
||||
* @param name Name of the parameter as defined by Material. Cannot be nullptr.
|
||||
* @param texture Non nullptr Texture object pointer.
|
||||
* @param sampler Sampler parameters.
|
||||
* @throws utils::PreConditionPanic if name doesn't exist or no-op if exceptions are disabled.
|
||||
*/
|
||||
void setParameter(const char* name,
|
||||
Texture const* texture, TextureSampler const& sampler) noexcept;
|
||||
|
||||
/**
|
||||
* Set an RGB color as the named parameter.
|
||||
* A conversion might occur depending on the specified type
|
||||
*
|
||||
* @param name Name of the parameter as defined by Material. Cannot be nullptr.
|
||||
* @param type Whether the color value is encoded as Linear or sRGB.
|
||||
* @param color Array of read, green, blue channels values.
|
||||
* @throws utils::PreConditionPanic if name doesn't exist or no-op if exceptions are disabled.
|
||||
*/
|
||||
void setParameter(const char* name, RgbType type, math::float3 color) noexcept;
|
||||
|
||||
/**
|
||||
* Set an RGBA color as the named parameter.
|
||||
* A conversion might occur depending on the specified type
|
||||
*
|
||||
* @param name Name of the parameter as defined by Material. Cannot be nullptr.
|
||||
* @param type Whether the color value is encoded as Linear or sRGB/A.
|
||||
* @param color Array of read, green, blue and alpha channels values.
|
||||
* @throws utils::PreConditionPanic if name doesn't exist or no-op if exceptions are disabled.
|
||||
*/
|
||||
void setParameter(const char* name, RgbaType type, math::float4 color) noexcept;
|
||||
|
||||
/**
|
||||
* Set up a custom scissor rectangle; by default this encompasses the View.
|
||||
*
|
||||
* @param left left coordinate of the scissor box
|
||||
* @param bottom bottom coordinate of the scissor box
|
||||
* @param width width of the scissor box
|
||||
* @param height height of the scissor box
|
||||
*/
|
||||
void setScissor(uint32_t left, uint32_t bottom, uint32_t width, uint32_t height) noexcept;
|
||||
|
||||
/**
|
||||
* Returns the scissor rectangle to its default setting, which encompasses the View.
|
||||
*/
|
||||
void unsetScissor() noexcept;
|
||||
|
||||
/**
|
||||
* Sets a polygon offset that will be applied to all renderables drawn with this material
|
||||
* instance.
|
||||
*
|
||||
* The value of the offset is scale * dz + r * constant, where dz is the change in depth
|
||||
* relative to the screen area of the triangle, and r is the smallest value that is guaranteed
|
||||
* to produce a resolvable offset for a given implementation. This offset is added before the
|
||||
* depth test.
|
||||
*
|
||||
* @warning using a polygon offset other than zero has a significant negative performance
|
||||
* impact, as most implementations have to disable early depth culling. DO NOT USE unless
|
||||
* absolutely necessary.
|
||||
*
|
||||
* @param scale scale factor used to create a variable depth offset for each triangle
|
||||
* @param constant scale factor used to create a constant depth offset for each triangle
|
||||
*/
|
||||
void setPolygonOffset(float scale, float constant) noexcept;
|
||||
|
||||
/**
|
||||
* Overrides the minimum alpha value a fragment must have to not be discarded when the blend
|
||||
* mode is MASKED. Defaults to 0.4 if it has not been set in the parent Material. The specified
|
||||
* value should be between 0 and 1 and will be clamped if necessary.
|
||||
*/
|
||||
void setMaskThreshold(float threshold) 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.
|
||||
*/
|
||||
void setSpecularAntiAliasingVariance(float variance) 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.
|
||||
*/
|
||||
void setSpecularAntiAliasingThreshold(float threshold) noexcept;
|
||||
|
||||
/**
|
||||
* Enables or disables double-sided lighting if the parent Material has double-sided capability,
|
||||
* otherwise prints a warning. If double-sided lighting is enabled, backface culling is
|
||||
* automatically disabled.
|
||||
*/
|
||||
void setDoubleSided(bool doubleSided) noexcept;
|
||||
|
||||
/**
|
||||
* Overrides the default triangle culling state that was set on the material.
|
||||
*/
|
||||
void setCullingMode(CullingMode culling) noexcept;
|
||||
|
||||
/**
|
||||
* Overrides the default color-buffer write state that was set on the material.
|
||||
*/
|
||||
void setColorWrite(bool enable) noexcept;
|
||||
|
||||
/**
|
||||
* Overrides the default depth-buffer write state that was set on the material.
|
||||
*/
|
||||
void setDepthWrite(bool enable) noexcept;
|
||||
|
||||
/**
|
||||
* Overrides the default depth testing state that was set on the material.
|
||||
*/
|
||||
void setDepthCulling(bool enable) noexcept;
|
||||
};
|
||||
|
||||
} // namespace filament
|
||||
|
||||
#endif // TNT_FILAMENT_MATERIALINSTANCE_H
|
||||
175
ios/include/filament/RenderTarget.h
Normal file
175
ios/include/filament/RenderTarget.h
Normal file
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef TNT_FILAMENT_RENDERTARGET_H
|
||||
#define TNT_FILAMENT_RENDERTARGET_H
|
||||
|
||||
#include <filament/FilamentAPI.h>
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/TargetBufferInfo.h>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
namespace filament {
|
||||
|
||||
class FRenderTarget;
|
||||
|
||||
class Engine;
|
||||
class Texture;
|
||||
|
||||
/**
|
||||
* An offscreen render target that can be associated with a View and contains
|
||||
* weak references to a set of attached Texture objects.
|
||||
*
|
||||
* Clients are responsible for the lifetime of all associated Texture attachments.
|
||||
*
|
||||
* @see View
|
||||
*/
|
||||
class UTILS_PUBLIC RenderTarget : public FilamentAPI {
|
||||
struct BuilderDetails;
|
||||
|
||||
public:
|
||||
using CubemapFace = backend::TextureCubemapFace;
|
||||
|
||||
/** Minimum number of color attachment supported */
|
||||
static constexpr uint8_t MIN_SUPPORTED_COLOR_ATTACHMENTS_COUNT =
|
||||
backend::MRT::MIN_SUPPORTED_RENDER_TARGET_COUNT;
|
||||
|
||||
/** Maximum number of color attachment supported */
|
||||
static constexpr uint8_t MAX_SUPPORTED_COLOR_ATTACHMENTS_COUNT =
|
||||
backend::MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT;
|
||||
|
||||
/**
|
||||
* Attachment identifiers
|
||||
*/
|
||||
enum class AttachmentPoint : uint8_t {
|
||||
COLOR0 = 0, //!< identifies the 1st color attachment
|
||||
COLOR1 = 1, //!< identifies the 2nd color attachment
|
||||
COLOR2 = 2, //!< identifies the 3rd color attachment
|
||||
COLOR3 = 3, //!< identifies the 4th color attachment
|
||||
COLOR4 = 4, //!< identifies the 5th color attachment
|
||||
COLOR5 = 5, //!< identifies the 6th color attachment
|
||||
COLOR6 = 6, //!< identifies the 7th color attachment
|
||||
COLOR7 = 7, //!< identifies the 8th color attachment
|
||||
DEPTH = MAX_SUPPORTED_COLOR_ATTACHMENTS_COUNT, //!< identifies the depth attachment
|
||||
COLOR = COLOR0, //!< identifies the 1st color attachment
|
||||
};
|
||||
|
||||
//! Use Builder to construct a RenderTarget object instance
|
||||
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;
|
||||
|
||||
/**
|
||||
* Sets a texture to a given attachment point.
|
||||
*
|
||||
* All RenderTargets must have a non-null COLOR attachment.
|
||||
*
|
||||
* @param attachment The attachment point of the texture.
|
||||
* @param texture The associated texture object.
|
||||
* @return A reference to this Builder for chaining calls.
|
||||
*/
|
||||
Builder& texture(AttachmentPoint attachment, Texture* texture) noexcept;
|
||||
|
||||
/**
|
||||
* Sets the mipmap level for a given attachment point.
|
||||
*
|
||||
* @param attachment The attachment point of the texture.
|
||||
* @param level The associated mipmap level, 0 by default.
|
||||
* @return A reference to this Builder for chaining calls.
|
||||
*/
|
||||
Builder& mipLevel(AttachmentPoint attachment, uint8_t level) noexcept;
|
||||
|
||||
/**
|
||||
* Sets the cubemap face for a given attachment point.
|
||||
*
|
||||
* @param attachment The attachment point.
|
||||
* @param face The associated cubemap face.
|
||||
* @return A reference to this Builder for chaining calls.
|
||||
*/
|
||||
Builder& face(AttachmentPoint attachment, CubemapFace face) noexcept;
|
||||
|
||||
/**
|
||||
* Sets the layer for a given attachment point (for 3D textures).
|
||||
*
|
||||
* @param attachment The attachment point.
|
||||
* @param layer The associated cubemap layer.
|
||||
* @return A reference to this Builder for chaining calls.
|
||||
*/
|
||||
Builder& layer(AttachmentPoint attachment, uint32_t layer) noexcept;
|
||||
|
||||
/**
|
||||
* Creates the RenderTarget object and returns a pointer to it.
|
||||
*
|
||||
* @return pointer to the newly created object or nullptr if exceptions are disabled and
|
||||
* an error occurred.
|
||||
*/
|
||||
RenderTarget* build(Engine& engine);
|
||||
|
||||
private:
|
||||
friend class FRenderTarget;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the texture set on the given attachment point
|
||||
* @param attachment Attachment point
|
||||
* @return A Texture object or nullptr if no texture is set for this attachment point
|
||||
*/
|
||||
Texture* getTexture(AttachmentPoint attachment) const noexcept;
|
||||
|
||||
/**
|
||||
* Returns the mipmap level set on the given attachment point
|
||||
* @param attachment Attachment point
|
||||
* @return the mipmap level set on the given attachment point
|
||||
*/
|
||||
uint8_t getMipLevel(AttachmentPoint attachment) const noexcept;
|
||||
|
||||
/**
|
||||
* Returns the face of a cubemap set on the given attachment point
|
||||
* @param attachment Attachment point
|
||||
* @return A cubemap face identifier. This is only relevant if the attachment's texture is
|
||||
* a cubemap.
|
||||
*/
|
||||
CubemapFace getFace(AttachmentPoint attachment) const noexcept;
|
||||
|
||||
/**
|
||||
* Returns the texture-layer set on the given attachment point
|
||||
* @param attachment Attachment point
|
||||
* @return A texture layer. This is only relevant if the attachment's texture is a 3D texture.
|
||||
*/
|
||||
uint32_t getLayer(AttachmentPoint attachment) const noexcept;
|
||||
|
||||
/**
|
||||
* Returns the number of color attachments usable by this instance of Engine. This method is
|
||||
* guaranteed to return at least MIN_SUPPORTED_COLOR_ATTACHMENTS_COUNT and at most
|
||||
* MAX_SUPPORTED_COLOR_ATTACHMENTS_COUNT.
|
||||
* @return Number of color attachments usable in a render target.
|
||||
*/
|
||||
uint8_t getSupportedColorAttachmentsCount() const noexcept;
|
||||
};
|
||||
|
||||
} // namespace filament
|
||||
|
||||
#endif // TNT_FILAMENT_RENDERTARGET_H
|
||||
585
ios/include/filament/RenderableManager.h
Normal file
585
ios/include/filament/RenderableManager.h
Normal file
@@ -0,0 +1,585 @@
|
||||
/*
|
||||
* 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_FILAMENT_RENDERABLECOMPONENTMANAGER_H
|
||||
#define TNT_FILAMENT_RENDERABLECOMPONENTMANAGER_H
|
||||
|
||||
#include <filament/Box.h>
|
||||
#include <filament/FilamentAPI.h>
|
||||
#include <filament/MaterialEnums.h>
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/EntityInstance.h>
|
||||
|
||||
#include <math/mathfwd.h>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace utils {
|
||||
class Entity;
|
||||
} // namespace utils
|
||||
|
||||
namespace filament {
|
||||
|
||||
class BufferObject;
|
||||
class Engine;
|
||||
class IndexBuffer;
|
||||
class Material;
|
||||
class MaterialInstance;
|
||||
class Renderer;
|
||||
class SkinningBuffer;
|
||||
class VertexBuffer;
|
||||
|
||||
class FEngine;
|
||||
class FRenderPrimitive;
|
||||
class FRenderableManager;
|
||||
|
||||
/**
|
||||
* Factory and manager for \em renderables, which are entities that can be drawn.
|
||||
*
|
||||
* Renderables are bundles of \em primitives, each of which has its own geometry and material. All
|
||||
* primitives in a particular renderable share a set of rendering attributes, such as whether they
|
||||
* cast shadows or use vertex skinning.
|
||||
*
|
||||
* Usage example:
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* auto renderable = utils::EntityManager::get().create();
|
||||
*
|
||||
* RenderableManager::Builder(1)
|
||||
* .boundingBox({{ -1, -1, -1 }, { 1, 1, 1 }})
|
||||
* .material(0, matInstance)
|
||||
* .geometry(0, RenderableManager::PrimitiveType::TRIANGLES, vertBuffer, indBuffer, 0, 3)
|
||||
* .receiveShadows(false)
|
||||
* .build(engine, renderable);
|
||||
*
|
||||
* scene->addEntity(renderable);
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* To modify the state of an existing renderable, clients should first use RenderableManager
|
||||
* to get a temporary handle called an \em instance. The instance can then be used to get or set
|
||||
* the renderable's state. Please note that instances are ephemeral; clients should store entities,
|
||||
* not instances.
|
||||
*
|
||||
* - For details about constructing renderables, see RenderableManager::Builder.
|
||||
* - To associate a 4x4 transform with an entity, see TransformManager.
|
||||
* - To associate a human-readable label with an entity, see utils::NameComponentManager.
|
||||
*/
|
||||
class UTILS_PUBLIC RenderableManager : public FilamentAPI {
|
||||
struct BuilderDetails;
|
||||
|
||||
public:
|
||||
using Instance = utils::EntityInstance<RenderableManager>;
|
||||
using PrimitiveType = backend::PrimitiveType;
|
||||
|
||||
/**
|
||||
* Checks if the given entity already has a renderable component.
|
||||
*/
|
||||
bool hasComponent(utils::Entity e) const noexcept;
|
||||
|
||||
/**
|
||||
* Gets a temporary handle that can be used to access the renderable state.
|
||||
*
|
||||
* @return Non-zero handle if the entity has a renderable component, 0 otherwise.
|
||||
*/
|
||||
Instance getInstance(utils::Entity e) const noexcept;
|
||||
|
||||
/**
|
||||
* The transformation associated with a skinning joint.
|
||||
*
|
||||
* Clients can specify bones either using this quat-vec3 pair, or by using 4x4 matrices.
|
||||
*/
|
||||
struct Bone {
|
||||
math::quatf unitQuaternion = { 1, 0, 0, 0 };
|
||||
math::float3 translation = { 0, 0, 0 };
|
||||
float reserved = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds renderable components to entities using a builder pattern.
|
||||
*/
|
||||
class Builder : public BuilderBase<BuilderDetails> {
|
||||
friend struct BuilderDetails;
|
||||
public:
|
||||
enum Result { Error = -1, Success = 0 };
|
||||
|
||||
/**
|
||||
* Creates a builder for renderable components.
|
||||
*
|
||||
* @param count the number of primitives that will be supplied to the builder
|
||||
*
|
||||
* Note that builders typically do not have a long lifetime since clients should discard
|
||||
* them after calling build(). For a usage example, see RenderableManager.
|
||||
*/
|
||||
explicit Builder(size_t count) noexcept;
|
||||
|
||||
/*! \cond PRIVATE */
|
||||
Builder(Builder const& rhs) = delete;
|
||||
Builder(Builder&& rhs) noexcept;
|
||||
~Builder() noexcept;
|
||||
Builder& operator=(Builder& rhs) = delete;
|
||||
Builder& operator=(Builder&& rhs) noexcept;
|
||||
/*! \endcond */
|
||||
|
||||
/**
|
||||
* Specifies the geometry data for a primitive.
|
||||
*
|
||||
* Filament primitives must have an associated VertexBuffer and IndexBuffer. Typically, each
|
||||
* primitive is specified with a pair of daisy-chained calls: \c geometry(...) and \c
|
||||
* material(...).
|
||||
*
|
||||
* @param index zero-based index of the primitive, must be less than the count passed to Builder constructor
|
||||
* @param type specifies the topology of the primitive (e.g., \c RenderableManager::PrimitiveType::TRIANGLES)
|
||||
* @param vertices specifies the vertex buffer, which in turn specifies a set of attributes
|
||||
* @param indices specifies the index buffer (either u16 or u32)
|
||||
* @param offset specifies where in the index buffer to start reading (expressed as a number of indices)
|
||||
* @param minIndex specifies the minimum index contained in the index buffer
|
||||
* @param maxIndex specifies the maximum index contained in the index buffer
|
||||
* @param count number of indices to read (for triangles, this should be a multiple of 3)
|
||||
*/
|
||||
Builder& geometry(size_t index, PrimitiveType type, VertexBuffer* vertices, IndexBuffer* indices, size_t offset, size_t minIndex, size_t maxIndex, size_t count) noexcept;
|
||||
Builder& geometry(size_t index, PrimitiveType type, VertexBuffer* vertices, IndexBuffer* indices, size_t offset, size_t count) noexcept; //!< \overload
|
||||
Builder& geometry(size_t index, PrimitiveType type, VertexBuffer* vertices, IndexBuffer* indices) noexcept; //!< \overload
|
||||
|
||||
/**
|
||||
* Binds a material instance to the specified primitive.
|
||||
*
|
||||
* If no material is specified for a given primitive, Filament will fall back to a basic default material.
|
||||
*
|
||||
* @param index zero-based index of the primitive, must be less than the count passed to Builder constructor
|
||||
* @param materialInstance the material to bind
|
||||
*/
|
||||
Builder& material(size_t index, MaterialInstance const* materialInstance) noexcept;
|
||||
|
||||
/**
|
||||
* The axis-aligned bounding box of the renderable.
|
||||
*
|
||||
* This is an object-space AABB used for frustum culling. For skinning and morphing, this
|
||||
* should encompass all possible vertex positions. It is mandatory unless culling is
|
||||
* disabled for the renderable.
|
||||
*
|
||||
* \see computeAABB()
|
||||
*/
|
||||
Builder& boundingBox(const Box& axisAlignedBoundingBox) noexcept;
|
||||
|
||||
/**
|
||||
* Sets bits in a visibility mask. By default, this is 0x1.
|
||||
*
|
||||
* This feature provides a simple mechanism for hiding and showing groups of renderables
|
||||
* in a Scene. See View::setVisibleLayers().
|
||||
*
|
||||
* For example, to set bit 1 and reset bits 0 and 2 while leaving all other bits unaffected,
|
||||
* do: `builder.layerMask(7, 2)`.
|
||||
*
|
||||
* To change this at run time, see RenderableManager::setLayerMask.
|
||||
*
|
||||
* @param select the set of bits to affect
|
||||
* @param values the replacement values for the affected bits
|
||||
*/
|
||||
Builder& layerMask(uint8_t select, uint8_t values) noexcept;
|
||||
|
||||
/**
|
||||
* Provides coarse-grained control over draw order.
|
||||
*
|
||||
* In general Filament reserves the right to re-order renderables to allow for efficient
|
||||
* rendering. However clients can control ordering at a coarse level using \em priority.
|
||||
*
|
||||
* For example, this could be used to draw a semitransparent HUD, if a client wishes to
|
||||
* avoid using a separate View for the HUD. Note that priority is completely orthogonal to
|
||||
* Builder::layerMask, which merely controls visibility.
|
||||
*
|
||||
* \see Builder::blendOrder()
|
||||
*
|
||||
* The priority is clamped to the range [0..7], defaults to 4; 7 is lowest priority
|
||||
* (rendered last).
|
||||
*/
|
||||
Builder& priority(uint8_t priority) noexcept;
|
||||
|
||||
/**
|
||||
* Controls frustum culling, true by default.
|
||||
*
|
||||
* \note Do not confuse frustum culling with backface culling. The latter is controlled via
|
||||
* the material.
|
||||
*/
|
||||
Builder& culling(bool enable) noexcept;
|
||||
|
||||
/**
|
||||
* Enables or disables a light channel. Light channel 0 is enabled by default.
|
||||
*
|
||||
* @param channel Light channel to enable or disable, between 0 and 7.
|
||||
* @param enable Whether to enable or disable the light channel.
|
||||
*/
|
||||
Builder& lightChannel(unsigned int channel, bool enable = true) noexcept;
|
||||
|
||||
/**
|
||||
* Controls if this renderable casts shadows, false by default.
|
||||
*
|
||||
* If the View's shadow type is set to ShadowType::VSM, castShadows should only be disabled
|
||||
* if either is true:
|
||||
* - receiveShadows is also disabled
|
||||
* - the object is guaranteed to not cast shadows on itself or other objects (for example,
|
||||
* a ground plane)
|
||||
*/
|
||||
Builder& castShadows(bool enable) noexcept;
|
||||
|
||||
/**
|
||||
* Controls if this renderable receives shadows, true by default.
|
||||
*/
|
||||
Builder& receiveShadows(bool enable) noexcept;
|
||||
|
||||
/**
|
||||
* Controls if this renderable uses screen-space contact shadows. This is more
|
||||
* expensive but can improve the quality of shadows, especially in large scenes.
|
||||
* (off by default).
|
||||
*/
|
||||
Builder& screenSpaceContactShadows(bool enable) noexcept;
|
||||
|
||||
/**
|
||||
* Allows bones to be swapped out and shared using SkinningBuffer.
|
||||
*
|
||||
* If skinning buffer mode is enabled, clients must call setSkinningBuffer() rather than
|
||||
* setBones(). This allows sharing of data between renderables.
|
||||
*
|
||||
* @param enabled If true, enables buffer object mode. False by default.
|
||||
*/
|
||||
Builder& enableSkinningBuffers(bool enabled = true) noexcept;
|
||||
|
||||
/**
|
||||
* Enables GPU vertex skinning for up to 255 bones, 0 by default.
|
||||
*
|
||||
* Skinning Buffer mode must be enabled.
|
||||
*
|
||||
* Each vertex can be affected by up to 4 bones simultaneously. The attached
|
||||
* VertexBuffer must provide data in the \c BONE_INDICES slot (uvec4) and the
|
||||
* \c BONE_WEIGHTS slot (float4).
|
||||
*
|
||||
* See also RenderableManager::setSkinningBuffer() or SkinningBuffer::setBones(),
|
||||
* which can be called on a per-frame basis to advance the animation.
|
||||
*
|
||||
* @param skinningBuffer nullptr to disable, otherwise the SkinningBuffer to use
|
||||
* @param count 0 to disable, otherwise the number of bone transforms (up to 255)
|
||||
* @param offset offset in the SkinningBuffer
|
||||
*/
|
||||
Builder& skinning(SkinningBuffer* skinningBuffer, size_t count, size_t offset) noexcept;
|
||||
|
||||
|
||||
/**
|
||||
* Enables GPU vertex skinning for up to 255 bones, 0 by default.
|
||||
*
|
||||
* Skinning Buffer mode must be disabled.
|
||||
*
|
||||
* Each vertex can be affected by up to 4 bones simultaneously. The attached
|
||||
* VertexBuffer must provide data in the \c BONE_INDICES slot (uvec4) and the
|
||||
* \c BONE_WEIGHTS slot (float4).
|
||||
*
|
||||
* See also RenderableManager::setBones(), which can be called on a per-frame basis
|
||||
* to advance the animation.
|
||||
*
|
||||
* @param boneCount 0 to disable, otherwise the number of bone transforms (up to 255)
|
||||
* @param transforms the initial set of transforms (one for each bone)
|
||||
*/
|
||||
Builder& skinning(size_t boneCount, math::mat4f const* transforms) noexcept;
|
||||
Builder& skinning(size_t boneCount, Bone const* bones) noexcept; //!< \overload
|
||||
Builder& skinning(size_t boneCount) noexcept; //!< \overload
|
||||
|
||||
/**
|
||||
* 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
|
||||
* to advance the animation.
|
||||
*/
|
||||
Builder& morphing(bool enable) noexcept;
|
||||
|
||||
/**
|
||||
* Sets an ordering index for blended primitives that all live at the same Z value.
|
||||
*
|
||||
* @param primitiveIndex the primitive of interest
|
||||
* @param order draw order number (0 by default). Only the lowest 15 bits are used.
|
||||
*/
|
||||
Builder& blendOrder(size_t primitiveIndex, uint16_t order) noexcept;
|
||||
|
||||
/**
|
||||
* Adds the Renderable component to an entity.
|
||||
*
|
||||
* @param engine Reference to the filament::Engine to associate this Renderable with.
|
||||
* @param entity Entity to add the Renderable component to.
|
||||
* @return Success if the component was created successfully, Error otherwise.
|
||||
*
|
||||
* If exceptions are disabled and an error occurs, this function is a no-op.
|
||||
* Success can be checked by looking at the return value.
|
||||
*
|
||||
* If this component already exists on the given entity and the construction is successful,
|
||||
* it is first destroyed as if destroy(utils::Entity e) was called. In case of error,
|
||||
* the existing component is unmodified.
|
||||
*
|
||||
* @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.
|
||||
*/
|
||||
Result build(Engine& engine, utils::Entity entity);
|
||||
|
||||
private:
|
||||
friend class FEngine;
|
||||
friend class FRenderPrimitive;
|
||||
friend class FRenderableManager;
|
||||
struct Entry {
|
||||
VertexBuffer* vertices = nullptr;
|
||||
IndexBuffer* indices = nullptr;
|
||||
size_t offset = 0;
|
||||
size_t minIndex = 0;
|
||||
size_t maxIndex = 0;
|
||||
size_t count = 0;
|
||||
MaterialInstance const* materialInstance = nullptr;
|
||||
PrimitiveType type = PrimitiveType::TRIANGLES;
|
||||
uint16_t blendOrder = 0;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Destroys the renderable component in the given entity.
|
||||
*/
|
||||
void destroy(utils::Entity e) noexcept;
|
||||
|
||||
/**
|
||||
* Changes the bounding box used for frustum culling.
|
||||
*
|
||||
* \see Builder::boundingBox()
|
||||
* \see RenderableManager::getAxisAlignedBoundingBox()
|
||||
*/
|
||||
void setAxisAlignedBoundingBox(Instance instance, const Box& aabb) noexcept;
|
||||
|
||||
/**
|
||||
* Changes the visibility bits.
|
||||
*
|
||||
* \see Builder::layerMask()
|
||||
* \see View::setVisibleLayers().
|
||||
* \see RenderableManager::getLayerMask()
|
||||
*/
|
||||
void setLayerMask(Instance instance, uint8_t select, uint8_t values) noexcept;
|
||||
|
||||
/**
|
||||
* Changes the coarse-level draw ordering.
|
||||
*
|
||||
* \see Builder::priority().
|
||||
*/
|
||||
void setPriority(Instance instance, uint8_t priority) noexcept;
|
||||
|
||||
/**
|
||||
* Changes whether or not frustum culling is on.
|
||||
*
|
||||
* \see Builder::culling()
|
||||
*/
|
||||
void setCulling(Instance instance, bool enable) noexcept;
|
||||
|
||||
/**
|
||||
* Enables or disables a light channel.
|
||||
* Light channel 0 is enabled by default.
|
||||
*
|
||||
* \see Builder::lightChannel()
|
||||
*/
|
||||
void setLightChannel(Instance instance, unsigned int channel, bool enable) noexcept;
|
||||
|
||||
/**
|
||||
* Returns whether a light channel is enabled on a specified renderable.
|
||||
* @param instance Instance of the component obtained from getInstance().
|
||||
* @param channel Light channel to query
|
||||
* @return true if the light channel is enabled, false otherwise
|
||||
*/
|
||||
bool getLightChannel(Instance instance, unsigned int channel) const noexcept;
|
||||
|
||||
/**
|
||||
* Changes whether or not the renderable casts shadows.
|
||||
*
|
||||
* \see Builder::castShadows()
|
||||
*/
|
||||
void setCastShadows(Instance instance, bool enable) noexcept;
|
||||
|
||||
/**
|
||||
* Changes whether or not the renderable can receive shadows.
|
||||
*
|
||||
* \see Builder::receiveShadows()
|
||||
*/
|
||||
void setReceiveShadows(Instance instance, bool enable) noexcept;
|
||||
|
||||
/**
|
||||
* Changes whether or not the renderable can use screen-space contact shadows.
|
||||
*
|
||||
* \see Builder::screenSpaceContactShadows()
|
||||
*/
|
||||
void setScreenSpaceContactShadows(Instance instance, bool enable) noexcept;
|
||||
|
||||
/**
|
||||
* Checks if the renderable can cast shadows.
|
||||
*
|
||||
* \see Builder::castShadows().
|
||||
*/
|
||||
bool isShadowCaster(Instance instance) const noexcept;
|
||||
|
||||
/**
|
||||
* Checks if the renderable can receive shadows.
|
||||
*
|
||||
* \see Builder::receiveShadows().
|
||||
*/
|
||||
bool isShadowReceiver(Instance instance) const noexcept;
|
||||
|
||||
/**
|
||||
* Updates the bone transforms in the range [offset, offset + boneCount).
|
||||
* The bones must be pre-allocated using Builder::skinning().
|
||||
*/
|
||||
void setBones(Instance instance, Bone const* transforms, size_t boneCount = 1, size_t offset = 0) noexcept;
|
||||
void setBones(Instance instance, math::mat4f const* transforms, size_t boneCount = 1, size_t offset = 0) noexcept; //!< \overload
|
||||
|
||||
/**
|
||||
* Associates a SkinningBuffer to a renderable instance
|
||||
*/
|
||||
void setSkinningBuffer(Instance instance, SkinningBuffer* skinningBuffer,
|
||||
size_t count, size_t offset) noexcept;
|
||||
|
||||
/**
|
||||
* 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().
|
||||
*/
|
||||
void setMorphWeights(Instance instance, math::float4 const& weights) noexcept;
|
||||
|
||||
/**
|
||||
* Gets the bounding box used for frustum culling.
|
||||
*
|
||||
* \see Builder::boundingBox()
|
||||
* \see RenderableManager::setAxisAlignedBoundingBox()
|
||||
*/
|
||||
const Box& getAxisAlignedBoundingBox(Instance instance) const noexcept;
|
||||
|
||||
/**
|
||||
* Get the visibility bits.
|
||||
*
|
||||
* \see Builder::layerMask()
|
||||
* \see View::setVisibleLayers().
|
||||
* \see RenderableManager::getLayerMask()
|
||||
*/
|
||||
uint8_t getLayerMask(Instance instance) const noexcept;
|
||||
|
||||
/**
|
||||
* Gets the immutable number of primitives in the given renderable.
|
||||
*/
|
||||
size_t getPrimitiveCount(Instance instance) const noexcept;
|
||||
|
||||
/**
|
||||
* Changes the material instance binding for the given primitive.
|
||||
*
|
||||
* \see Builder::material()
|
||||
*/
|
||||
void setMaterialInstanceAt(Instance instance,
|
||||
size_t primitiveIndex, MaterialInstance const* materialInstance) noexcept;
|
||||
|
||||
/**
|
||||
* Retrieves the material instance that is bound to the given primitive.
|
||||
*/
|
||||
MaterialInstance* getMaterialInstanceAt(Instance instance, size_t primitiveIndex) const noexcept;
|
||||
|
||||
/**
|
||||
* Changes the geometry for the given primitive.
|
||||
*
|
||||
* \see Builder::geometry()
|
||||
*/
|
||||
void setGeometryAt(Instance instance, size_t primitiveIndex,
|
||||
PrimitiveType type, VertexBuffer* vertices, IndexBuffer* indices,
|
||||
size_t offset, size_t count) noexcept;
|
||||
|
||||
/**
|
||||
* Changes the active range of indices or topology for the given primitive.
|
||||
*
|
||||
* \see Builder::geometry()
|
||||
*/
|
||||
void setGeometryAt(Instance instance, size_t primitiveIndex,
|
||||
PrimitiveType type, size_t offset, size_t count) noexcept;
|
||||
|
||||
/**
|
||||
* Changes the ordering index for blended primitives that all live at the same Z value.
|
||||
*
|
||||
* \see Builder::blendOrder()
|
||||
*
|
||||
* @param instance the renderable of interest
|
||||
* @param primitiveIndex the primitive of interest
|
||||
* @param order draw order number (0 by default). Only the lowest 15 bits are used.
|
||||
*/
|
||||
void setBlendOrderAt(Instance instance, size_t primitiveIndex, uint16_t order) noexcept;
|
||||
|
||||
/**
|
||||
* Retrieves the set of enabled attribute slots in the given primitive's VertexBuffer.
|
||||
*/
|
||||
AttributeBitset getEnabledAttributesAt(Instance instance, size_t primitiveIndex) const noexcept;
|
||||
|
||||
/*! \cond PRIVATE */
|
||||
template<typename T>
|
||||
struct is_supported_vector_type {
|
||||
using type = typename std::enable_if<
|
||||
std::is_same<math::float4, T>::value ||
|
||||
std::is_same<math::half4, T>::value ||
|
||||
std::is_same<math::float3, T>::value ||
|
||||
std::is_same<math::half3, T>::value
|
||||
>::type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct is_supported_index_type {
|
||||
using type = typename std::enable_if<
|
||||
std::is_same<uint16_t, T>::value ||
|
||||
std::is_same<uint32_t, T>::value
|
||||
>::type;
|
||||
};
|
||||
/*! \endcond */
|
||||
|
||||
/**
|
||||
* Utility method that computes the axis-aligned bounding box from a set of vertices.
|
||||
*
|
||||
* - The index type must be \c uint16_t or \c uint32_t.
|
||||
* - The vertex type must be \c float4, \c half4, \c float3, or \c half3.
|
||||
* - For 4-component vertices, the w component is ignored (implicitly replaced with 1.0).
|
||||
*/
|
||||
template<typename VECTOR, typename INDEX,
|
||||
typename = typename is_supported_vector_type<VECTOR>::type,
|
||||
typename = typename is_supported_index_type<INDEX>::type>
|
||||
static Box computeAABB(VECTOR const* vertices, INDEX const* indices, size_t count,
|
||||
size_t stride = sizeof(VECTOR)) noexcept;
|
||||
};
|
||||
|
||||
template<typename VECTOR, typename INDEX, typename, typename>
|
||||
Box RenderableManager::computeAABB(VECTOR const* vertices, INDEX const* indices, size_t count,
|
||||
size_t stride) noexcept {
|
||||
math::float3 bmin(std::numeric_limits<float>::max());
|
||||
math::float3 bmax(std::numeric_limits<float>::lowest());
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
VECTOR const* p = reinterpret_cast<VECTOR const*>(
|
||||
(char const*)vertices + indices[i] * stride);
|
||||
const math::float3 v(p->x, p->y, p->z);
|
||||
bmin = min(bmin, v);
|
||||
bmax = max(bmax, v);
|
||||
}
|
||||
return Box().set(bmin, bmax);
|
||||
}
|
||||
|
||||
} // namespace filament
|
||||
|
||||
#endif // TNT_FILAMENT_RENDERABLECOMPONENTMANAGER_H
|
||||
540
ios/include/filament/Renderer.h
Normal file
540
ios/include/filament/Renderer.h
Normal file
@@ -0,0 +1,540 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef TNT_FILAMENT_RENDERER_H
|
||||
#define TNT_FILAMENT_RENDERER_H
|
||||
|
||||
#include <filament/FilamentAPI.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <backend/PresentCallable.h>
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
#include <math/vec4.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace filament {
|
||||
|
||||
class Engine;
|
||||
class RenderTarget;
|
||||
class SwapChain;
|
||||
class View;
|
||||
class Viewport;
|
||||
|
||||
namespace backend {
|
||||
class PixelBufferDescriptor;
|
||||
} // namespace backend
|
||||
|
||||
/**
|
||||
* A Renderer instance represents an operating system's window.
|
||||
*
|
||||
* Typically, applications create a Renderer per window. The Renderer generates drawing commands
|
||||
* for the render thread and manages frame latency.
|
||||
*
|
||||
* A Renderer generates drawing commands from a View, itself containing a Scene description.
|
||||
*
|
||||
* Creation and Destruction
|
||||
* ========================
|
||||
*
|
||||
* A Renderer is created using Engine.createRenderer() and destroyed using
|
||||
* Engine.destroy(const Renderer*).
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* #include <filament/Renderer.h>
|
||||
* #include <filament/Engine.h>
|
||||
* using namespace filament;
|
||||
*
|
||||
* Engine* engine = Engine::create();
|
||||
*
|
||||
* Renderer* renderer = engine->createRenderer();
|
||||
* engine->destroy(&renderer);
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* @see Engine, View
|
||||
*/
|
||||
class UTILS_PUBLIC Renderer : public FilamentAPI {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Use DisplayInfo to set important Display properties. This is used to achieve correct
|
||||
* frame pacing and dynamic resolution scaling.
|
||||
*/
|
||||
struct DisplayInfo {
|
||||
// refresh-rate of the display in Hz. set to 0 for offscreen or turn off frame-pacing.
|
||||
float refreshRate = 60.0f;
|
||||
|
||||
// how far in advance a buffer must be queued for presentation at a given time in ns
|
||||
uint64_t presentationDeadlineNanos = 0;
|
||||
|
||||
// offset by which vsyncSteadyClockTimeNano provided in beginFrame() is offset in ns
|
||||
uint64_t vsyncOffsetNanos = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Use FrameRateOptions to set the desired frame rate and control how quickly the system
|
||||
* reacts to GPU load changes.
|
||||
*
|
||||
* interval: desired frame interval in multiple of the refresh period, set in DisplayInfo
|
||||
* (as 1 / DisplayInfo::refreshRate)
|
||||
*
|
||||
* The parameters below are relevant when some Views are using dynamic resolution scaling:
|
||||
*
|
||||
* headRoomRatio: additional headroom for the GPU as a ratio of the targetFrameTime.
|
||||
* Useful for taking into account constant costs like post-processing or
|
||||
* GPU drivers on different platforms.
|
||||
* history: History size. higher values, tend to filter more (clamped to 30)
|
||||
* 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
|
||||
* needed to reach 64% of the target scale factor.
|
||||
* Higher values make the dynamic resolution react faster.
|
||||
*
|
||||
* @see View::DynamicResolutionOptions
|
||||
* @see Renderer::DisplayInfo
|
||||
*
|
||||
*/
|
||||
struct FrameRateOptions {
|
||||
float headRoomRatio = 0.0f; //!< additional headroom for the GPU
|
||||
float scaleRate = 0.125f; //!< rate at which the system reacts to load changes
|
||||
uint8_t history = 3; //!< history size
|
||||
uint8_t interval = 1; //!< desired frame interval in unit of 1.0 / DisplayInfo::refreshRate
|
||||
};
|
||||
|
||||
/**
|
||||
* ClearOptions are used at the beginning of a frame to clear or retain the SwapChain content.
|
||||
*/
|
||||
struct ClearOptions {
|
||||
/** Color to use to clear the SwapChain */
|
||||
math::float4 clearColor = {};
|
||||
/**
|
||||
* Whether the SwapChain should be cleared using the clearColor. Use this if translucent
|
||||
* View will be drawn, for instance.
|
||||
*/
|
||||
bool clear = false;
|
||||
/**
|
||||
* Whether the SwapChain content should be discarded. clear implies discard. Set this
|
||||
* to false (along with clear to false as well) if the SwapChain already has content that
|
||||
* needs to be preserved
|
||||
*/
|
||||
bool discard = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Information about the display this Renderer is associated to. This information is needed
|
||||
* to accurately compute dynamic-resolution scaling and for frame-pacing.
|
||||
*/
|
||||
void setDisplayInfo(const DisplayInfo& info) noexcept;
|
||||
|
||||
/**
|
||||
* Set options controlling the desired frame-rate.
|
||||
*/
|
||||
void setFrameRateOptions(FrameRateOptions const& options) noexcept;
|
||||
|
||||
/**
|
||||
* Set ClearOptions which are used at the beginning of a frame to clear or retain the
|
||||
* SwapChain content.
|
||||
*/
|
||||
void setClearOptions(const ClearOptions& options);
|
||||
|
||||
/**
|
||||
* Get the Engine that created this Renderer.
|
||||
*
|
||||
* @return A pointer to the Engine instance this Renderer is associated to.
|
||||
*/
|
||||
Engine* getEngine() noexcept;
|
||||
|
||||
/**
|
||||
* Get the Engine that created this Renderer.
|
||||
*
|
||||
* @return A constant pointer to the Engine instance this Renderer is associated to.
|
||||
*/
|
||||
inline Engine const* getEngine() const noexcept {
|
||||
return const_cast<Renderer *>(this)->getEngine();
|
||||
}
|
||||
|
||||
/**
|
||||
* Flags used to configure the behavior of copyFrame().
|
||||
*
|
||||
* @see
|
||||
* copyFrame()
|
||||
*/
|
||||
using CopyFrameFlag = uint32_t;
|
||||
|
||||
/**
|
||||
* Indicates that the dstSwapChain passed into copyFrame() should be
|
||||
* committed after the frame has been copied.
|
||||
*
|
||||
* @see
|
||||
* copyFrame()
|
||||
*/
|
||||
static constexpr CopyFrameFlag COMMIT = 0x1;
|
||||
/**
|
||||
* Indicates that the presentation time should be set on the dstSwapChain
|
||||
* passed into copyFrame to the monotonic clock time when the frame is
|
||||
* copied.
|
||||
*
|
||||
* @see
|
||||
* copyFrame()
|
||||
*/
|
||||
static constexpr CopyFrameFlag SET_PRESENTATION_TIME = 0x2;
|
||||
/**
|
||||
* Indicates that the dstSwapChain passed into copyFrame() should be
|
||||
* cleared to black before the frame is copied into the specified viewport.
|
||||
*
|
||||
* @see
|
||||
* copyFrame()
|
||||
*/
|
||||
static constexpr CopyFrameFlag CLEAR = 0x4;
|
||||
|
||||
|
||||
/**
|
||||
* Set-up a frame for this Renderer.
|
||||
*
|
||||
* beginFrame() manages frame pacing, and returns whether or not a frame should be drawn. The
|
||||
* goal of this is to skip frames when the GPU falls behind in order to keep the frame
|
||||
* latency low.
|
||||
*
|
||||
* If a given frame takes too much time in the GPU, the CPU will get ahead of the GPU. The
|
||||
* display will draw the same frame twice producing a stutter. At this point, the CPU is
|
||||
* ahead of the GPU and depending on how many frames are buffered, latency increases.
|
||||
*
|
||||
* beginFrame() attempts to detect this situation and returns false in that case, indicating
|
||||
* to the caller to skip the current frame.
|
||||
*
|
||||
* When beginFrame() returns true, it is mandatory to render the frame and call endFrame().
|
||||
* However, when beginFrame() returns false, the caller has the choice to either skip the
|
||||
* frame and not call endFrame(), or proceed as though true was returned.
|
||||
*
|
||||
* @param vsyncSteadyClockTimeNano The time in nanosecond of when the current frame started,
|
||||
* or 0 if unknown. This value should be the timestamp of
|
||||
* the last h/w vsync. It is expressed in the
|
||||
* std::chrono::steady_clock time base.
|
||||
* @param swapChain A pointer to the SwapChain instance to use.
|
||||
*
|
||||
* @return
|
||||
* *false* the current frame should be skipped,
|
||||
* *true* the current frame must be drawn and endFrame() must be called.
|
||||
*
|
||||
* @remark
|
||||
* When skipping a frame, the whole frame is canceled, and endFrame() must not be called.
|
||||
*
|
||||
* @note
|
||||
* All calls to render() must happen *after* beginFrame().
|
||||
*
|
||||
* @see
|
||||
* endFrame()
|
||||
*/
|
||||
bool beginFrame(SwapChain* swapChain,
|
||||
uint64_t vsyncSteadyClockTimeNano = 0u);
|
||||
|
||||
/**
|
||||
* Render a View into this renderer's window.
|
||||
*
|
||||
* This is filament main rendering method, most of the CPU-side heavy lifting is performed
|
||||
* here. render() main function is to generate render commands which are asynchronously
|
||||
* executed by the Engine's render thread.
|
||||
*
|
||||
* render() generates commands for each of the following stages:
|
||||
*
|
||||
* 1. Shadow map pass, if needed (currently only a single shadow map is supported).
|
||||
* 2. Depth pre-pass.
|
||||
* 3. Color pass.
|
||||
* 4. Post-processing pass.
|
||||
*
|
||||
* A typical render loop looks like this:
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* #include <filament/Renderer.h>
|
||||
* #include <filament/View.h>
|
||||
* using namespace filament;
|
||||
*
|
||||
* void renderLoop(Renderer* renderer, SwapChain* swapChain) {
|
||||
* do {
|
||||
* // typically we wait for VSYNC and user input events
|
||||
* if (renderer->beginFrame(swapChain)) {
|
||||
* renderer->render(mView);
|
||||
* renderer->endFrame();
|
||||
* }
|
||||
* } while (!quit());
|
||||
* }
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
*
|
||||
* @param view A pointer to the view to render.
|
||||
*
|
||||
* @attention
|
||||
* render() must be called *after* beginFrame() and *before* endFrame().
|
||||
*
|
||||
* @note
|
||||
* render() must be called from the Engine's main thread (or external synchronization
|
||||
* must be provided). In particular, calls to render() on different Renderer instances
|
||||
* **must** be synchronized.
|
||||
*
|
||||
* @remark
|
||||
* render() perform potentially heavy computations and cannot be multi-threaded. However,
|
||||
* internally, render() is highly multi-threaded to both improve performance in mitigate
|
||||
* the call's latency.
|
||||
*
|
||||
* @remark
|
||||
* render() is typically called once per frame (but not necessarily).
|
||||
*
|
||||
* @see
|
||||
* beginFrame(), endFrame(), View
|
||||
*
|
||||
*/
|
||||
void render(View const* view);
|
||||
|
||||
/**
|
||||
* Copy the currently rendered view to the indicated swap chain, using the
|
||||
* indicated source and destination rectangle.
|
||||
*
|
||||
* @param dstSwapChain The swap chain into which the frame should be copied.
|
||||
* @param dstViewport The destination rectangle in which to draw the view.
|
||||
* @param srcViewport The source rectangle to be copied.
|
||||
* @param flags One or more CopyFrameFlag behavior configuration flags.
|
||||
*
|
||||
* @remark
|
||||
* copyFrame() should be called after a frame is rendered using render()
|
||||
* but before endFrame() is called.
|
||||
*/
|
||||
void copyFrame(SwapChain* dstSwapChain, Viewport const& dstViewport,
|
||||
Viewport const& srcViewport, uint32_t flags = 0);
|
||||
|
||||
/**
|
||||
* Reads back the content of the SwapChain associated with this Renderer.
|
||||
*
|
||||
* @param xoffset Left offset of the sub-region to read back.
|
||||
* @param yoffset Bottom offset of the sub-region to read back.
|
||||
* @param width Width of the sub-region to read back.
|
||||
* @param height Height of the sub-region to read back.
|
||||
* @param buffer Client-side buffer where the read-back will be written.
|
||||
*
|
||||
* The following formats are always supported:
|
||||
* - PixelBufferDescriptor::PixelDataFormat::RGBA
|
||||
* - PixelBufferDescriptor::PixelDataFormat::RGBA_INTEGER
|
||||
*
|
||||
* The following types are always supported:
|
||||
* - PixelBufferDescriptor::PixelDataType::UBYTE
|
||||
* - PixelBufferDescriptor::PixelDataType::UINT
|
||||
* - PixelBufferDescriptor::PixelDataType::INT
|
||||
* - PixelBufferDescriptor::PixelDataType::FLOAT
|
||||
*
|
||||
* Other combinations of format/type may be supported. If a combination is
|
||||
* not supported, this operation may fail silently. Use a DEBUG build
|
||||
* to get some logs about the failure.
|
||||
*
|
||||
*
|
||||
* Framebuffer as seen on User buffer (PixelBufferDescriptor&)
|
||||
* screen
|
||||
*
|
||||
* +--------------------+
|
||||
* | | .stride .alignment
|
||||
* | | ----------------------->-->
|
||||
* | | O----------------------+--+ low addresses
|
||||
* | | | | | |
|
||||
* | w | | | .top | |
|
||||
* | <---------> | | V | |
|
||||
* | +---------+ | | +---------+ | |
|
||||
* | | ^ | | ======> | | | | |
|
||||
* | x | h| | | |.left| | | |
|
||||
* +------>| v | | +---->| | | |
|
||||
* | +.........+ | | +.........+ | |
|
||||
* | ^ | | | |
|
||||
* | y | | +----------------------+--+ high addresses
|
||||
* O------------+-------+
|
||||
*
|
||||
*
|
||||
* Typically readPixels() will be called after render() and before endFrame().
|
||||
*
|
||||
* 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
|
||||
* after multiple calls to beginFrame(), render(), endFrame().
|
||||
*
|
||||
* It is also possible to use a Fence to wait for the read-back.
|
||||
*
|
||||
* @remark
|
||||
* readPixels() is intended for debugging and testing. It will impact performance significantly.
|
||||
*
|
||||
*/
|
||||
void readPixels(uint32_t xoffset, uint32_t yoffset, uint32_t width, uint32_t height,
|
||||
backend::PixelBufferDescriptor&& buffer);
|
||||
|
||||
/**
|
||||
* Finishes the current frame and schedules it for display.
|
||||
*
|
||||
* endFrame() schedules the current frame to be displayed on the Renderer's window.
|
||||
*
|
||||
* @note
|
||||
* All calls to render() must happen *before* endFrame(). endFrame() must be called if
|
||||
* beginFrame() returned true, otherwise, endFrame() must not be called unless the caller
|
||||
* ignored beginFrame()'s return value.
|
||||
*
|
||||
* @see
|
||||
* beginFrame()
|
||||
*/
|
||||
void endFrame();
|
||||
|
||||
|
||||
/**
|
||||
* Reads back the content of the provided RenderTarget.
|
||||
*
|
||||
* @param renderTarget RenderTarget to read back from.
|
||||
* @param xoffset Left offset of the sub-region to read back.
|
||||
* @param yoffset Bottom offset of the sub-region to read back.
|
||||
* @param width Width of the sub-region to read back.
|
||||
* @param height Height of the sub-region to read back.
|
||||
* @param buffer Client-side buffer where the read-back will be written.
|
||||
*
|
||||
* The following formats are always supported:
|
||||
* - PixelBufferDescriptor::PixelDataFormat::RGBA
|
||||
* - PixelBufferDescriptor::PixelDataFormat::RGBA_INTEGER
|
||||
*
|
||||
* The following types are always supported:
|
||||
* - PixelBufferDescriptor::PixelDataType::UBYTE
|
||||
* - PixelBufferDescriptor::PixelDataType::UINT
|
||||
* - PixelBufferDescriptor::PixelDataType::INT
|
||||
* - PixelBufferDescriptor::PixelDataType::FLOAT
|
||||
*
|
||||
* Other combinations of format/type may be supported. If a combination is
|
||||
* not supported, this operation may fail silently. Use a DEBUG build
|
||||
* to get some logs about the failure.
|
||||
*
|
||||
*
|
||||
* Framebuffer as seen on User buffer (PixelBufferDescriptor&)
|
||||
* screen
|
||||
*
|
||||
* +--------------------+
|
||||
* | | .stride .alignment
|
||||
* | | ----------------------->-->
|
||||
* | | O----------------------+--+ low addresses
|
||||
* | | | | | |
|
||||
* | w | | | .top | |
|
||||
* | <---------> | | V | |
|
||||
* | +---------+ | | +---------+ | |
|
||||
* | | ^ | | ======> | | | | |
|
||||
* | x | h| | | |.left| | | |
|
||||
* +------>| v | | +---->| | | |
|
||||
* | +.........+ | | +.........+ | |
|
||||
* | ^ | | | |
|
||||
* | y | | +----------------------+--+ high addresses
|
||||
* O------------+-------+
|
||||
*
|
||||
*
|
||||
* Typically readPixels() will be called after render() and before endFrame().
|
||||
*
|
||||
* 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
|
||||
* after multiple calls to beginFrame(), render(), endFrame().
|
||||
*
|
||||
* It is also possible to use a Fence to wait for the read-back.
|
||||
*
|
||||
* @remark
|
||||
* readPixels() is intended for debugging and testing. It will impact performance significantly.
|
||||
*
|
||||
*/
|
||||
void readPixels(RenderTarget* renderTarget,
|
||||
uint32_t xoffset, uint32_t yoffset, uint32_t width, uint32_t height,
|
||||
backend::PixelBufferDescriptor&& buffer);
|
||||
|
||||
/**
|
||||
* Render a standalone View into its associated RenderTarget
|
||||
*
|
||||
* This call is mostly equivalent to calling render(View*) inside a
|
||||
* beginFrame / endFrame block, but incurs less overhead. It can be used
|
||||
* as a poor man's compute API.
|
||||
*
|
||||
* @param view A pointer to the view to render. This View must have a RenderTarget associated
|
||||
* to it.
|
||||
*
|
||||
* @attention
|
||||
* renderStandaloneView() must be called outside of beginFrame() / endFrame().
|
||||
*
|
||||
* @note
|
||||
* renderStandaloneView() must be called from the Engine's main thread
|
||||
* (or external synchronization must be provided). In particular, calls to
|
||||
* renderStandaloneView() on different Renderer instances **must** be synchronized.
|
||||
*
|
||||
* @remark
|
||||
* renderStandaloneView() perform potentially heavy computations and cannot be multi-threaded.
|
||||
* However, internally, renderStandaloneView() is highly multi-threaded to both improve
|
||||
* performance in mitigate the call's latency.
|
||||
*/
|
||||
void renderStandaloneView(View const* view);
|
||||
|
||||
|
||||
/**
|
||||
* Returns the time in second of the last call to beginFrame(). This value is constant for all
|
||||
* views rendered during a frame. The epoch is set with resetUserTime().
|
||||
*
|
||||
* In materials, this value can be queried using `vec4 getUserTime()`. The value returned
|
||||
* is a highp vec4 encoded as follows:
|
||||
*
|
||||
* time.x = (float)Renderer.getUserTime();
|
||||
* time.y = Renderer.getUserTime() - time.x;
|
||||
*
|
||||
* It follows that the following invariants are true:
|
||||
*
|
||||
* (double)time.x + (double)time.y == Renderer.getUserTime()
|
||||
* time.x == (float)Renderer.getUserTime()
|
||||
*
|
||||
* This encoding allows the shader code to perform high precision (i.e. double) time
|
||||
* calculations when needed despite the lack of double precision in the shader, for e.g.:
|
||||
*
|
||||
* To compute (double)time * vertex in the material, use the following construct:
|
||||
*
|
||||
* vec3 result = time.x * vertex + time.y * vertex;
|
||||
*
|
||||
*
|
||||
* Most of the time, high precision computations are not required, but be aware that the
|
||||
* precision of time.x rapidly diminishes as time passes:
|
||||
*
|
||||
* time | precision
|
||||
* --------+----------
|
||||
* 16.7s | us
|
||||
* 4h39 | ms
|
||||
* 77h | 1/60s
|
||||
*
|
||||
*
|
||||
* In other words, it only possible to get microsecond accuracy for about 16s or millisecond
|
||||
* accuracy for just under 5h.
|
||||
*
|
||||
* This problem can be mitigated by calling resetUserTime(), or using high precision time as
|
||||
* described above.
|
||||
*
|
||||
* @return The time is seconds since resetUserTime() was last called.
|
||||
*
|
||||
* @see
|
||||
* resetUserTime()
|
||||
*/
|
||||
double getUserTime() const;
|
||||
|
||||
/**
|
||||
* Sets the user time epoch to now, i.e. resets the user time to zero.
|
||||
*
|
||||
* Use this method used to keep the precision of time high in materials, in practice it should
|
||||
* be called at least when the application is paused, e.g. Activity.onPause() in Android.
|
||||
*
|
||||
* @see
|
||||
* getUserTime()
|
||||
*/
|
||||
void resetUserTime();
|
||||
};
|
||||
|
||||
} // namespace filament
|
||||
|
||||
#endif // TNT_FILAMENT_RENDERER_H
|
||||
163
ios/include/filament/Scene.h
Normal file
163
ios/include/filament/Scene.h
Normal file
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef TNT_FILAMENT_SCENE_H
|
||||
#define TNT_FILAMENT_SCENE_H
|
||||
|
||||
#include <filament/FilamentAPI.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
namespace utils {
|
||||
class Entity;
|
||||
} // namespace utils
|
||||
|
||||
namespace filament {
|
||||
|
||||
class IndirectLight;
|
||||
class Skybox;
|
||||
|
||||
/**
|
||||
* A Scene is a flat container of Renderable and Light instances.
|
||||
*
|
||||
* A Scene doesn't provide a hierarchy of Renderable objects, i.e.: it's not a scene-graph.
|
||||
* However, it manages the list of objects to render and the list of lights. Renderable
|
||||
* and Light objects can be added or removed from a Scene at any time.
|
||||
*
|
||||
* A Renderable *must* be added to a Scene in order to be rendered, and the Scene must be
|
||||
* provided to a View.
|
||||
*
|
||||
*
|
||||
* Creation and Destruction
|
||||
* ========================
|
||||
*
|
||||
* A Scene is created using Engine.createScene() and destroyed using
|
||||
* Engine.destroy(const Scene*).
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* #include <filament/Scene.h>
|
||||
* #include <filament/Engine.h>
|
||||
* using namespace filament;
|
||||
*
|
||||
* Engine* engine = Engine::create();
|
||||
*
|
||||
* Scene* scene = engine->createScene();
|
||||
* engine->destroy(&scene);
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* @see View, Renderable, Light
|
||||
*/
|
||||
class UTILS_PUBLIC Scene : public FilamentAPI {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Sets the Skybox.
|
||||
*
|
||||
* The Skybox is drawn last and covers all pixels not touched by geometry.
|
||||
*
|
||||
* @param skybox The Skybox to use to fill untouched pixels, or nullptr to unset the Skybox.
|
||||
*/
|
||||
void setSkybox(Skybox* skybox) noexcept;
|
||||
|
||||
/**
|
||||
* Returns the Skybox associated with the Scene.
|
||||
*
|
||||
* @return The associated Skybox, or nullptr if there is none.
|
||||
*/
|
||||
Skybox* getSkybox() noexcept;
|
||||
|
||||
/**
|
||||
* Returns an immutable Skybox associated with the Scene.
|
||||
*
|
||||
* @return The associated Skybox, or nullptr if there is none.
|
||||
*/
|
||||
Skybox const* getSkybox() const noexcept;
|
||||
|
||||
/**
|
||||
* Set the IndirectLight to use when rendering the Scene.
|
||||
*
|
||||
* Currently, a Scene may only have a single IndirectLight. This call replaces the current
|
||||
* IndirectLight.
|
||||
*
|
||||
* @param ibl The IndirectLight to use when rendering the Scene or nullptr to unset.
|
||||
*/
|
||||
void setIndirectLight(IndirectLight const* ibl) noexcept;
|
||||
|
||||
/**
|
||||
* Adds an Entity to the Scene.
|
||||
*
|
||||
* @param entity The entity is ignored if it doesn't have a Renderable or Light component.
|
||||
*
|
||||
* \attention
|
||||
* A given Entity object can only be added once to a Scene.
|
||||
*
|
||||
*/
|
||||
void addEntity(utils::Entity entity);
|
||||
|
||||
/**
|
||||
* Adds a list of entities to the Scene.
|
||||
*
|
||||
* @param entities Array containing entities to add to the scene.
|
||||
* @param count Size of the entity array.
|
||||
*/
|
||||
void addEntities(const utils::Entity* entities, size_t count);
|
||||
|
||||
/**
|
||||
* Removes the Renderable from the Scene.
|
||||
*
|
||||
* @param entity The Entity to remove from the Scene. If the specified
|
||||
* \p entity doesn't exist, this call is ignored.
|
||||
*/
|
||||
void remove(utils::Entity entity);
|
||||
|
||||
/**
|
||||
* Removes a list of entities to the Scene.
|
||||
*
|
||||
* This is equivalent to calling remove in a loop.
|
||||
* If any of the specified entities do not exist in the scene, they are skipped.
|
||||
*
|
||||
* @param entities Array containing entities to remove from the scene.
|
||||
* @param count Size of the entity array.
|
||||
*/
|
||||
void removeEntities(const utils::Entity* entities, size_t count);
|
||||
|
||||
/**
|
||||
* Returns the number of Renderable objects in the Scene.
|
||||
*
|
||||
* @return number of Renderable objects in the Scene.
|
||||
*/
|
||||
size_t getRenderableCount() const noexcept;
|
||||
|
||||
/**
|
||||
* Returns the total number of Light objects in the Scene.
|
||||
*
|
||||
* @return The total number of Light objects in the Scene.
|
||||
*/
|
||||
size_t getLightCount() const noexcept;
|
||||
|
||||
/**
|
||||
* Returns true if the given entity is in the Scene.
|
||||
*
|
||||
* @return Whether the given entity is in the Scene.
|
||||
*/
|
||||
bool hasEntity(utils::Entity entity) const noexcept;
|
||||
};
|
||||
|
||||
} // namespace filament
|
||||
|
||||
#endif // TNT_FILAMENT_SCENE_H
|
||||
119
ios/include/filament/SkinningBuffer.h
Normal file
119
ios/include/filament/SkinningBuffer.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_SKINNINGBUFFER_H
|
||||
#define TNT_FILAMENT_SKINNINGBUFFER_H
|
||||
|
||||
#include <filament/FilamentAPI.h>
|
||||
|
||||
#include <filament/RenderableManager.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <math/mathfwd.h>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
namespace filament {
|
||||
|
||||
/**
|
||||
* SkinningBuffer is used to hold skinning data (bones). It is a simple wraper around
|
||||
* a structured UBO.
|
||||
*/
|
||||
class UTILS_PUBLIC SkinningBuffer : 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 skinning buffer in bones.
|
||||
*
|
||||
* Due to limitation in the GLSL, the SkinningBuffer must always by a multiple of
|
||||
* 256, this adjustment is done automatically, but can cause
|
||||
* some memory overhead. This memory overhead can be mitigated by using the same
|
||||
* SkinningBuffer to store the bone information for multiple RenderPrimitives.
|
||||
*
|
||||
* @param boneCount Number of bones the skinning buffer can hold.
|
||||
* @return A reference to this Builder for chaining calls.
|
||||
*/
|
||||
Builder& boneCount(uint32_t boneCount) noexcept;
|
||||
|
||||
/**
|
||||
* The new buffer is created with identity bones
|
||||
* @param initialize true to initializing the buffer, false to not.
|
||||
* @return A reference to this Builder for chaining calls.
|
||||
*/
|
||||
Builder& initialize(bool initialize = true) noexcept;
|
||||
|
||||
/**
|
||||
* Creates the SkinningBuffer object and returns a pointer to it.
|
||||
*
|
||||
* @param engine Reference to the filament::Engine to associate this SkinningBuffer 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.
|
||||
*
|
||||
* @see SkinningBuffer::setBones
|
||||
*/
|
||||
SkinningBuffer* build(Engine& engine);
|
||||
private:
|
||||
friend class FSkinningBuffer;
|
||||
};
|
||||
|
||||
/**
|
||||
* Updates the bone transforms in the range [offset, offset + count).
|
||||
* @param engine Reference to the filament::Engine to associate this SkinningBuffer with.
|
||||
* @param transforms pointer to at least count Bone
|
||||
* @param count number of Bone elements in transforms
|
||||
* @param offset offset in elements (not bytes) in the SkinningBuffer (not in transforms)
|
||||
*/
|
||||
void setBones(Engine& engine, RenderableManager::Bone const* transforms,
|
||||
size_t count, size_t offset = 0);
|
||||
|
||||
/**
|
||||
* Updates the bone transforms in the range [offset, offset + count).
|
||||
* @param engine Reference to the filament::Engine to associate this SkinningBuffer with.
|
||||
* @param transforms pointer to at least count mat4f
|
||||
* @param count number of mat4f elements in transforms
|
||||
* @param offset offset in elements (not bytes) in the SkinningBuffer (not in transforms)
|
||||
*/
|
||||
void setBones(Engine& engine, math::mat4f const* transforms,
|
||||
size_t count, size_t offset = 0);
|
||||
|
||||
/**
|
||||
* Returns the size of this SkinningBuffer in elements.
|
||||
* @return The number of bones the SkinningBuffer holds.
|
||||
*/
|
||||
size_t getBoneCount() const noexcept;
|
||||
};
|
||||
|
||||
} // namespace filament
|
||||
|
||||
#endif //TNT_FILAMENT_SKINNINGBUFFER_H
|
||||
181
ios/include/filament/Skybox.h
Normal file
181
ios/include/filament/Skybox.h
Normal file
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef TNT_FILAMENT_SKYBOX_H
|
||||
#define TNT_FILAMENT_SKYBOX_H
|
||||
|
||||
#include <filament/FilamentAPI.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <math/mathfwd.h>
|
||||
|
||||
namespace filament {
|
||||
|
||||
class FSkybox;
|
||||
|
||||
class Engine;
|
||||
class Texture;
|
||||
|
||||
/**
|
||||
* Skybox
|
||||
*
|
||||
* When added to a Scene, the Skybox fills all untouched pixels.
|
||||
*
|
||||
* Creation and destruction
|
||||
* ========================
|
||||
*
|
||||
* A Skybox object is created using the Skybox::Builder and destroyed by calling
|
||||
* Engine::destroy(const Skybox*).
|
||||
*
|
||||
* ~~~~~~~~~~~{.cpp}
|
||||
* filament::Engine* engine = filament::Engine::create();
|
||||
*
|
||||
* filament::IndirectLight* skybox = filament::Skybox::Builder()
|
||||
* .environment(cubemap)
|
||||
* .build(*engine);
|
||||
*
|
||||
* engine->destroy(skybox);
|
||||
* ~~~~~~~~~~~
|
||||
*
|
||||
*
|
||||
* @note
|
||||
* Currently only Texture based sky boxes are supported.
|
||||
*
|
||||
* @see Scene, IndirectLight
|
||||
*/
|
||||
class UTILS_PUBLIC Skybox : public FilamentAPI {
|
||||
struct BuilderDetails;
|
||||
|
||||
public:
|
||||
//! Use Builder to construct an Skybox object instance
|
||||
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;
|
||||
|
||||
/**
|
||||
* Set the environment map (i.e. the skybox content).
|
||||
*
|
||||
* The Skybox is rendered as though it were an infinitely large cube with the camera
|
||||
* inside it. This means that the cubemap which is mapped onto the cube's exterior
|
||||
* will appear mirrored. This follows the OpenGL conventions.
|
||||
*
|
||||
* The cmgen tool generates reflection maps by default which are therefore ideal to use
|
||||
* as skyboxes.
|
||||
*
|
||||
* @param cubemap This Texture must be a cube map.
|
||||
*
|
||||
* @return This Builder, for chaining calls.
|
||||
*
|
||||
* @see Texture
|
||||
*/
|
||||
Builder& environment(Texture* cubemap) noexcept;
|
||||
|
||||
/**
|
||||
* Indicates whether the sun should be rendered. The sun can only be
|
||||
* rendered if there is at least one light of type SUN in the scene.
|
||||
* The default value is false.
|
||||
*
|
||||
* @param show True if the sun should be rendered, false otherwise
|
||||
*
|
||||
* @return This Builder, for chaining calls.
|
||||
*/
|
||||
Builder& showSun(bool show) noexcept;
|
||||
|
||||
/**
|
||||
* Skybox intensity when no IndirectLight is set on the Scene.
|
||||
*
|
||||
* This call is ignored when an IndirectLight is set on the Scene, and the intensity
|
||||
* of the IndirectLight is used instead.
|
||||
*
|
||||
* @param envIntensity Scale factor applied to the skybox texel values such that
|
||||
* the result is in lux, or lumen/m^2 (default = 30000)
|
||||
*
|
||||
* @return This Builder, for chaining calls.
|
||||
*
|
||||
* @see IndirectLight::Builder::intensity
|
||||
*/
|
||||
Builder& intensity(float envIntensity) noexcept;
|
||||
|
||||
/**
|
||||
* Sets the skybox to a constant color. Default is opaque black.
|
||||
*
|
||||
* Ignored if an environment is set.
|
||||
*
|
||||
* @param color
|
||||
*
|
||||
* @return This Builder, for chaining calls.
|
||||
*/
|
||||
Builder& color(math::float4 color) noexcept;
|
||||
|
||||
/**
|
||||
* Creates the Skybox object and returns a pointer to it.
|
||||
*
|
||||
* @param engine Reference to the filament::Engine to associate this Skybox with.
|
||||
*
|
||||
* @return pointer to the newly created object, or nullptr if the light couldn't be created.
|
||||
*/
|
||||
Skybox* build(Engine& engine);
|
||||
|
||||
private:
|
||||
friend class FSkybox;
|
||||
};
|
||||
|
||||
void setColor(math::float4 color) noexcept;
|
||||
|
||||
/**
|
||||
* Sets bits in a visibility mask. By default, this is 0x1.
|
||||
*
|
||||
* This provides a simple mechanism for hiding or showing this Skybox in a Scene.
|
||||
*
|
||||
* @see View::setVisibleLayers().
|
||||
*
|
||||
* For example, to set bit 1 and reset bits 0 and 2 while leaving all other bits unaffected,
|
||||
* call: `setLayerMask(7, 2)`.
|
||||
*
|
||||
* @param select the set of bits to affect
|
||||
* @param values the replacement values for the affected bits
|
||||
*/
|
||||
void setLayerMask(uint8_t select, uint8_t values) noexcept;
|
||||
|
||||
/**
|
||||
* @return the visibility mask bits
|
||||
*/
|
||||
uint8_t getLayerMask() const noexcept;
|
||||
|
||||
/**
|
||||
* Returns the skybox's intensity in lux, or lumen/m^2.
|
||||
*/
|
||||
float getIntensity() const noexcept;
|
||||
|
||||
/**
|
||||
* @return the associated texture, or null if it does not exist
|
||||
*/
|
||||
Texture const* getTexture() const noexcept;
|
||||
};
|
||||
|
||||
} // namespace filament
|
||||
|
||||
#endif // TNT_FILAMENT_SKYBOX_H
|
||||
281
ios/include/filament/Stream.h
Normal file
281
ios/include/filament/Stream.h
Normal file
@@ -0,0 +1,281 @@
|
||||
/*
|
||||
* 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_FILAMENT_STREAM_H
|
||||
#define TNT_FILAMENT_STREAM_H
|
||||
|
||||
#include <filament/FilamentAPI.h>
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
#include <backend/PixelBufferDescriptor.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
namespace filament {
|
||||
|
||||
class FStream;
|
||||
|
||||
class Engine;
|
||||
|
||||
/**
|
||||
* Stream is used to attach a video stream to a Filament `Texture`.
|
||||
*
|
||||
* Note that the `Stream` class is fairly Android centric. It supports three different
|
||||
* configurations:
|
||||
*
|
||||
* - TEXTURE_ID...takes an OpenGL texture ID and incurs a copy
|
||||
* - ACQUIRED.....connects to an Android AHardwareBuffer
|
||||
* - NATIVE.......connects to an Android SurfaceTexture
|
||||
*
|
||||
* Before explaining these different configurations, let's review the high-level structure of an AR
|
||||
* or video application that uses Filament:
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* while (true) {
|
||||
*
|
||||
* // Misc application work occurs here, such as:
|
||||
* // - Writing the image data for a video frame into a Stream
|
||||
* // - Moving the Filament Camera
|
||||
*
|
||||
* if (renderer->beginFrame(swapChain)) {
|
||||
* renderer->render(view);
|
||||
* renderer->endFrame();
|
||||
* }
|
||||
* }
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* Let's say that the video image data at the time of a particular invocation of `beginFrame`
|
||||
* becomes visible to users at time A. The 3D scene state (including the camera) at the time of
|
||||
* that same invocation becomes apparent to users at time B.
|
||||
*
|
||||
* - If time A matches time B, we say that the stream is \em{synchronized}.
|
||||
* - Filament invokes low-level graphics commands on the \em{driver thread}.
|
||||
* - The thread that calls `beginFrame` is called the \em{main thread}.
|
||||
*
|
||||
* The TEXTURE_ID configuration achieves synchronization automatically. In this mode, Filament
|
||||
* performs a copy on the main thread during `beginFrame` by blitting the external image into
|
||||
* an internal round-robin queue of images. This copy has a run-time cost.
|
||||
*
|
||||
* For ACQUIRED streams, there is no need to perform the copy because Filament explictly acquires
|
||||
* the stream, then releases it later via a callback function. This configuration is especially
|
||||
* useful when the Vulkan backend is enabled.
|
||||
*
|
||||
* For NATIVE streams, Filament does not make any synchronization guarantee. However they are simple
|
||||
* to use and do not incur a copy. These are often appropriate in video applications.
|
||||
*
|
||||
* Please see `sample-stream-test` and `sample-hello-camera` for usage examples.
|
||||
*
|
||||
* @see backend::StreamType
|
||||
* @see Texture#setExternalStream
|
||||
* @see Engine#destroyStream
|
||||
*/
|
||||
class UTILS_PUBLIC Stream : public FilamentAPI {
|
||||
struct BuilderDetails;
|
||||
|
||||
public:
|
||||
using Callback = backend::StreamCallback;
|
||||
using StreamType = backend::StreamType;
|
||||
|
||||
/**
|
||||
* Constructs a Stream object instance.
|
||||
*
|
||||
* By default, Stream objects are ACQUIRED and must have external images pushed to them via
|
||||
* <pre>Stream::setAcquiredImage</pre>.
|
||||
*
|
||||
* To create a NATIVE or TEXTURE_ID stream, call one of the <pre>stream</pre> methods
|
||||
* on the builder.
|
||||
*/
|
||||
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;
|
||||
|
||||
/**
|
||||
* Creates a NATIVE stream. Native streams can sample data directly from an
|
||||
* opaque platform object such as a SurfaceTexture on Android.
|
||||
*
|
||||
* @param stream An opaque native stream handle. e.g.: on Android this is an
|
||||
* `android/graphics/SurfaceTexture` JNI jobject. The wrap mode must
|
||||
* be CLAMP_TO_EDGE.
|
||||
*
|
||||
* @return This Builder, for chaining calls.
|
||||
*/
|
||||
Builder& stream(void* stream) noexcept;
|
||||
|
||||
/**
|
||||
* Creates a TEXTURE_ID stream. This will sample data from the supplied
|
||||
* external texture and copy it into an internal private texture.
|
||||
*
|
||||
* @param externalTextureId An opaque texture id (typically a GLuint created with glGenTextures)
|
||||
* In a context shared with filament. In that case this texture's
|
||||
* target must be GL_TEXTURE_EXTERNAL_OES and the wrap mode must
|
||||
* be CLAMP_TO_EDGE.
|
||||
*
|
||||
* @return This Builder, for chaining calls.
|
||||
*
|
||||
* @see Texture::setExternalStream()
|
||||
* @deprecated this method existed only for ARCore which doesn't need this anymore, use Texture::import() instead.
|
||||
*/
|
||||
UTILS_DEPRECATED
|
||||
Builder& stream(intptr_t externalTextureId) noexcept;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param width initial width of the incoming stream. Whether this value is used is
|
||||
* stream dependent. On Android, it must be set when using
|
||||
* Builder::stream(long externalTextureId).
|
||||
*
|
||||
* @return This Builder, for chaining calls.
|
||||
*/
|
||||
Builder& width(uint32_t width) noexcept;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param height initial height of the incoming stream. Whether this value is used is
|
||||
* stream dependent. On Android, it must be set when using
|
||||
* Builder::stream(long externalTextureId).
|
||||
*
|
||||
* @return This Builder, for chaining calls.
|
||||
*/
|
||||
Builder& height(uint32_t height) noexcept;
|
||||
|
||||
/**
|
||||
* Creates the Stream object and returns a pointer to it.
|
||||
*
|
||||
* @param engine Reference to the filament::Engine to associate this Stream with.
|
||||
*
|
||||
* @return pointer to the newly created object, or nullptr if the stream couldn't be created.
|
||||
*/
|
||||
Stream* build(Engine& engine);
|
||||
|
||||
private:
|
||||
friend class FStream;
|
||||
};
|
||||
|
||||
/**
|
||||
* Indicates whether this stream is a NATIVE stream, TEXTURE_ID stream, or ACQUIRED stream.
|
||||
*/
|
||||
StreamType getStreamType() const noexcept;
|
||||
|
||||
/**
|
||||
* Updates an ACQUIRED stream with an image that is guaranteed to be used in the next frame.
|
||||
*
|
||||
* This method tells Filament to immediately "acquire" the image and trigger a callback
|
||||
* when it is done with it. This should be called by the user outside of beginFrame / endFrame,
|
||||
* and should be called only once per frame. If the user pushes images to the same stream
|
||||
* multiple times in a single frame, only the final image is honored, but all callbacks are
|
||||
* invoked.
|
||||
*
|
||||
* This method should be called on the same thread that calls Renderer::beginFrame, which is
|
||||
* also where the callback is invoked. This method can only be used for streams that were
|
||||
* constructed without calling the `stream` method on the builder.
|
||||
*
|
||||
* @see Stream for more information about NATIVE, TEXTURE_ID, and ACQUIRED configurations.
|
||||
*
|
||||
* @param image Pointer to AHardwareBuffer, casted to void* since this is a public header.
|
||||
* @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, Callback callback, void* userdata) noexcept;
|
||||
|
||||
/**
|
||||
* Updates the size of the incoming stream. Whether this value is used is
|
||||
* stream dependent. On Android, it must be set when using
|
||||
* Builder::stream(long externalTextureId).
|
||||
*
|
||||
* @param width new width of the incoming stream
|
||||
* @param height new height of the incoming stream
|
||||
*/
|
||||
void setDimensions(uint32_t width, uint32_t height) noexcept;
|
||||
|
||||
/**
|
||||
* Read-back the content of the last frame of a Stream since the last call to
|
||||
* Renderer.beginFrame().
|
||||
*
|
||||
* The Stream must be of type externalTextureId. This function is a no-op otherwise.
|
||||
*
|
||||
* @param xoffset Left offset of the sub-region to read back.
|
||||
* @param yoffset Bottom offset of the sub-region to read back.
|
||||
* @param width Width of the sub-region to read back.
|
||||
* @param height Height of the sub-region to read back.
|
||||
* @param buffer Client-side buffer where the read-back will be written.
|
||||
*
|
||||
* The following format are always supported:
|
||||
* - PixelBufferDescriptor::PixelDataFormat::RGBA
|
||||
* - PixelBufferDescriptor::PixelDataFormat::RGBA_INTEGER
|
||||
*
|
||||
* The following types are always supported:
|
||||
* - PixelBufferDescriptor::PixelDataType::UBYTE
|
||||
* - PixelBufferDescriptor::PixelDataType::UINT
|
||||
* - PixelBufferDescriptor::PixelDataType::INT
|
||||
* - PixelBufferDescriptor::PixelDataType::FLOAT
|
||||
*
|
||||
* Other combination of format/type may be supported. If a combination is
|
||||
* not supported, this operation may fail silently. Use a DEBUG build
|
||||
* to get some logs about the failure.
|
||||
*
|
||||
* Stream buffer User buffer (PixelBufferDescriptor&)
|
||||
* +--------------------+
|
||||
* | | .stride .alignment
|
||||
* | | ----------------------->-->
|
||||
* | | O----------------------+--+ low addresses
|
||||
* | | | | | |
|
||||
* | w | | | .top | |
|
||||
* | <---------> | | V | |
|
||||
* | +---------+ | | +---------+ | |
|
||||
* | | ^ | | ======> | | | | |
|
||||
* | x | h| | | |.left| | | |
|
||||
* +------>| v | | +---->| | | |
|
||||
* | +.........+ | | +.........+ | |
|
||||
* | ^ | | | |
|
||||
* | y | | +----------------------+--+ high addresses
|
||||
* O------------+-------+
|
||||
*
|
||||
* Typically readPixels() will be called after Renderer.beginFrame().
|
||||
*
|
||||
* 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
|
||||
* after multiple calls to beginFrame(), render(), endFrame().
|
||||
*
|
||||
* It is also possible to use a Fence to wait for the read-back.
|
||||
*
|
||||
* @remark
|
||||
* readPixels() is intended for debugging and testing. It will impact performance significantly.
|
||||
*/
|
||||
void readPixels(uint32_t xoffset, uint32_t yoffset, uint32_t width, uint32_t height,
|
||||
backend::PixelBufferDescriptor&& buffer) noexcept;
|
||||
|
||||
/**
|
||||
* Returns the presentation time of the currently displayed frame in nanosecond.
|
||||
*
|
||||
* This value can change at any time.
|
||||
*
|
||||
* @return timestamp in nanosecond.
|
||||
*/
|
||||
int64_t getTimestamp() const noexcept;
|
||||
};
|
||||
|
||||
} // namespace filament
|
||||
|
||||
#endif // TNT_FILAMENT_STREAM_H
|
||||
230
ios/include/filament/SwapChain.h
Normal file
230
ios/include/filament/SwapChain.h
Normal file
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
* 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_FILAMENT_SWAPCHAIN_H
|
||||
#define TNT_FILAMENT_SWAPCHAIN_H
|
||||
|
||||
#include <filament/FilamentAPI.h>
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/PresentCallable.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
namespace filament {
|
||||
|
||||
/**
|
||||
* A swap chain represents an Operating System's *native* renderable surface.
|
||||
*
|
||||
* Typically it's a native window or a view. Because a SwapChain is initialized from a
|
||||
* native object, it is given to filament as a `void *`, which must be of the proper type
|
||||
* for each platform filament is running on.
|
||||
*
|
||||
* \code
|
||||
* SwapChain* swapChain = engine->createSwapChain(nativeWindow);
|
||||
* \endcode
|
||||
*
|
||||
* When Engine::create() is used without specifying a Platform, the `nativeWindow`
|
||||
* parameter above must be of type:
|
||||
*
|
||||
* Platform | nativeWindow type
|
||||
* :---------------|:----------------------------:
|
||||
* Android | ANativeWindow*
|
||||
* macOS - OpenGL | NSView*
|
||||
* macOS - Metal | CAMetalLayer*
|
||||
* iOS - OpenGL | CAEAGLLayer*
|
||||
* iOS - Metal | CAMetalLayer*
|
||||
* X11 | Window
|
||||
* Windows | HWND
|
||||
*
|
||||
* Otherwise, the `nativeWindow` is defined by the concrete implementation of Platform.
|
||||
*
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* Android
|
||||
* -------
|
||||
*
|
||||
* On Android, an `ANativeWindow*` can be obtained from a Java `Surface` object using:
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* #include <android/native_window_jni.h>
|
||||
* // parameters
|
||||
* // env: JNIEnv*
|
||||
* // surface: jobject
|
||||
* ANativeWindow* win = ANativeWindow_fromSurface(env, surface);
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* \warning
|
||||
* Don't use reflection to access the `mNativeObject` field, it won't work.
|
||||
*
|
||||
* A `Surface` can be retrieved from a `SurfaceView` or `SurfaceHolder` easily using
|
||||
* `SurfaceHolder.getSurface()` and/or `SurfaceView.getHolder()`.
|
||||
*
|
||||
* \note
|
||||
* To use a `TextureView` as a SwapChain, it is necessary to first get its `SurfaceTexture`,
|
||||
* for instance using `TextureView.SurfaceTextureListener` and then create a `Surface`:
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.java}
|
||||
* // using a TextureView.SurfaceTextureListener:
|
||||
* public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) {
|
||||
* mSurface = new Surface(surfaceTexture);
|
||||
* // mSurface can now be used in JNI to create an ANativeWindow.
|
||||
* }
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* Linux
|
||||
* -----
|
||||
*
|
||||
* Example using SDL:
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* SDL_SysWMinfo wmi;
|
||||
* SDL_VERSION(&wmi.version);
|
||||
* SDL_GetWindowWMInfo(sdlWindow, &wmi);
|
||||
* Window nativeWindow = (Window) wmi.info.x11.window;
|
||||
*
|
||||
* using namespace filament;
|
||||
* Engine* engine = Engine::create();
|
||||
* SwapChain* swapChain = engine->createSwapChain((void*) nativeWindow);
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* Windows
|
||||
* -------
|
||||
*
|
||||
* Example using SDL:
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* SDL_SysWMinfo wmi;
|
||||
* SDL_VERSION(&wmi.version);
|
||||
* ASSERT_POSTCONDITION(SDL_GetWindowWMInfo(sdlWindow, &wmi), "SDL version unsupported!");
|
||||
* HDC nativeWindow = (HDC) wmi.info.win.hdc;
|
||||
*
|
||||
* using namespace filament;
|
||||
* Engine* engine = Engine::create();
|
||||
* SwapChain* swapChain = engine->createSwapChain((void*) nativeWindow);
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* OSX
|
||||
* ---
|
||||
*
|
||||
* On OSX, any `NSView` can be used *directly* as a `nativeWindow` with createSwapChain().
|
||||
*
|
||||
* Example using SDL/Objective-C:
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.mm}
|
||||
* #include <filament/Engine.h>
|
||||
*
|
||||
* #include <Cocoa/Cocoa.h>
|
||||
* #include <SDL_syswm.h>
|
||||
*
|
||||
* SDL_SysWMinfo wmi;
|
||||
* SDL_VERSION(&wmi.version);
|
||||
* NSWindow* win = (NSWindow*) wmi.info.cocoa.window;
|
||||
* NSView* view = [win contentView];
|
||||
* void* nativeWindow = view;
|
||||
*
|
||||
* using namespace filament;
|
||||
* Engine* engine = Engine::create();
|
||||
* SwapChain* swapChain = engine->createSwapChain(nativeWindow);
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* @see Engine
|
||||
*/
|
||||
class UTILS_PUBLIC SwapChain : public FilamentAPI {
|
||||
public:
|
||||
using FrameScheduledCallback = backend::FrameScheduledCallback;
|
||||
using FrameCompletedCallback = backend::FrameCompletedCallback;
|
||||
|
||||
static const uint64_t CONFIG_TRANSPARENT = backend::SWAP_CHAIN_CONFIG_TRANSPARENT;
|
||||
/**
|
||||
* This flag indicates that the swap chain may be used as a source surface
|
||||
* for reading back render results. This config must be set when creating
|
||||
* any swap chain that will be used as the source for a blit operation.
|
||||
*
|
||||
* @see
|
||||
* Renderer.copyFrame()
|
||||
*/
|
||||
static const uint64_t CONFIG_READABLE = backend::SWAP_CHAIN_CONFIG_READABLE;
|
||||
|
||||
/**
|
||||
* Indicates that the native X11 window is an XCB window rather than an XLIB window.
|
||||
* This is ignored on non-Linux platforms and in builds that support only one X11 API.
|
||||
*/
|
||||
static const uint64_t CONFIG_ENABLE_XCB = backend::SWAP_CHAIN_CONFIG_ENABLE_XCB;
|
||||
|
||||
/**
|
||||
* Indicates that the native window is a CVPixelBufferRef.
|
||||
*
|
||||
* This is only supported by the Metal backend. The CVPixelBuffer must be in the
|
||||
* kCVPixelFormatType_32BGRA format.
|
||||
*
|
||||
* It is not necessary to add an additional retain call before passing the pixel buffer to
|
||||
* Filament. Filament will call CVPixelBufferRetain during Engine::createSwapChain, and
|
||||
* CVPixelBufferRelease when the swap chain is destroyed.
|
||||
*/
|
||||
static const uint64_t CONFIG_APPLE_CVPIXELBUFFER =
|
||||
backend::SWAP_CHAIN_CONFIG_APPLE_CVPIXELBUFFER;
|
||||
|
||||
void* getNativeWindow() const noexcept;
|
||||
|
||||
/**
|
||||
* FrameScheduledCallback is a callback function that notifies an application when Filament has
|
||||
* completed processing a frame and that frame is ready to be scheduled for presentation.
|
||||
*
|
||||
* Typically, Filament is responsible for scheduling the frame's presentation to the SwapChain.
|
||||
* If a SwapChain::FrameScheduledCallback is set, however, the application bares the
|
||||
* responsibility of scheduling a frame for presentation by calling the backend::PresentCallable
|
||||
* passed to the callback function. Currently this functionality is only supported by the Metal
|
||||
* backend.
|
||||
*
|
||||
* A FrameScheduledCallback can be set on an individual SwapChain through
|
||||
* SwapChain::setFrameScheduledCallback. If the callback is set, then the SwapChain will *not*
|
||||
* automatically schedule itself for presentation. Instead, the application must call the
|
||||
* PresentCallable passed to the FrameScheduledCallback.
|
||||
*
|
||||
* @param callback A callback, or nullptr to unset.
|
||||
* @param user An optional pointer to user data passed to the callback function.
|
||||
*
|
||||
* @remark Only Filament's Metal backend supports PresentCallables and frame callbacks. Other
|
||||
* backends ignore the callback (which will never be called) and proceed normally.
|
||||
*
|
||||
* @remark The SwapChain::FrameScheduledCallback is called on an arbitrary thread.
|
||||
*
|
||||
* @see PresentCallable
|
||||
*/
|
||||
void setFrameScheduledCallback(FrameScheduledCallback callback, void* user = nullptr);
|
||||
|
||||
/**
|
||||
* FrameCompletedCallback is a callback function that notifies an application when a frame's
|
||||
* contents have completed rendering on the GPU.
|
||||
*
|
||||
* Use SwapChain::setFrameCompletedCallback to set a callback on an individual SwapChain. Each
|
||||
* time a frame completes GPU rendering, the callback will be called with optional user data.
|
||||
*
|
||||
* The FrameCompletedCallback is guaranteed to be called on the main Filament thread.
|
||||
*
|
||||
* @param callback A callback, or nullptr to unset.
|
||||
* @param user An optional pointer to user data passed to the callback function.
|
||||
*
|
||||
* @remark Only Filament's Metal backend supports frame callbacks. Other backends ignore the
|
||||
* callback (which will never be called) and proceed normally.
|
||||
*/
|
||||
void setFrameCompletedCallback(FrameCompletedCallback callback, void* user = nullptr);
|
||||
};
|
||||
|
||||
} // namespace filament
|
||||
|
||||
#endif // TNT_FILAMENT_SWAPCHAIN_H
|
||||
517
ios/include/filament/Texture.h
Normal file
517
ios/include/filament/Texture.h
Normal file
@@ -0,0 +1,517 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef TNT_FILAMENT_TEXTURE_H
|
||||
#define TNT_FILAMENT_TEXTURE_H
|
||||
|
||||
#include <filament/FilamentAPI.h>
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/PixelBufferDescriptor.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
namespace filament {
|
||||
|
||||
class FTexture;
|
||||
|
||||
class Engine;
|
||||
class Stream;
|
||||
|
||||
/**
|
||||
* Texture
|
||||
*
|
||||
* The Texture class supports:
|
||||
* - 2D textures
|
||||
* - 3D textures
|
||||
* - Cube maps
|
||||
* - mip mapping
|
||||
*
|
||||
*
|
||||
* Creation and destruction
|
||||
* ========================
|
||||
*
|
||||
* A Texture object is created using the Texture::Builder and destroyed by calling
|
||||
* Engine::destroy(const Texture*).
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
|
||||
* filament::Engine* engine = filament::Engine::create();
|
||||
*
|
||||
* filament::Texture* texture = filament::Texture::Builder()
|
||||
* .width(64)
|
||||
* .height(64)
|
||||
* .build(*engine);
|
||||
*
|
||||
* engine->destroy(texture);
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
*/
|
||||
class UTILS_PUBLIC Texture : public FilamentAPI {
|
||||
struct BuilderDetails;
|
||||
|
||||
public:
|
||||
static constexpr const size_t BASE_LEVEL = 0;
|
||||
|
||||
using PixelBufferDescriptor = backend::PixelBufferDescriptor; //!< Geometry of a pixel buffer
|
||||
using Sampler = backend::SamplerType; //!< Type of sampler
|
||||
using InternalFormat = backend::TextureFormat; //!< Internal texel format
|
||||
using CubemapFace = backend::TextureCubemapFace; //!< Cube map faces
|
||||
using Format = backend::PixelDataFormat; //!< Pixel color format
|
||||
using Type = backend::PixelDataType; //!< Pixel data format
|
||||
using CompressedType = backend::CompressedPixelDataType; //!< Compressed pixel data format
|
||||
using FaceOffsets = backend::FaceOffsets; //!< Cube map faces offsets
|
||||
using Usage = backend::TextureUsage; //!< Usage affects texel layout
|
||||
using Swizzle = backend::TextureSwizzle; //!< Texture swizzle
|
||||
|
||||
/** @return whether a backend supports a particular format. */
|
||||
static bool isTextureFormatSupported(Engine& engine, InternalFormat format) noexcept;
|
||||
|
||||
/** @return whether a backend supports texture swizzling. */
|
||||
static bool isTextureSwizzleSupported(Engine& engine) noexcept;
|
||||
|
||||
static size_t computeTextureDataSize(Texture::Format format, Texture::Type type,
|
||||
size_t stride, size_t height, size_t alignment) noexcept;
|
||||
|
||||
|
||||
/**
|
||||
* Options for environment prefiltering into reflection map
|
||||
*
|
||||
* @see generatePrefilterMipmap()
|
||||
*/
|
||||
struct PrefilterOptions {
|
||||
uint16_t sampleCount = 8; //!< sample count used for filtering
|
||||
bool mirror = true; //!< whether the environment must be mirrored
|
||||
private:
|
||||
UTILS_UNUSED uintptr_t reserved[3] = {};
|
||||
};
|
||||
|
||||
|
||||
//! Use Builder to construct a Texture object instance
|
||||
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;
|
||||
|
||||
/**
|
||||
* Specifies the width in texels of the texture. Doesn't need to be a power-of-two.
|
||||
* @param width Width of the texture in texels (default: 1).
|
||||
* @return This Builder, for chaining calls.
|
||||
*/
|
||||
Builder& width(uint32_t width) noexcept;
|
||||
|
||||
/**
|
||||
* Specifies the height in texels of the texture. Doesn't need to be a power-of-two.
|
||||
* @param height Height of the texture in texels (default: 1).
|
||||
* @return This Builder, for chaining calls.
|
||||
*/
|
||||
Builder& height(uint32_t height) noexcept;
|
||||
|
||||
/**
|
||||
* Specifies the depth in texels of the texture. Doesn't need to be a power-of-two.
|
||||
* The depth controls the number of layers in a 2D array texture. Values greater than 1
|
||||
* effectively create a 3D texture.
|
||||
* @param depth Depth of the texture in texels (default: 1).
|
||||
* @return This Builder, for chaining calls.
|
||||
* @attention This Texture instance must use Sampler::SAMPLER_3D or Sampler::SAMPLER_2D_ARRAY or it has no effect.
|
||||
*/
|
||||
Builder& depth(uint32_t depth) noexcept;
|
||||
|
||||
/**
|
||||
* Specifies the numbers of mip map levels.
|
||||
* This creates a mip-map pyramid. The maximum number of levels a texture can have is
|
||||
* such that max(width, height, level) / 2^MAX_LEVELS = 1
|
||||
* @param levels Number of mipmap levels for this texture.
|
||||
* @return This Builder, for chaining calls.
|
||||
*/
|
||||
Builder& levels(uint8_t levels) noexcept;
|
||||
|
||||
/**
|
||||
* Specifies the type of sampler to use.
|
||||
* @param target Sampler type
|
||||
* @return This Builder, for chaining calls.
|
||||
* @see Sampler
|
||||
*/
|
||||
Builder& sampler(Sampler target) noexcept;
|
||||
|
||||
/**
|
||||
* Specifies the *internal* format of this texture.
|
||||
*
|
||||
* The internal format specifies how texels are stored (which may be different from how
|
||||
* they're specified in setImage()). InternalFormat specifies both the color components
|
||||
* and the data type used.
|
||||
*
|
||||
* @param format Format of the texture's texel.
|
||||
* @return This Builder, for chaining calls.
|
||||
* @see InternalFormat, setImage
|
||||
*/
|
||||
Builder& format(InternalFormat format) noexcept;
|
||||
|
||||
/**
|
||||
* Specifies if the texture will be used as a render target attachment.
|
||||
*
|
||||
* If the texture is potentially rendered into, it may require a different memory layout,
|
||||
* which needs to be known during construction.
|
||||
*
|
||||
* @param usage Defaults to Texture::Usage::DEFAULT; c.f. Texture::Usage::COLOR_ATTACHMENT.
|
||||
* @return This Builder, for chaining calls.
|
||||
*/
|
||||
Builder& usage(Usage usage) noexcept;
|
||||
|
||||
/**
|
||||
* Specifies how a texture's channels map to color components
|
||||
*
|
||||
* Texture Swizzle is only supported is isTextureSwizzleSupported() returns true.
|
||||
*
|
||||
* @param r texture channel for red component
|
||||
* @param g texture channel for green component
|
||||
* @param b texture channel for blue component
|
||||
* @param a texture channel for alpha component
|
||||
* @return This Builder, for chaining calls.
|
||||
* @see Texture::isTextureSwizzleSupported()
|
||||
*/
|
||||
Builder& swizzle(Swizzle r, Swizzle g, Swizzle b, Swizzle a) noexcept;
|
||||
|
||||
/**
|
||||
* Creates the Texture object and returns a pointer to it.
|
||||
*
|
||||
* @param engine Reference to the filament::Engine to associate this Texture 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.
|
||||
*/
|
||||
Texture* build(Engine& engine);
|
||||
|
||||
/* no user serviceable parts below */
|
||||
|
||||
/**
|
||||
* Specify a native texture to import as a Filament texture.
|
||||
*
|
||||
* The texture id is backend-specific:
|
||||
* - OpenGL: GLuint texture ID
|
||||
* - Metal: id<MTLTexture>
|
||||
*
|
||||
* With Metal, the id<MTLTexture> object should be cast to an intptr_t using
|
||||
* CFBridgingRetain to transfer ownership to Filament. Filament will release ownership of
|
||||
* the texture object when the Filament texture is destroyed.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
|
||||
* id <MTLTexture> metalTexture = ...
|
||||
* filamentTexture->import((intptr_t) CFBridgingRetain(metalTexture));
|
||||
* // free to release metalTexture
|
||||
*
|
||||
* // after using texture:
|
||||
* engine->destroy(filamentTexture); // metalTexture is released
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* @warning This method should be used as a last resort. This API is subject to change or
|
||||
* removal.
|
||||
*
|
||||
* @param id a backend specific texture identifier
|
||||
*
|
||||
* @return This Builder, for chaining calls.
|
||||
*/
|
||||
Builder& import(intptr_t id) noexcept;
|
||||
|
||||
private:
|
||||
friend class FTexture;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the width of a 2D or 3D texture level
|
||||
* @param level texture level.
|
||||
* @return Width in texel of the specified \p level, clamped to 1.
|
||||
* @attention If this texture is using Sampler::SAMPLER_EXTERNAL, the dimension
|
||||
* of the texture are unknown and this method always returns whatever was set on the Builder.
|
||||
*/
|
||||
size_t getWidth(size_t level = BASE_LEVEL) const noexcept;
|
||||
|
||||
/**
|
||||
* Returns the height of a 2D or 3D texture level
|
||||
* @param level texture level.
|
||||
* @return Height in texel of the specified \p level, clamped to 1.
|
||||
* @attention If this texture is using Sampler::SAMPLER_EXTERNAL, the dimension
|
||||
* of the texture are unknown and this method always returns whatever was set on the Builder.
|
||||
*/
|
||||
size_t getHeight(size_t level = BASE_LEVEL) const noexcept;
|
||||
|
||||
/**
|
||||
* Returns the depth of a 3D texture level
|
||||
* @param level texture level.
|
||||
* @return Depth in texel of the specified \p level, clamped to 1.
|
||||
* @attention If this texture is using Sampler::SAMPLER_EXTERNAL, the dimension
|
||||
* of the texture are unknown and this method always returns whatever was set on the Builder.
|
||||
*/
|
||||
size_t getDepth(size_t level = BASE_LEVEL) const noexcept;
|
||||
|
||||
/**
|
||||
* Returns the maximum number of levels this texture can have.
|
||||
* @return maximum number of levels this texture can have.
|
||||
* @attention If this texture is using Sampler::SAMPLER_EXTERNAL, the dimension
|
||||
* of the texture are unknown and this method always returns whatever was set on the Builder.
|
||||
*/
|
||||
size_t getLevels() const noexcept;
|
||||
|
||||
/**
|
||||
* Return this texture Sampler as set by Builder::sampler().
|
||||
* @return this texture Sampler as set by Builder::sampler()
|
||||
*/
|
||||
Sampler getTarget() const noexcept;
|
||||
|
||||
/**
|
||||
* Return this texture InternalFormat as set by Builder::format().
|
||||
* @return this texture InternalFormat as set by Builder::format().
|
||||
*/
|
||||
InternalFormat getFormat() const noexcept;
|
||||
|
||||
/**
|
||||
* Specify the image of a 2D texture for a level.
|
||||
*
|
||||
* @param engine Engine this texture is associated to.
|
||||
* @param level Level to set the image for.
|
||||
* @param buffer Client-side buffer containing the image to set.
|
||||
*
|
||||
* @attention \p engine must be the instance passed to Builder::build()
|
||||
* @attention \p level must be less than getLevels().
|
||||
* @attention \p buffer's Texture::Format must match that of getFormat().
|
||||
* @attention This Texture instance must use Sampler::SAMPLER_2D or
|
||||
* Sampler::SAMPLER_EXTERNAL. IF the later is specified
|
||||
* and external textures are supported by the driver implementation,
|
||||
* this method will have no effect, otherwise it will behave as if the
|
||||
* texture was specified with driver::SamplerType::SAMPLER_2D.
|
||||
*
|
||||
* @note
|
||||
* This is equivalent to calling:
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* setImage(engine, level, 0, 0, getWidth(level), getHeight(level), buffer);
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* @see Builder::sampler()
|
||||
*/
|
||||
void setImage(Engine& engine, size_t level, PixelBufferDescriptor&& buffer) const;
|
||||
|
||||
/**
|
||||
* Updates a sub-image of a 2D texture for a level.
|
||||
*
|
||||
* @param engine Engine this texture is associated to.
|
||||
* @param level Level to set the image for.
|
||||
* @param xoffset Left offset of the sub-region to update.
|
||||
* @param yoffset Bottom offset of the sub-region to update.
|
||||
* @param width Width of the sub-region to update.
|
||||
* @param height Height of the sub-region to update.
|
||||
* @param buffer Client-side buffer containing the image to set.
|
||||
*
|
||||
* @attention \p engine must be the instance passed to Builder::build()
|
||||
* @attention \p level must be less than getLevels().
|
||||
* @attention \p buffer's Texture::Format must match that of getFormat().
|
||||
* @attention This Texture instance must use Sampler::SAMPLER_2D or
|
||||
* Sampler::SAMPLER_EXTERNAL. IF the later is specified
|
||||
* and external textures are supported by the driver implementation,
|
||||
* this method will have no effect, otherwise it will behave as if the
|
||||
* texture was specified with Sampler::SAMPLER_2D.
|
||||
*
|
||||
* @see Builder::sampler()
|
||||
*/
|
||||
void setImage(Engine& engine, size_t level,
|
||||
uint32_t xoffset, uint32_t yoffset, uint32_t width, uint32_t height,
|
||||
PixelBufferDescriptor&& buffer) const;
|
||||
|
||||
/**
|
||||
* Updates a sub-image of a 3D texture or 2D texture array for a level.
|
||||
*
|
||||
* @param engine Engine this texture is associated to.
|
||||
* @param level Level to set the image for.
|
||||
* @param xoffset Left offset of the sub-region to update.
|
||||
* @param yoffset Bottom offset of the sub-region to update.
|
||||
* @param zoffset Depth offset of the sub-region to update.
|
||||
* @param width Width of the sub-region to update.
|
||||
* @param height Height of the sub-region to update.
|
||||
* @param depth Depth of the sub-region to update.
|
||||
* @param buffer Client-side buffer containing the image to set.
|
||||
*
|
||||
* @attention \p engine must be the instance passed to Builder::build()
|
||||
* @attention \p level must be less than getLevels().
|
||||
* @attention \p buffer's Texture::Format must match that of getFormat().
|
||||
* @attention This Texture instance must use Sampler::SAMPLER_3D or Sampler::SAMPLER_2D_array.
|
||||
*
|
||||
* @see Builder::sampler()
|
||||
*/
|
||||
void setImage(Engine& engine, size_t level,
|
||||
uint32_t xoffset, uint32_t yoffset, uint32_t zoffset,
|
||||
uint32_t width, uint32_t height, uint32_t depth,
|
||||
PixelBufferDescriptor&& buffer) const;
|
||||
|
||||
/**
|
||||
* Specify all six images of a cube map level.
|
||||
*
|
||||
* This method follows exactly the OpenGL conventions.
|
||||
*
|
||||
* @param engine Engine this texture is associated to.
|
||||
* @param level Level to set the image for.
|
||||
* @param buffer Client-side buffer containing the images to set.
|
||||
* @param faceOffsets Offsets in bytes into \p buffer for all six images. The offsets
|
||||
* are specified in the following order: +x, -x, +y, -y, +z, -z
|
||||
*
|
||||
* @attention \p engine must be the instance passed to Builder::build()
|
||||
* @attention \p level must be less than getLevels().
|
||||
* @attention \p buffer's Texture::Format must match that of getFormat().
|
||||
* @attention This Texture instance must use Sampler::SAMPLER_CUBEMAP or it has no effect
|
||||
*
|
||||
* @see Texture::CubemapFace, Builder::sampler()
|
||||
*/
|
||||
void setImage(Engine& engine, size_t level,
|
||||
PixelBufferDescriptor&& buffer, const FaceOffsets& faceOffsets) const;
|
||||
|
||||
|
||||
/**
|
||||
* Specify the external image to associate with this Texture. Typically the external
|
||||
* image is OS specific, and can be a video or camera frame.
|
||||
* There are many restrictions when using an external image as a texture, such as:
|
||||
* - only the level of detail (lod) 0 can be specified
|
||||
* - only nearest or linear filtering is supported
|
||||
* - the size and format of the texture is defined by the external image
|
||||
* - only the CLAMP_TO_EDGE wrap mode is supported
|
||||
*
|
||||
* @param engine Engine this texture is associated to.
|
||||
* @param image An opaque handle to a platform specific image. Supported types are
|
||||
* eglImageOES on Android and CVPixelBufferRef on iOS.
|
||||
*
|
||||
* On iOS the following pixel formats are supported:
|
||||
* - kCVPixelFormatType_32BGRA
|
||||
* - kCVPixelFormatType_420YpCbCr8BiPlanarFullRange
|
||||
*
|
||||
* @attention \p engine must be the instance passed to Builder::build()
|
||||
* @attention This Texture instance must use Sampler::SAMPLER_EXTERNAL or it has no effect
|
||||
*
|
||||
* @see Builder::sampler()
|
||||
*
|
||||
*/
|
||||
void setExternalImage(Engine& engine, void* image) noexcept;
|
||||
|
||||
/**
|
||||
* Specify the external image and plane to associate with this Texture. Typically the external
|
||||
* image is OS specific, and can be a video or camera frame. When using this method, the
|
||||
* external image must be a planar type (such as a YUV camera frame). The plane parameter
|
||||
* selects which image plane is bound to this texture.
|
||||
*
|
||||
* A single external image can be bound to different Filament textures, with each texture
|
||||
* associated with a separate plane:
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* textureA->setExternalImage(engine, image, 0);
|
||||
* textureB->setExternalImage(engine, image, 1);
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* There are many restrictions when using an external image as a texture, such as:
|
||||
* - only the level of detail (lod) 0 can be specified
|
||||
* - only nearest or linear filtering is supported
|
||||
* - the size and format of the texture is defined by the external image
|
||||
* - only the CLAMP_TO_EDGE wrap mode is supported
|
||||
*
|
||||
* @param engine Engine this texture is associated to.
|
||||
* @param image An opaque handle to a platform specific image. Supported types are
|
||||
* eglImageOES on Android and CVPixelBufferRef on iOS.
|
||||
* @param plane The plane index of the external image to associate with this texture.
|
||||
*
|
||||
* This method is only meaningful on iOS with
|
||||
* kCVPixelFormatType_420YpCbCr8BiPlanarFullRange images. On platforms
|
||||
* other than iOS, this method is a no-op.
|
||||
*/
|
||||
void setExternalImage(Engine& engine, void* image, size_t plane) noexcept;
|
||||
|
||||
/**
|
||||
* Specify the external stream to associate with this Texture. Typically the external
|
||||
* stream is OS specific, and can be a video or camera stream.
|
||||
* There are many restrictions when using an external stream as a texture, such as:
|
||||
* - only the level of detail (lod) 0 can be specified
|
||||
* - only nearest or linear filtering is supported
|
||||
* - the size and format of the texture is defined by the external stream
|
||||
*
|
||||
* @param engine Engine this texture is associated to.
|
||||
* @param stream A Stream object
|
||||
*
|
||||
* @attention \p engine must be the instance passed to Builder::build()
|
||||
* @attention This Texture instance must use Sampler::SAMPLER_EXTERNAL or it has no effect
|
||||
*
|
||||
* @see Builder::sampler(), Stream
|
||||
*
|
||||
*/
|
||||
void setExternalStream(Engine& engine, Stream* stream) noexcept;
|
||||
|
||||
/**
|
||||
* Generates all the mipmap levels automatically. This requires the texture to have a
|
||||
* color-renderable format.
|
||||
*
|
||||
* @param engine Engine this texture is associated to.
|
||||
*
|
||||
* @attention \p engine must be the instance passed to Builder::build()
|
||||
* @attention This Texture instance must NOT use Sampler::SAMPLER_CUBEMAP or it has no effect
|
||||
*/
|
||||
void generateMipmaps(Engine& engine) const noexcept;
|
||||
|
||||
/**
|
||||
* Creates a reflection map from an environment map.
|
||||
*
|
||||
* This is a utility function that replaces calls to Texture::setImage().
|
||||
* The provided environment map is processed and all mipmap levels are populated. The
|
||||
* processing is similar to the offline tool `cmgen` as a lower quality setting.
|
||||
*
|
||||
* This function is intended to be used when the environment cannot be processed offline,
|
||||
* for instance if it's generated at runtime.
|
||||
*
|
||||
* The source data must obey to some constraints:
|
||||
* - the data type must be PixelDataFormat::RGB
|
||||
* - the data format must be one of
|
||||
* - PixelDataType::FLOAT
|
||||
* - PixelDataType::HALF
|
||||
*
|
||||
* The current texture must be a cubemap
|
||||
*
|
||||
* The reflections cubemap's internal format cannot be a compressed format.
|
||||
*
|
||||
* The reflections cubemap's dimension must be a power-of-two.
|
||||
*
|
||||
* @warning This operation is computationally intensive, especially with large environments and
|
||||
* is currently synchronous. Expect about 1ms for a 16x16 cubemap.
|
||||
*
|
||||
* @param engine Reference to the filament::Engine to associate this IndirectLight with.
|
||||
* @param buffer Client-side buffer containing the images to set.
|
||||
* @param faceOffsets Offsets in bytes into \p buffer for all six images. The offsets
|
||||
* are specified in the following order: +x, -x, +y, -y, +z, -z
|
||||
* @param options Optional parameter to controlling user-specified quality and options.
|
||||
*
|
||||
* @exception utils::PreConditionPanic if the source data constraints are not respected.
|
||||
*
|
||||
*/
|
||||
void generatePrefilterMipmap(Engine& engine,
|
||||
PixelBufferDescriptor&& buffer, const FaceOffsets& faceOffsets,
|
||||
PrefilterOptions const* options = nullptr);
|
||||
};
|
||||
|
||||
} // namespace filament
|
||||
|
||||
#endif // TNT_FILAMENT_TEXTURE_H
|
||||
205
ios/include/filament/TextureSampler.h
Normal file
205
ios/include/filament/TextureSampler.h
Normal file
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef TNT_FILAMENT_TEXTURESAMPLER_H
|
||||
#define TNT_FILAMENT_TEXTURESAMPLER_H
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <math.h>
|
||||
|
||||
namespace filament {
|
||||
|
||||
/**
|
||||
* TextureSampler defines how a texture is accessed.
|
||||
*/
|
||||
class UTILS_PUBLIC TextureSampler {
|
||||
public:
|
||||
using WrapMode = backend::SamplerWrapMode;
|
||||
using MinFilter = backend::SamplerMinFilter;
|
||||
using MagFilter = backend::SamplerMagFilter;
|
||||
using CompareMode = backend::SamplerCompareMode;
|
||||
using CompareFunc = backend::SamplerCompareFunc;
|
||||
|
||||
/**
|
||||
* Creates a default sampler.
|
||||
* The default parameters are:
|
||||
* - filterMag : NEAREST
|
||||
* - filterMin : NEAREST
|
||||
* - wrapS : CLAMP_TO_EDGE
|
||||
* - wrapT : CLAMP_TO_EDGE
|
||||
* - wrapR : CLAMP_TO_EDGE
|
||||
* - compareMode : NONE
|
||||
* - compareFunc : Less or equal
|
||||
* - no anisotropic filtering
|
||||
*/
|
||||
TextureSampler() noexcept = default;
|
||||
|
||||
TextureSampler(const TextureSampler& rhs) noexcept = default;
|
||||
TextureSampler& operator=(const TextureSampler& rhs) noexcept = default;
|
||||
|
||||
/**
|
||||
* Creates a TextureSampler with the default parameters but setting the filtering and wrap modes.
|
||||
* @param minMag filtering for both minification and magnification
|
||||
* @param str wrapping mode for all texture coordinate axes
|
||||
*/
|
||||
explicit TextureSampler(MagFilter minMag, WrapMode str = WrapMode::CLAMP_TO_EDGE) noexcept {
|
||||
mSamplerParams.filterMin = MinFilter(minMag);
|
||||
mSamplerParams.filterMag = minMag;
|
||||
mSamplerParams.wrapS = str;
|
||||
mSamplerParams.wrapT = str;
|
||||
mSamplerParams.wrapR = str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a TextureSampler with the default parameters but setting the filtering and wrap modes.
|
||||
* @param min filtering for minification
|
||||
* @param mag filtering for magnification
|
||||
* @param str wrapping mode for all texture coordinate axes
|
||||
*/
|
||||
TextureSampler(MinFilter min, MagFilter mag, WrapMode str = WrapMode::CLAMP_TO_EDGE) noexcept {
|
||||
mSamplerParams.filterMin = min;
|
||||
mSamplerParams.filterMag = mag;
|
||||
mSamplerParams.wrapS = str;
|
||||
mSamplerParams.wrapT = str;
|
||||
mSamplerParams.wrapR = str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a TextureSampler with the default parameters but setting the filtering and wrap modes.
|
||||
* @param min filtering for minification
|
||||
* @param mag filtering for magnification
|
||||
* @param s wrap mode for the s (horizontal)texture coordinate
|
||||
* @param t wrap mode for the t (vertical) texture coordinate
|
||||
* @param r wrap mode for the r (depth) texture coordinate
|
||||
*/
|
||||
TextureSampler(MinFilter min, MagFilter mag, WrapMode s, WrapMode t, WrapMode r) noexcept {
|
||||
mSamplerParams.filterMin = min;
|
||||
mSamplerParams.filterMag = mag;
|
||||
mSamplerParams.wrapS = s;
|
||||
mSamplerParams.wrapT = t;
|
||||
mSamplerParams.wrapR = r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a TextureSampler with the default parameters but setting the compare mode and function
|
||||
* @param mode Compare mode
|
||||
* @param func Compare function
|
||||
*/
|
||||
explicit TextureSampler(CompareMode mode, CompareFunc func = CompareFunc::LE) noexcept {
|
||||
mSamplerParams.compareMode = mode;
|
||||
mSamplerParams.compareFunc = func;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the minification filter
|
||||
* @param v Minification filter
|
||||
*/
|
||||
void setMinFilter(MinFilter v) noexcept {
|
||||
mSamplerParams.filterMin = v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the magnification filter
|
||||
* @param v Magnification filter
|
||||
*/
|
||||
void setMagFilter(MagFilter v) noexcept {
|
||||
mSamplerParams.filterMag = v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the wrap mode for the s (horizontal) texture coordinate
|
||||
* @param v wrap mode
|
||||
*/
|
||||
void setWrapModeS(WrapMode v) noexcept {
|
||||
mSamplerParams.wrapS = v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the wrap mode for the t (vertical) texture coordinate
|
||||
* @param v wrap mode
|
||||
*/
|
||||
void setWrapModeT(WrapMode v) noexcept {
|
||||
mSamplerParams.wrapT = v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the wrap mode for the r (depth, for 3D textures) texture coordinate
|
||||
* @param v wrap mode
|
||||
*/
|
||||
void setWrapModeR(WrapMode v) noexcept {
|
||||
mSamplerParams.wrapR = v;
|
||||
}
|
||||
|
||||
/**
|
||||
* This controls anisotropic filtering.
|
||||
* @param anisotropy Amount of anisotropy, should be a power-of-two. The default is 0.
|
||||
* The maximum permissible value is 7.
|
||||
*/
|
||||
void setAnisotropy(float anisotropy) noexcept {
|
||||
const int log2 = ilogbf(anisotropy > 0 ? anisotropy : -anisotropy);
|
||||
mSamplerParams.anisotropyLog2 = uint8_t(log2 < 7 ? log2 : 7);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the compare mode and function.
|
||||
* @param mode Compare mode
|
||||
* @param func Compare function
|
||||
*/
|
||||
void setCompareMode(CompareMode mode, CompareFunc func = CompareFunc::LE) noexcept {
|
||||
mSamplerParams.compareMode = mode;
|
||||
mSamplerParams.compareFunc = func;
|
||||
}
|
||||
|
||||
//! returns the minification filter value
|
||||
MinFilter getMinFilter() const noexcept { return mSamplerParams.filterMin; }
|
||||
|
||||
//! returns the magnification filter value
|
||||
MagFilter getMagFilter() const noexcept { return mSamplerParams.filterMag; }
|
||||
|
||||
//! returns the s-coordinate wrap mode (horizontal)
|
||||
WrapMode getWrapModeS() const noexcept { return mSamplerParams.wrapS; }
|
||||
|
||||
//! returns the t-coordinate wrap mode (vertical)
|
||||
WrapMode getWrapModeT() const noexcept { return mSamplerParams.wrapT; }
|
||||
|
||||
//! returns the r-coordinate wrap mode (depth)
|
||||
WrapMode getWrapModeR() const noexcept { return mSamplerParams.wrapR; }
|
||||
|
||||
//! returns the anisotropy value
|
||||
float getAnisotropy() const noexcept { return float(1u << mSamplerParams.anisotropyLog2); }
|
||||
|
||||
//! returns the compare mode
|
||||
CompareMode getCompareMode() const noexcept { return mSamplerParams.compareMode; }
|
||||
|
||||
//! returns the compare function
|
||||
CompareFunc getCompareFunc() const noexcept { return mSamplerParams.compareFunc; }
|
||||
|
||||
|
||||
// no user-serviceable parts below...
|
||||
backend::SamplerParams getSamplerParams() const noexcept { return mSamplerParams; }
|
||||
|
||||
private:
|
||||
backend::SamplerParams mSamplerParams{};
|
||||
};
|
||||
|
||||
} // namespace filament
|
||||
|
||||
#endif // TNT_FILAMENT_TEXTURESAMPLER_H
|
||||
235
ios/include/filament/ToneMapper.h
Normal file
235
ios/include/filament/ToneMapper.h
Normal file
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
* 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 TNT_FILAMENT_TONE_MAPPER_H
|
||||
#define TNT_FILAMENT_TONE_MAPPER_H
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <math/mathfwd.h>
|
||||
|
||||
namespace filament {
|
||||
|
||||
/**
|
||||
* Interface for tone mapping operators. A tone mapping operator, or tone mapper,
|
||||
* is responsible for compressing the dynamic range of the rendered scene to a
|
||||
* dynamic range suitable for display.
|
||||
*
|
||||
* In Filament, tone mapping is a color grading step. ToneMapper instances are
|
||||
* created and passed to the ColorGrading::Builder to produce a 3D LUT that will
|
||||
* be used during post-processing to prepare the final color buffer for display.
|
||||
*
|
||||
* Filament provides several default tone mapping operators that fall into three
|
||||
* categories:
|
||||
*
|
||||
* - Configurable tone mapping operators
|
||||
* - GenericToneMapper
|
||||
* - Fixed-aesthetic tone mapping operators
|
||||
* - ACESToneMapper
|
||||
* - ACESLegacyToneMapper
|
||||
* - FilmicToneMapper
|
||||
* - Debug/validation tone mapping operators
|
||||
* - LinearToneMapper
|
||||
* - DisplayRangeToneMapper
|
||||
*
|
||||
* You can create custom tone mapping operators by subclassing ToneMapper.
|
||||
*/
|
||||
struct UTILS_PUBLIC ToneMapper {
|
||||
ToneMapper() noexcept;
|
||||
virtual ~ToneMapper() noexcept;
|
||||
|
||||
/**
|
||||
* Maps an open domain (or "scene referred" values) color value to display
|
||||
* domain (or "display referred") color value. Both the input and output
|
||||
* color values are defined in the Rec.2020 color space, with no transfer
|
||||
* function applied ("linear Rec.2020").
|
||||
*
|
||||
* @param c Input color to tone map, in the Rec.2020 color space with no
|
||||
* transfer function applied ("linear")
|
||||
*
|
||||
* @return A tone mapped color in the Rec.2020 color space, with no transfer
|
||||
* function applied ("linear")
|
||||
*/
|
||||
virtual math::float3 operator()(math::float3 c) const noexcept = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Linear tone mapping operator that returns the input color but clamped to
|
||||
* the 0..1 range. This operator is mostly useful for debugging.
|
||||
*/
|
||||
struct UTILS_PUBLIC LinearToneMapper final : public ToneMapper {
|
||||
LinearToneMapper() noexcept;
|
||||
~LinearToneMapper() noexcept final;
|
||||
|
||||
math::float3 operator()(math::float3 c) const noexcept;
|
||||
};
|
||||
|
||||
/**
|
||||
* ACES tone mapping operator. This operator is an implementation of the
|
||||
* ACES Reference Rendering Transform (RRT) combined with the Output Device
|
||||
* Transform (ODT) for sRGB monitors (dim surround, 100 nits).
|
||||
*/
|
||||
struct UTILS_PUBLIC ACESToneMapper final : public ToneMapper {
|
||||
ACESToneMapper() noexcept;
|
||||
~ACESToneMapper() noexcept final;
|
||||
|
||||
math::float3 operator()(math::float3 c) const noexcept;
|
||||
};
|
||||
|
||||
/**
|
||||
* ACES tone mapping operator, modified to match the perceived brightness
|
||||
* of FilmicToneMapper. This operator is the same as ACESToneMapper but
|
||||
* applies a brightness multiplier of ~1.6 to the input color value to
|
||||
* target brighter viewing environments.
|
||||
*/
|
||||
struct UTILS_PUBLIC ACESLegacyToneMapper final : public ToneMapper {
|
||||
ACESLegacyToneMapper() noexcept;
|
||||
~ACESLegacyToneMapper() noexcept final;
|
||||
|
||||
math::float3 operator()(math::float3 c) const noexcept;
|
||||
};
|
||||
|
||||
/**
|
||||
* "Filmic" tone mapping operator. This tone mapper was designed to
|
||||
* approximate the aesthetics of the ACES RRT + ODT for Rec.709
|
||||
* and historically Filament's default tone mapping operator. It exists
|
||||
* only for backward compatibility purposes and is not otherwise recommended.
|
||||
*/
|
||||
struct UTILS_PUBLIC FilmicToneMapper final : public ToneMapper {
|
||||
FilmicToneMapper() noexcept;
|
||||
~FilmicToneMapper() noexcept final;
|
||||
|
||||
math::float3 operator()(math::float3 x) const noexcept;
|
||||
};
|
||||
|
||||
/**
|
||||
* Generic tone mapping operator that gives control over the tone mapping
|
||||
* curve. This operator can be used to control the aesthetics of the final
|
||||
* image. This operator also allows to control the dynamic range of the
|
||||
* scene referred values.
|
||||
*
|
||||
* The tone mapping curve is defined by 5 parameters:
|
||||
* - 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
|
||||
* - midGrayOut: sets the output middle gray
|
||||
* - hdrMax: defines the maximum input value that will be mapped to
|
||||
* output white
|
||||
*/
|
||||
struct UTILS_PUBLIC GenericToneMapper final : public ToneMapper {
|
||||
/**
|
||||
* Builds a new generic tone mapper. The default values of the
|
||||
* constructor parameters approximate an ACES tone mapping curve
|
||||
* and the maximum input value is set to 10.0.
|
||||
*
|
||||
* @param contrast: controls the contrast of the curve, must be > 0.0, values
|
||||
* 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 midGrayOut: sets the output middle gray, between 0.0 and 1.0.
|
||||
* @param hdrMax: defines the maximum input value that will be mapped to
|
||||
* output white. Must be >= 1.0.
|
||||
*/
|
||||
GenericToneMapper(
|
||||
float contrast = 1.585f,
|
||||
float shoulder = 0.5f,
|
||||
float midGrayIn = 0.18f,
|
||||
float midGrayOut = 0.268f,
|
||||
float hdrMax = 10.0f
|
||||
) noexcept;
|
||||
~GenericToneMapper() noexcept final;
|
||||
|
||||
GenericToneMapper(GenericToneMapper const&) = delete;
|
||||
GenericToneMapper& operator=(GenericToneMapper const&) = delete;
|
||||
GenericToneMapper(GenericToneMapper&& rhs) noexcept;
|
||||
GenericToneMapper& operator=(GenericToneMapper& rhs) noexcept;
|
||||
|
||||
math::float3 operator()(math::float3 x) const noexcept;
|
||||
|
||||
/** Returns the contrast of the curve as a strictly positive value. */
|
||||
float getContrast() const noexcept;
|
||||
|
||||
/** Returns how fast scene referred values map to output white as a value between 0.0 and 1.0. */
|
||||
float getShoulder() const noexcept;
|
||||
|
||||
/** Returns the middle gray point for input values as a value between 0.0 and 1.0. */
|
||||
float getMidGrayIn() const noexcept;
|
||||
|
||||
/** Returns the middle gray point for output values as a value between 0.0 and 1.0. */
|
||||
float getMidGrayOut() const noexcept;
|
||||
|
||||
/** Returns the maximum input value that will map to output white, as a value >= 1.0. */
|
||||
float getHdrMax() const noexcept;
|
||||
|
||||
/** 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;
|
||||
|
||||
/** 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. */
|
||||
void setMidGrayIn(float midGrayIn) noexcept;
|
||||
|
||||
/** Sets the output middle gray, between 0.0 and 1.0. */
|
||||
void setMidGrayOut(float midGrayOut) noexcept;
|
||||
|
||||
/** Defines the maximum input value that will be mapped to output white. Must be >= 1.0. */
|
||||
void setHdrMax(float hdrMax) noexcept;
|
||||
|
||||
private:
|
||||
struct Options;
|
||||
Options* mOptions;
|
||||
};
|
||||
|
||||
/**
|
||||
* A tone mapper that converts the input HDR RGB color into one of 16 debug colors
|
||||
* that represent the pixel's exposure. When the output is cyan, the input color
|
||||
* represents middle gray (18% exposure). Every exposure stop above or below middle
|
||||
* gray causes a color shift.
|
||||
*
|
||||
* The relationship between exposures and colors is:
|
||||
*
|
||||
* - -5EV black
|
||||
* - -4EV darkest blue
|
||||
* - -3EV darker blue
|
||||
* - -2EV dark blue
|
||||
* - -1EV blue
|
||||
* - OEV cyan
|
||||
* - +1EV dark green
|
||||
* - +2EV green
|
||||
* - +3EV yellow
|
||||
* - +4EV yellow-orange
|
||||
* - +5EV orange
|
||||
* - +6EV bright red
|
||||
* - +7EV red
|
||||
* - +8EV magenta
|
||||
* - +9EV purple
|
||||
* - +10EV white
|
||||
*
|
||||
* This tone mapper is useful to validate and tweak scene lighting.
|
||||
*/
|
||||
struct UTILS_PUBLIC DisplayRangeToneMapper final : public ToneMapper {
|
||||
DisplayRangeToneMapper() noexcept;
|
||||
~DisplayRangeToneMapper() noexcept;
|
||||
|
||||
math::float3 operator()(math::float3 c) const noexcept;
|
||||
};
|
||||
|
||||
} // namespace filament
|
||||
|
||||
#endif // TNT_FILAMENT_TONE_MAPPER_H
|
||||
310
ios/include/filament/TransformManager.h
Normal file
310
ios/include/filament/TransformManager.h
Normal file
@@ -0,0 +1,310 @@
|
||||
/*
|
||||
* 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_FILAMENT_TRANSFORMMANAGER_H
|
||||
#define TNT_FILAMENT_TRANSFORMMANAGER_H
|
||||
|
||||
#include <filament/FilamentAPI.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/EntityInstance.h>
|
||||
|
||||
#include <math/mathfwd.h>
|
||||
|
||||
#include <iterator>
|
||||
|
||||
|
||||
namespace utils {
|
||||
class Entity;
|
||||
} // namespace utils
|
||||
|
||||
namespace filament {
|
||||
|
||||
class FTransformManager;
|
||||
|
||||
/**
|
||||
* TransformManager is used to add transform components to entities.
|
||||
*
|
||||
* A Transform component gives an entity a position and orientation in space in the coordinate
|
||||
* space of its parent transform. The TransformManager takes care of computing the world-space
|
||||
* transform of each component (i.e. its transform relative to the root).
|
||||
*
|
||||
* Creation and destruction
|
||||
* ========================
|
||||
*
|
||||
* A transform component is created using TransformManager::create() and destroyed by calling
|
||||
* TransformManager::destroy().
|
||||
*
|
||||
* ~~~~~~~~~~~{.cpp}
|
||||
* filament::Engine* engine = filament::Engine::create();
|
||||
* utils::Entity object = utils::EntityManager.get().create();
|
||||
*
|
||||
* auto& tcm = engine->getTransformManager();
|
||||
*
|
||||
* // create the transform component
|
||||
* tcm.create(object);
|
||||
*
|
||||
* // set its transform
|
||||
* auto i = tcm.getInstance(object);
|
||||
* tcm.setTransform(i, mat4f::translation({ 0, 0, -1 }));
|
||||
*
|
||||
* // destroy the transform component
|
||||
* tcm.destroy(object);
|
||||
* ~~~~~~~~~~~
|
||||
*
|
||||
*/
|
||||
class UTILS_PUBLIC TransformManager : public FilamentAPI {
|
||||
public:
|
||||
using Instance = utils::EntityInstance<TransformManager>;
|
||||
|
||||
class children_iterator : std::iterator<std::forward_iterator_tag, Instance> {
|
||||
friend class FTransformManager;
|
||||
TransformManager const& mManager;
|
||||
Instance mInstance;
|
||||
children_iterator(TransformManager const& mgr, Instance instance) noexcept
|
||||
: mManager(mgr), mInstance(instance) { }
|
||||
public:
|
||||
children_iterator& operator++();
|
||||
|
||||
children_iterator operator++(int) { // NOLINT
|
||||
children_iterator ret(*this);
|
||||
++(*this);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool operator == (const children_iterator& other) const noexcept {
|
||||
return mInstance == other.mInstance;
|
||||
}
|
||||
|
||||
bool operator != (const children_iterator& other) const noexcept {
|
||||
return mInstance != other.mInstance;
|
||||
}
|
||||
|
||||
value_type operator*() const { return mInstance; }
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns whether a particular Entity is associated with a component of this TransformManager
|
||||
* @param e An Entity.
|
||||
* @return true if this Entity has a component associated with this manager.
|
||||
*/
|
||||
bool hasComponent(utils::Entity e) const noexcept;
|
||||
|
||||
/**
|
||||
* Gets an Instance representing the transform component associated with the given Entity.
|
||||
* @param e An Entity.
|
||||
* @return An Instance object, which represents the transform component associated with the Entity e.
|
||||
* @note Use Instance::isValid() to make sure the component exists.
|
||||
* @see hasComponent()
|
||||
*/
|
||||
Instance getInstance(utils::Entity e) const noexcept;
|
||||
|
||||
/**
|
||||
* Enables or disable the accurate translation mode. Disabled by default.
|
||||
*
|
||||
* When accurate translation mode is active, the translation component of all transforms is
|
||||
* maintained at double precision. This is only useful if the mat4 version of setTransform()
|
||||
* is used, as well as getTransformAccurate().
|
||||
*
|
||||
* @param enable true to enable the accurate translation mode, false to disable.
|
||||
*
|
||||
* @see isAccurateTranslationsEnabled
|
||||
* @see create(utils::Entity, Instance, const math::mat4&);
|
||||
* @see setTransform(Instance, const math::mat4&)
|
||||
* @see getTransformAccurate
|
||||
* @see getWorldTransformAccurate
|
||||
*/
|
||||
void setAccurateTranslationsEnabled(bool enable) noexcept;
|
||||
|
||||
/**
|
||||
* Returns whether the high precision translation mode is active.
|
||||
* @return true if accurate translations mode is active, false otherwise
|
||||
* @see setAccurateTranslationsEnabled
|
||||
*/
|
||||
bool isAccurateTranslationsEnabled() const noexcept;
|
||||
|
||||
/**
|
||||
* Creates a transform component and associate it with the given entity.
|
||||
* @param entity An Entity to associate a transform component to.
|
||||
* @param parent The Instance of the parent transform, or Instance{} if no parent.
|
||||
* @param localTransform The transform to initialize the transform component with.
|
||||
* This is always relative to the parent.
|
||||
*
|
||||
* If this component already exists on the given entity, it is first destroyed as if
|
||||
* destroy(utils::Entity e) was called.
|
||||
*
|
||||
* @see destroy()
|
||||
*/
|
||||
void create(utils::Entity entity, Instance parent, const math::mat4f& localTransform);
|
||||
void create(utils::Entity entity, Instance parent, const math::mat4& localTransform); //!< \overload
|
||||
void create(utils::Entity entity, Instance parent = {}); //!< \overload
|
||||
|
||||
/**
|
||||
* Destroys this component from the given entity, children are orphaned.
|
||||
* @param e An entity.
|
||||
*
|
||||
* @note If this transform had children, these are orphaned, which means their local
|
||||
* transform becomes a world transform. Usually it's nonsensical. It's recommended to make
|
||||
* sure that a destroyed transform doesn't have children.
|
||||
*
|
||||
* @see create()
|
||||
*/
|
||||
void destroy(utils::Entity e) noexcept;
|
||||
|
||||
/**
|
||||
* Re-parents an entity to a new one.
|
||||
* @param i The instance of the transform component to re-parent
|
||||
* @param newParent The instance of the new parent transform
|
||||
* @attention It is an error to re-parent an entity to a descendant and will cause undefined behaviour.
|
||||
* @see getInstance()
|
||||
*/
|
||||
void setParent(Instance i, Instance newParent) noexcept;
|
||||
|
||||
/**
|
||||
* Returns the parent of a transform component, or the null entity if it is a root.
|
||||
* @param i The instance of the transform component to query.
|
||||
*/
|
||||
utils::Entity getParent(Instance i) const noexcept;
|
||||
|
||||
/**
|
||||
* Returns the number of children of a transform component.
|
||||
* @param i The instance of the transform component to query.
|
||||
* @return The number of children of the queried component.
|
||||
*/
|
||||
size_t getChildCount(Instance i) const noexcept;
|
||||
|
||||
/**
|
||||
* Gets a list of children for a transform component.
|
||||
*
|
||||
* @param i The instance of the transform component to query.
|
||||
* @param children Pointer to array-of-Entity. The array must have at least "count" elements.
|
||||
* @param count The maximum number of children to retrieve.
|
||||
* @return The number of children written to the pointer.
|
||||
*/
|
||||
size_t getChildren(Instance i, utils::Entity* children, size_t count) const noexcept;
|
||||
|
||||
/**
|
||||
* Returns an iterator to the Instance of the first child of the given parent.
|
||||
*
|
||||
* @param parent Instance of the parent
|
||||
* @return A forward iterator pointing to the first child of the given parent.
|
||||
*
|
||||
* A child_iterator can only safely be dereferenced if it's different from getChildrenEnd(parent)
|
||||
*/
|
||||
children_iterator getChildrenBegin(Instance parent) const noexcept;
|
||||
|
||||
/**
|
||||
* Returns an undreferencable iterator representing the end of the children list
|
||||
*
|
||||
* @param parent Instance of the parent
|
||||
* @return A forward iterator.
|
||||
*
|
||||
* This iterator cannot be dereferenced
|
||||
*/
|
||||
children_iterator getChildrenEnd(Instance parent) const noexcept;
|
||||
|
||||
/**
|
||||
* Sets a local transform of a transform component.
|
||||
* @param ci The instance of the transform component to set the local transform to.
|
||||
* @param localTransform The local transform (i.e. relative to the parent).
|
||||
* @see getTransform()
|
||||
* @attention This operation can be slow if the hierarchy of transform is too deep, and this
|
||||
* will be particularly bad when updating a lot of transforms. In that case,
|
||||
* consider using openLocalTransformTransaction() / commitLocalTransformTransaction().
|
||||
*/
|
||||
void setTransform(Instance ci, const math::mat4f& localTransform) noexcept;
|
||||
|
||||
/**
|
||||
* Sets a local transform of a transform component and keeps double precision translation.
|
||||
* All other values of the transform are stored at single precision.
|
||||
* @param ci The instance of the transform component to set the local transform to.
|
||||
* @param localTransform The local transform (i.e. relative to the parent).
|
||||
* @see getTransform()
|
||||
* @attention This operation can be slow if the hierarchy of transform is too deep, and this
|
||||
* will be particularly bad when updating a lot of transforms. In that case,
|
||||
* consider using openLocalTransformTransaction() / commitLocalTransformTransaction().
|
||||
*/
|
||||
void setTransform(Instance ci, const math::mat4& localTransform) noexcept;
|
||||
|
||||
/**
|
||||
* Returns the local transform of a transform component.
|
||||
* @param ci The instance of the transform component to query the local transform from.
|
||||
* @return The local transform of the component (i.e. relative to the parent). This always
|
||||
* returns the value set by setTransform().
|
||||
* @see setTransform()
|
||||
*/
|
||||
const math::mat4f& getTransform(Instance ci) const noexcept;
|
||||
|
||||
/**
|
||||
* Returns the local transform of a transform component.
|
||||
* @param ci The instance of the transform component to query the local transform from.
|
||||
* @return The local transform of the component (i.e. relative to the parent). This always
|
||||
* returns the value set by setTransform().
|
||||
* @see setTransform()
|
||||
*/
|
||||
const math::mat4 getTransformAccurate(Instance ci) const noexcept;
|
||||
|
||||
/**
|
||||
* Return the world transform of a transform component.
|
||||
* @param ci The instance of the transform component to query the world transform from.
|
||||
* @return The world transform of the component (i.e. relative to the root). This is the
|
||||
* composition of this component's local transform with its parent's world transform.
|
||||
* @see setTransform()
|
||||
*/
|
||||
const math::mat4f& getWorldTransform(Instance ci) const noexcept;
|
||||
|
||||
/**
|
||||
* Return the world transform of a transform component.
|
||||
* @param ci The instance of the transform component to query the world transform from.
|
||||
* @return The world transform of the component (i.e. relative to the root). This is the
|
||||
* composition of this component's local transform with its parent's world transform.
|
||||
* @see setTransform()
|
||||
*/
|
||||
const math::mat4 getWorldTransformAccurate(Instance ci) const noexcept;
|
||||
|
||||
/**
|
||||
* Opens a local transform transaction. During a transaction, getWorldTransform() can
|
||||
* return an invalid transform until commitLocalTransformTransaction() is called. However,
|
||||
* setTransform() will perform significantly better and in constant time.
|
||||
*
|
||||
* This is useful when updating many transforms and the transform hierarchy is deep (say more
|
||||
* than 4 or 5 levels).
|
||||
*
|
||||
* @note If the local transform transaction is already open, this is a no-op.
|
||||
*
|
||||
* @see commitLocalTransformTransaction(), setTransform()
|
||||
*/
|
||||
void openLocalTransformTransaction() noexcept;
|
||||
|
||||
/**
|
||||
* Commits the currently open local transform transaction. When this returns, calls
|
||||
* to getWorldTransform() will return the proper value.
|
||||
*
|
||||
* @attention failing to call this method when done updating the local transform will cause
|
||||
* a lot of rendering problems. The system never closes the transaction
|
||||
* automatically.
|
||||
*
|
||||
* @note If the local transform transaction is not open, this is a no-op.
|
||||
*
|
||||
* @see openLocalTransformTransaction(), setTransform()
|
||||
*/
|
||||
void commitLocalTransformTransaction() noexcept;
|
||||
};
|
||||
|
||||
} // namespace filament
|
||||
|
||||
|
||||
#endif // TNT_TRANSFORMMANAGER_H
|
||||
201
ios/include/filament/VertexBuffer.h
Normal file
201
ios/include/filament/VertexBuffer.h
Normal file
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef TNT_FILAMENT_VERTEXBUFFER_H
|
||||
#define TNT_FILAMENT_VERTEXBUFFER_H
|
||||
|
||||
#include <filament/FilamentAPI.h>
|
||||
#include <filament/MaterialEnums.h>
|
||||
|
||||
#include <backend/BufferDescriptor.h>
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
namespace filament {
|
||||
|
||||
class FVertexBuffer;
|
||||
|
||||
class BufferObject;
|
||||
class Engine;
|
||||
|
||||
/**
|
||||
* Holds a set of buffers that define the geometry of a Renderable.
|
||||
*
|
||||
* The geometry of the Renderable itself is defined by a set of vertex attributes such as
|
||||
* position, color, normals, tangents, etc...
|
||||
*
|
||||
* There is no need to have a 1-to-1 mapping between attributes and buffer. A buffer can hold the
|
||||
* data of several attributes -- attributes are then referred as being "interleaved".
|
||||
*
|
||||
* The buffers themselves are GPU resources, therefore mutating their data can be relatively slow.
|
||||
* For this reason, it is best to separate the constant data from the dynamic data into multiple
|
||||
* buffers.
|
||||
*
|
||||
* It is possible, and even encouraged, to use a single vertex buffer for several Renderables.
|
||||
*
|
||||
* @see IndexBuffer, RenderableManager
|
||||
*/
|
||||
class UTILS_PUBLIC VertexBuffer : public FilamentAPI {
|
||||
struct BuilderDetails;
|
||||
|
||||
public:
|
||||
using AttributeType = backend::ElementType;
|
||||
using BufferDescriptor = backend::BufferDescriptor;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* Defines how many buffers will be created in this vertex buffer set. These buffers are
|
||||
* later referenced by index from 0 to \p bufferCount - 1.
|
||||
*
|
||||
* This call is mandatory. The default is 0.
|
||||
*
|
||||
* @param bufferCount Number of buffers in this vertex buffer set. The maximum value is 8.
|
||||
* @return A reference to this Builder for chaining calls.
|
||||
*/
|
||||
Builder& bufferCount(uint8_t bufferCount) noexcept;
|
||||
|
||||
/**
|
||||
* Size of each buffer in the set in vertex.
|
||||
*
|
||||
* @param vertexCount Number of vertices in each buffer in this set.
|
||||
* @return A reference to this Builder for chaining calls.
|
||||
*/
|
||||
Builder& vertexCount(uint32_t vertexCount) noexcept;
|
||||
|
||||
/**
|
||||
* Allows buffers to be swapped out and shared using BufferObject.
|
||||
*
|
||||
* If buffer objects mode is enabled, clients must call setBufferObjectAt rather than
|
||||
* setBufferAt. This allows sharing of data between VertexBuffer objects, but it may
|
||||
* slightly increase the memory footprint of Filament's internal bookkeeping.
|
||||
*
|
||||
* @param enabled If true, enables buffer object mode. False by default.
|
||||
*/
|
||||
Builder& enableBufferObjects(bool enabled = true) noexcept;
|
||||
|
||||
/**
|
||||
* Sets up an attribute for this vertex buffer set.
|
||||
*
|
||||
* Using \p byteOffset and \p byteStride, attributes can be interleaved in the same buffer.
|
||||
*
|
||||
* @param attribute The attribute to set up.
|
||||
* @param bufferIndex The index of the buffer containing the data for this attribute. Must
|
||||
* be between 0 and bufferCount() - 1.
|
||||
* @param attributeType The type of the attribute data (e.g. byte, float3, etc...)
|
||||
* @param byteOffset Offset in *bytes* into the buffer \p bufferIndex
|
||||
* @param byteStride Stride in *bytes* to the next element of this attribute. When set to
|
||||
* zero the attribute size, as defined by \p attributeType is used.
|
||||
*
|
||||
* @return A reference to this Builder for chaining calls.
|
||||
*
|
||||
* @warning VertexAttribute::TANGENTS must be specified as a quaternion and is how normals
|
||||
* are specified.
|
||||
*
|
||||
* @warning Not all backends support 3-component attributes that are not floats. For help
|
||||
* with conversion, see geometry::Transcoder.
|
||||
*
|
||||
* @see VertexAttribute
|
||||
*
|
||||
* This is a no-op if the \p attribute is an invalid enum.
|
||||
* This is a no-op if the \p bufferIndex is out of bounds.
|
||||
*
|
||||
*/
|
||||
Builder& attribute(VertexAttribute attribute, uint8_t bufferIndex,
|
||||
AttributeType attributeType,
|
||||
uint32_t byteOffset = 0, uint8_t byteStride = 0) noexcept;
|
||||
|
||||
/**
|
||||
* Sets whether a given attribute should be normalized. By default attributes are not
|
||||
* normalized. A normalized attribute is mapped between 0 and 1 in the shader. This applies
|
||||
* only to integer types.
|
||||
*
|
||||
* @param attribute Enum of the attribute to set the normalization flag to.
|
||||
* @param normalize true to automatically normalize the given attribute.
|
||||
* @return A reference to this Builder for chaining calls.
|
||||
*
|
||||
* This is a no-op if the \p attribute is an invalid enum.
|
||||
*/
|
||||
Builder& normalized(VertexAttribute attribute, bool normalize = true) noexcept;
|
||||
|
||||
/**
|
||||
* Creates the VertexBuffer object and returns a pointer to it.
|
||||
*
|
||||
* @param engine Reference to the filament::Engine to associate this VertexBuffer 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.
|
||||
*/
|
||||
VertexBuffer* build(Engine& engine);
|
||||
|
||||
private:
|
||||
friend class FVertexBuffer;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the vertex count.
|
||||
* @return Number of vertices in this vertex buffer set.
|
||||
*/
|
||||
size_t getVertexCount() const noexcept;
|
||||
|
||||
/**
|
||||
* Asynchronously copy-initializes the specified buffer from the given buffer data.
|
||||
*
|
||||
* Do not use this if you called enableBufferObjects() on the Builder.
|
||||
*
|
||||
* @param engine Reference to the filament::Engine to associate this VertexBuffer with.
|
||||
* @param bufferIndex Index of the buffer to initialize. Must be between 0
|
||||
* and Builder::bufferCount() - 1.
|
||||
* @param buffer A BufferDescriptor representing the data used to initialize the buffer at
|
||||
* index \p bufferIndex. BufferDescriptor points to raw, untyped data that will
|
||||
* be copied as-is into the buffer.
|
||||
* @param byteOffset Offset in *bytes* into the buffer at index \p bufferIndex of this vertex
|
||||
* buffer set.
|
||||
*/
|
||||
void setBufferAt(Engine& engine, uint8_t bufferIndex, BufferDescriptor&& buffer,
|
||||
uint32_t byteOffset = 0);
|
||||
|
||||
/**
|
||||
* Swaps in the given buffer object.
|
||||
*
|
||||
* To use this, you must first call enableBufferObjects() on the Builder.
|
||||
*
|
||||
* @param engine Reference to the filament::Engine to associate this VertexBuffer with.
|
||||
* @param bufferIndex Index of the buffer to initialize. Must be between 0
|
||||
* and Builder::bufferCount() - 1.
|
||||
* @param bufferObject The handle to the GPU data that will be used in this buffer slot.
|
||||
*/
|
||||
void setBufferObjectAt(Engine& engine, uint8_t bufferIndex, BufferObject const* bufferObject);
|
||||
};
|
||||
|
||||
} // namespace filament
|
||||
|
||||
#endif // TNT_FILAMENT_VERTEXBUFFER_H
|
||||
911
ios/include/filament/View.h
Normal file
911
ios/include/filament/View.h
Normal file
@@ -0,0 +1,911 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef TNT_FILAMENT_VIEW_H
|
||||
#define TNT_FILAMENT_VIEW_H
|
||||
|
||||
#include <filament/Color.h>
|
||||
#include <filament/FilamentAPI.h>
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <math/mathfwd.h>
|
||||
|
||||
namespace filament {
|
||||
|
||||
class Camera;
|
||||
class ColorGrading;
|
||||
class MaterialInstance;
|
||||
class RenderTarget;
|
||||
class Scene;
|
||||
class Texture;
|
||||
class Viewport;
|
||||
|
||||
/**
|
||||
* A View encompasses all the state needed for rendering a Scene.
|
||||
*
|
||||
* Renderer::render() operates on View objects. These View objects specify important parameters
|
||||
* such as:
|
||||
* - The Scene
|
||||
* - The Camera
|
||||
* - The Viewport
|
||||
* - Some rendering parameters
|
||||
*
|
||||
* \note
|
||||
* View instances are heavy objects that internally cache a lot of data needed for rendering.
|
||||
* It is not advised for an application to use many View objects.
|
||||
*
|
||||
* For example, in a game, a View could be used for the main scene and another one for the
|
||||
* game's user interface. More View instances could be used for creating special effects (e.g.
|
||||
* a View is akin to a rendering pass).
|
||||
*
|
||||
*
|
||||
* @see Renderer, Scene, Camera, RenderTarget
|
||||
*/
|
||||
class UTILS_PUBLIC View : public FilamentAPI {
|
||||
public:
|
||||
enum class QualityLevel : uint8_t {
|
||||
LOW,
|
||||
MEDIUM,
|
||||
HIGH,
|
||||
ULTRA
|
||||
};
|
||||
|
||||
enum class BlendMode : uint8_t {
|
||||
OPAQUE,
|
||||
TRANSLUCENT
|
||||
};
|
||||
|
||||
/**
|
||||
* Dynamic resolution can be used to either reach a desired target frame rate
|
||||
* by lowering the resolution of a View, or to increase the quality when the
|
||||
* rendering is faster than the target frame rate.
|
||||
*
|
||||
* This structure can be used to specify the minimum scale factor used when
|
||||
* lowering the resolution of a View, and the maximum scale factor used when
|
||||
* increasing the resolution for higher quality rendering. The scale factors
|
||||
* can be controlled on each X and Y axis independently. By default, all scale
|
||||
* factors are set to 1.0.
|
||||
*
|
||||
* enabled: enable or disables dynamic resolution on a View
|
||||
*
|
||||
* homogeneousScaling: by default the system scales the major axis first. Set this to true
|
||||
* to force homogeneous scaling.
|
||||
*
|
||||
* minScale: the minimum scale in X and Y this View should use
|
||||
*
|
||||
* maxScale: the maximum scale in X and Y this View should use
|
||||
*
|
||||
* quality: upscaling quality.
|
||||
* LOW: 1 bilinear tap, Medium: 4 bilinear taps, High: 9 bilinear taps (tent)
|
||||
*
|
||||
* \note
|
||||
* Dynamic resolution is only supported on platforms where the time to render
|
||||
* a frame can be measured accurately. Dynamic resolution is currently only
|
||||
* supported on Android.
|
||||
*
|
||||
* @see Renderer::FrameRateOptions
|
||||
*
|
||||
*/
|
||||
struct DynamicResolutionOptions {
|
||||
math::float2 minScale = math::float2(0.5f); //!< minimum scale factors in x and y
|
||||
math::float2 maxScale = math::float2(1.0f); //!< maximum scale factors in x and y
|
||||
bool enabled = false; //!< enable or disable dynamic resolution
|
||||
bool homogeneousScaling = false; //!< set to true to force homogeneous scaling
|
||||
QualityLevel quality = QualityLevel::LOW; //!< Upscaling quality
|
||||
};
|
||||
|
||||
/**
|
||||
* Options to control the bloom effect
|
||||
*
|
||||
* enabled: Enable or disable the bloom post-processing effect. Disabled by default.
|
||||
*
|
||||
* levels: Number of successive blurs to achieve the blur effect, the minimum is 3 and the
|
||||
* maximum is 12. This value together with resolution influences the spread of the
|
||||
* blur effect. This value can be silently reduced to accommodate the original
|
||||
* image size.
|
||||
*
|
||||
* resolution: Resolution of bloom's minor axis. The minimum value is 2^levels and the
|
||||
* the maximum is lower of the original resolution and 4096. This parameter is
|
||||
* silently clamped to the minimum and maximum.
|
||||
* It is highly recommended that this value be smaller than the target resolution
|
||||
* after dynamic resolution is applied (horizontally and vertically).
|
||||
*
|
||||
* strength: how much of the bloom is added to the original image. Between 0 and 1.
|
||||
*
|
||||
* blendMode: Whether the bloom effect is purely additive (false) or mixed with the original
|
||||
* image (true).
|
||||
*
|
||||
* anamorphism: Bloom's aspect ratio (x/y), for artistic purposes.
|
||||
*
|
||||
* threshold: When enabled, a threshold at 1.0 is applied on the source image, this is
|
||||
* useful for artistic reasons and is usually needed when a dirt texture is used.
|
||||
*
|
||||
* dirt: A dirt/scratch/smudges texture (that can be RGB), which gets added to the
|
||||
* bloom effect. Smudges are visible where bloom occurs. Threshold must be
|
||||
* enabled for the dirt effect to work properly.
|
||||
*
|
||||
* dirtStrength: Strength of the dirt texture.
|
||||
*/
|
||||
struct BloomOptions {
|
||||
enum class BlendMode : uint8_t {
|
||||
ADD, //!< Bloom is modulated by the strength parameter and added to the scene
|
||||
INTERPOLATE //!< Bloom is interpolated with the scene using the strength parameter
|
||||
};
|
||||
Texture* dirt = nullptr; //!< user provided dirt texture
|
||||
float dirtStrength = 0.2f; //!< strength of the dirt texture
|
||||
float strength = 0.10f; //!< bloom's strength between 0.0 and 1.0
|
||||
uint32_t resolution = 360; //!< resolution of vertical axis (2^levels to 2048)
|
||||
float anamorphism = 1.0f; //!< bloom x/y aspect-ratio (1/32 to 32)
|
||||
uint8_t levels = 6; //!< number of blur levels (3 to 11)
|
||||
BlendMode blendMode = BlendMode::ADD; //!< how the bloom effect is applied
|
||||
bool threshold = true; //!< whether to threshold the source
|
||||
bool enabled = false; //!< enable or disable bloom
|
||||
float highlight = 1000.0f; //!< limit highlights to this value before bloom [10, +inf]
|
||||
|
||||
bool lensFlare = false; //!< enable screen-space lens flare
|
||||
bool starburst = true; //!< enable starburst effect on lens flare
|
||||
float chromaticAberration = 0.005f; //!< amount of chromatic aberration
|
||||
uint8_t ghostCount = 4; //!< number of flare "ghosts"
|
||||
float ghostSpacing = 0.6f; //!< spacing of the ghost in screen units [0, 1[
|
||||
float ghostThreshold = 10.0f; //!< hdr threshold for the ghosts
|
||||
float haloThickness = 0.1f; //!< thickness of halo in vertical screen units, 0 to disable
|
||||
float haloRadius = 0.4f; //!< radius of halo in vertical screen units [0, 0.5]
|
||||
float haloThreshold = 10.0f; //!< hdr threshold for the halo
|
||||
};
|
||||
|
||||
/**
|
||||
* Options to control fog in the scene
|
||||
*/
|
||||
struct FogOptions {
|
||||
float distance = 0.0f; //!< distance in world units from the camera where the fog starts ( >= 0.0 )
|
||||
float maximumOpacity = 1.0f; //!< fog's maximum opacity between 0 and 1
|
||||
float height = 0.0f; //!< fog's floor in world units
|
||||
float heightFalloff = 1.0f; //!< how fast fog dissipates with altitude
|
||||
LinearColor color{0.5f}; //!< fog's color (linear), see fogColorFromIbl
|
||||
float density = 0.1f; //!< fog's density at altitude given by 'height'
|
||||
float inScatteringStart = 0.0f; //!< distance in world units from the camera where in-scattering starts
|
||||
float inScatteringSize = -1.0f; //!< size of in-scattering (>0 to activate). Good values are >> 1 (e.g. ~10 - 100).
|
||||
bool fogColorFromIbl = false; //!< Fog color will be modulated by the IBL color in the view direction.
|
||||
bool enabled = false; //!< enable or disable fog
|
||||
};
|
||||
|
||||
/**
|
||||
* Options to control Depth of Field (DoF) effect in the scene.
|
||||
*
|
||||
* cocScale can be used to set the depth of field blur independently from the camera
|
||||
* aperture, e.g. for artistic reasons. This can be achieved by setting:
|
||||
* cocScale = cameraAperture / desiredDoFAperture
|
||||
*
|
||||
* @see Camera
|
||||
*/
|
||||
struct DepthOfFieldOptions {
|
||||
enum class Filter : uint8_t {
|
||||
NONE = 0,
|
||||
MEDIAN = 2
|
||||
};
|
||||
float cocScale = 1.0f; //!< circle of confusion scale factor (amount of blur)
|
||||
float maxApertureDiameter = 0.01f; //!< maximum aperture diameter in meters (zero to disable rotation)
|
||||
bool enabled = false; //!< enable or disable depth of field effect
|
||||
Filter filter = Filter::MEDIAN; //!< filter to use for filling gaps in the kernel
|
||||
bool nativeResolution = false; //!< perform DoF processing at native resolution
|
||||
/**
|
||||
* Number of of rings used by the gather kernels. The number of rings affects quality
|
||||
* and performance. The actual number of sample per pixel is defined
|
||||
* as (ringCount * 2 - 1)^2. Here are a few commonly used values:
|
||||
* 3 rings : 25 ( 5x 5 grid)
|
||||
* 4 rings : 49 ( 7x 7 grid)
|
||||
* 5 rings : 81 ( 9x 9 grid)
|
||||
* 17 rings : 1089 (33x33 grid)
|
||||
*
|
||||
* With a maximum circle-of-confusion of 32, it is never necessary to use more than 17 rings.
|
||||
*
|
||||
* Usually all three settings below are set to the same value, however, it is often
|
||||
* acceptable to use a lower ring count for the "fast tiles", which improves performance.
|
||||
* Fast tiles are regions of the screen where every pixels have a similar
|
||||
* circle-of-confusion radius.
|
||||
*
|
||||
* A value of 0 means default, which is 5 on desktop and 3 on mobile.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
uint8_t foregroundRingCount = 0; //!< number of kernel rings for foreground tiles
|
||||
uint8_t backgroundRingCount = 0; //!< number of kernel rings for background tiles
|
||||
uint8_t fastGatherRingCount = 0; //!< number of kernel rings for fast tiles
|
||||
/** @}*/
|
||||
|
||||
/**
|
||||
* maximum circle-of-confusion in pixels for the foreground, must be in [0, 32] range.
|
||||
* A value of 0 means default, which is 32 on desktop and 24 on mobile.
|
||||
*/
|
||||
uint16_t maxForegroundCOC = 0;
|
||||
|
||||
/**
|
||||
* maximum circle-of-confusion in pixels for the background, must be in [0, 32] range.
|
||||
* A value of 0 means default, which is 32 on desktop and 24 on mobile.
|
||||
*/
|
||||
uint16_t maxBackgroundCOC = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Options to control the vignetting effect.
|
||||
*/
|
||||
struct VignetteOptions {
|
||||
float midPoint = 0.5f; //!< high values restrict the vignette closer to the corners, between 0 and 1
|
||||
float roundness = 0.5f; //!< controls the shape of the vignette, from a rounded rectangle (0.0), to an oval (0.5), to a circle (1.0)
|
||||
float feather = 0.5f; //!< softening amount of the vignette effect, between 0 and 1
|
||||
LinearColorA color{0.0f, 0.0f, 0.0f, 1.0f}; //!< color of the vignette effect, alpha is currently ignored
|
||||
bool enabled = false; //!< enables or disables the vignette effect
|
||||
};
|
||||
|
||||
/**
|
||||
* Structure used to set the precision of the color buffer and related quality settings.
|
||||
*
|
||||
* @see setRenderQuality, getRenderQuality
|
||||
*/
|
||||
struct RenderQuality {
|
||||
/**
|
||||
* Sets the quality of the HDR color buffer.
|
||||
*
|
||||
* A quality of HIGH or ULTRA means using an RGB16F or RGBA16F color buffer. This means
|
||||
* colors in the LDR range (0..1) have a 10 bit precision. A quality of LOW or MEDIUM means
|
||||
* using an R11G11B10F opaque color buffer or an RGBA16F transparent color buffer. With
|
||||
* R11G11B10F colors in the LDR range have a precision of either 6 bits (red and green
|
||||
* channels) or 5 bits (blue channel).
|
||||
*/
|
||||
QualityLevel hdrColorBuffer = QualityLevel::HIGH;
|
||||
};
|
||||
|
||||
/**
|
||||
* Options for screen space Ambient Occlusion (SSAO) and Screen Space Cone Tracing (SSCT)
|
||||
* @see setAmbientOcclusionOptions()
|
||||
*/
|
||||
struct AmbientOcclusionOptions {
|
||||
float radius = 0.3f; //!< Ambient Occlusion radius in meters, between 0 and ~10.
|
||||
float power = 1.0f; //!< Controls ambient occlusion's contrast. Must be positive.
|
||||
float bias = 0.0005f; //!< Self-occlusion bias in meters. Use to avoid self-occlusion. Between 0 and a few mm.
|
||||
float resolution = 0.5f;//!< How each dimension of the AO buffer is scaled. Must be either 0.5 or 1.0.
|
||||
float intensity = 1.0f; //!< Strength of the Ambient Occlusion effect.
|
||||
float bilateralThreshold = 0.05f; //!< depth distance that constitute an edge for filtering
|
||||
QualityLevel quality = QualityLevel::LOW; //!< affects # of samples used for AO.
|
||||
QualityLevel lowPassFilter = QualityLevel::MEDIUM; //!< affects AO smoothness
|
||||
QualityLevel upsampling = QualityLevel::LOW; //!< affects AO buffer upsampling quality
|
||||
bool enabled = false; //!< enables or disables screen-space ambient occlusion
|
||||
bool bentNormals = false; //!< enables bent normals computation from AO, and specular AO
|
||||
float minHorizonAngleRad = 0.0f; //!< min angle in radian to consider
|
||||
/**
|
||||
* Screen Space Cone Tracing (SSCT) options
|
||||
* Ambient shadows from dominant light
|
||||
*/
|
||||
struct Ssct {
|
||||
float lightConeRad = 1.0f; //!< full cone angle in radian, between 0 and pi/2
|
||||
float shadowDistance = 0.3f; //!< how far shadows can be cast
|
||||
float contactDistanceMax = 1.0f; //!< max distance for contact
|
||||
float intensity = 0.8f; //!< intensity
|
||||
math::float3 lightDirection{ 0, -1, 0 }; //!< light direction
|
||||
float depthBias = 0.01f; //!< depth bias in world units (mitigate self shadowing)
|
||||
float depthSlopeBias = 0.01f; //!< depth slope bias (mitigate self shadowing)
|
||||
uint8_t sampleCount = 4; //!< tracing sample count, between 1 and 255
|
||||
uint8_t rayCount = 1; //!< # of rays to trace, between 1 and 255
|
||||
bool enabled = false; //!< enables or disables SSCT
|
||||
} ssct;
|
||||
};
|
||||
|
||||
/**
|
||||
* Options for Temporal Anti-aliasing (TAA)
|
||||
* @see setTemporalAntiAliasingOptions()
|
||||
*/
|
||||
struct TemporalAntiAliasingOptions {
|
||||
float filterWidth = 1.0f; //!< reconstruction filter width typically between 0 (sharper, aliased) and 1 (smoother)
|
||||
float feedback = 0.04f; //!< history feedback, between 0 (maximum temporal AA) and 1 (no temporal AA).
|
||||
bool enabled = false; //!< enables or disables temporal anti-aliasing
|
||||
};
|
||||
|
||||
/**
|
||||
* List of available post-processing anti-aliasing techniques.
|
||||
* @see setAntiAliasing, getAntiAliasing, setSampleCount
|
||||
*/
|
||||
enum class AntiAliasing : uint8_t {
|
||||
NONE = 0, //!< no anti aliasing performed as part of post-processing
|
||||
FXAA = 1 //!< FXAA is a low-quality but very efficient type of anti-aliasing. (default).
|
||||
};
|
||||
|
||||
/**
|
||||
* List of available post-processing dithering techniques.
|
||||
*/
|
||||
enum class Dithering : uint8_t {
|
||||
NONE = 0, //!< No dithering
|
||||
TEMPORAL = 1 //!< Temporal dithering (default)
|
||||
};
|
||||
|
||||
/**
|
||||
* List of available shadow mapping techniques.
|
||||
* @see setShadowType
|
||||
*/
|
||||
enum class ShadowType : uint8_t {
|
||||
PCF, //!< percentage-closer filtered shadows (default)
|
||||
VSM //!< variance shadows
|
||||
};
|
||||
|
||||
/**
|
||||
* View-level options for VSM Shadowing.
|
||||
* @see setVsmShadowOptions()
|
||||
* @warning This API is still experimental and subject to change.
|
||||
*/
|
||||
struct VsmShadowOptions {
|
||||
/**
|
||||
* Sets the number of anisotropic samples to use when sampling a VSM shadow map. If greater
|
||||
* than 0, mipmaps will automatically be generated each frame for all lights.
|
||||
*
|
||||
* The number of anisotropic samples = 2 ^ vsmAnisotropy.
|
||||
*/
|
||||
uint8_t anisotropy = 0;
|
||||
|
||||
/**
|
||||
* Whether to generate mipmaps for all VSM shadow maps.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
float minVarianceScale = 0.5f;
|
||||
|
||||
/**
|
||||
* VSM light bleeding reduction amount, between 0 and 1.
|
||||
*/
|
||||
float lightBleedReduction = 0.15f;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the View's name. Only useful for debugging.
|
||||
* @param name Pointer to the View's name. The string is copied.
|
||||
*/
|
||||
void setName(const char* name) noexcept;
|
||||
|
||||
/**
|
||||
* Returns the View's name
|
||||
*
|
||||
* @return a pointer owned by the View instance to the View's name.
|
||||
*
|
||||
* @attention Do *not* free the pointer or modify its content.
|
||||
*/
|
||||
const char* getName() const noexcept;
|
||||
|
||||
/**
|
||||
* Set this View instance's Scene.
|
||||
*
|
||||
* @param scene Associate the specified Scene to this View. A Scene can be associated to
|
||||
* several View instances.\n
|
||||
* \p scene can be nullptr to dissociate the currently set Scene
|
||||
* from this View.\n
|
||||
* The View doesn't take ownership of the Scene pointer (which
|
||||
* acts as a reference).
|
||||
*
|
||||
* @note
|
||||
* There is no reference-counting.
|
||||
* Make sure to dissociate a Scene from all Views before destroying it.
|
||||
*/
|
||||
void setScene(Scene* scene);
|
||||
|
||||
/**
|
||||
* Returns the Scene currently associated with this View.
|
||||
* @return A pointer to the Scene associated to this View. nullptr if no Scene is set.
|
||||
*/
|
||||
Scene* getScene() noexcept;
|
||||
|
||||
/**
|
||||
* Returns the Scene currently associated with this View.
|
||||
* @return A pointer to the Scene associated to this View. nullptr if no Scene is set.
|
||||
*/
|
||||
Scene const* getScene() const noexcept {
|
||||
return const_cast<View*>(this)->getScene();
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies an offscreen render target to render into.
|
||||
*
|
||||
* By default, the view's associated render target is nullptr, which corresponds to the
|
||||
* SwapChain associated with the engine.
|
||||
*
|
||||
* A view with a custom render target cannot rely on Renderer::ClearOptions, which only apply
|
||||
* to the SwapChain. Such view can use a Skybox instead.
|
||||
*
|
||||
* @param renderTarget Render target associated with view, or nullptr for the swap chain.
|
||||
*/
|
||||
void setRenderTarget(RenderTarget* renderTarget) noexcept;
|
||||
|
||||
/**
|
||||
* Gets the offscreen render target associated with this view.
|
||||
*
|
||||
* Returns nullptr if the render target is the swap chain (which is default).
|
||||
*
|
||||
* @see setRenderTarget
|
||||
*/
|
||||
RenderTarget* getRenderTarget() const noexcept;
|
||||
|
||||
/**
|
||||
* Sets the rectangular region to render to.
|
||||
*
|
||||
* The viewport specifies where the content of the View (i.e. the Scene) is rendered in
|
||||
* the render target. The Render target is automatically clipped to the Viewport.
|
||||
*
|
||||
* @param viewport The Viewport to render the Scene into. The Viewport is a value-type, it is
|
||||
* therefore copied. The parameter can be discarded after this call returns.
|
||||
*/
|
||||
void setViewport(Viewport const& viewport) noexcept;
|
||||
|
||||
/**
|
||||
* Returns the rectangular region that gets rendered to.
|
||||
* @return A constant reference to View's viewport.
|
||||
*/
|
||||
Viewport const& getViewport() const noexcept;
|
||||
|
||||
/**
|
||||
* Sets this View's Camera.
|
||||
*
|
||||
* @param camera Associate the specified Camera to this View. A Camera can be associated to
|
||||
* several View instances.\n
|
||||
* \p camera can be nullptr to dissociate the currently set Camera from this
|
||||
* View.\n
|
||||
* The View doesn't take ownership of the Camera pointer (which
|
||||
* acts as a reference).
|
||||
*
|
||||
* @note
|
||||
* There is no reference-counting.
|
||||
* Make sure to dissociate a Camera from all Views before destroying it.
|
||||
*/
|
||||
void setCamera(Camera* camera) noexcept;
|
||||
|
||||
/**
|
||||
* Returns the Camera currently associated with this View.
|
||||
* @return A reference to the Camera associated to this View.
|
||||
*/
|
||||
Camera& getCamera() noexcept;
|
||||
|
||||
/**
|
||||
* Returns the Camera currently associated with this View.
|
||||
* @return A reference to the Camera associated to this View.
|
||||
*/
|
||||
Camera const& getCamera() const noexcept {
|
||||
return const_cast<View*>(this)->getCamera();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the blending mode used to draw the view into the SwapChain.
|
||||
*
|
||||
* @param blendMode either BlendMode::OPAQUE or BlendMode::TRANSLUCENT
|
||||
* @see getBlendMode
|
||||
*/
|
||||
void setBlendMode(BlendMode blendMode) noexcept;
|
||||
|
||||
/**
|
||||
*
|
||||
* @return blending mode set by setBlendMode
|
||||
* @see setBlendMode
|
||||
*/
|
||||
BlendMode getBlendMode() const noexcept;
|
||||
|
||||
/**
|
||||
* Sets which layers are visible.
|
||||
*
|
||||
* Renderable objects can have one or several layers associated to them. Layers are
|
||||
* represented with an 8-bits bitmask, where each bit corresponds to a layer.
|
||||
* @see RenderableManager::setLayerMask().
|
||||
*
|
||||
* This call sets which of those layers are visible. Renderables in invisible layers won't be
|
||||
* rendered.
|
||||
*
|
||||
* @param select a bitmask specifying which layer to set or clear using \p values.
|
||||
* @param values a bitmask where each bit sets the visibility of the corresponding layer
|
||||
* (1: visible, 0: invisible), only layers in \p select are affected.
|
||||
*
|
||||
* @note By default all layers are visible.
|
||||
* @note This is a convenient way to quickly show or hide sets of Renderable objects.
|
||||
*/
|
||||
void setVisibleLayers(uint8_t select, uint8_t values) noexcept;
|
||||
|
||||
/**
|
||||
* Get the visible layers.
|
||||
*
|
||||
* @see View::setVisibleLayers()
|
||||
*/
|
||||
uint8_t getVisibleLayers() const noexcept;
|
||||
|
||||
/**
|
||||
* Enables or disables shadow mapping. Enabled by default.
|
||||
*
|
||||
* @param enabled true enables shadow mapping, false disables it.
|
||||
*
|
||||
* @see LightManager::Builder::castShadows(),
|
||||
* RenderableManager::Builder::receiveShadows(),
|
||||
* RenderableManager::Builder::castShadows(),
|
||||
*/
|
||||
void setShadowingEnabled(bool enabled) noexcept;
|
||||
|
||||
/**
|
||||
* @return whether shadowing is enabled
|
||||
*/
|
||||
bool isShadowingEnabled() const noexcept;
|
||||
|
||||
/**
|
||||
* Enables or disables screen space refraction. Enabled by default.
|
||||
*
|
||||
* @param enabled true enables screen space refraction, false disables it.
|
||||
*/
|
||||
void setScreenSpaceRefractionEnabled(bool enabled) noexcept;
|
||||
|
||||
/**
|
||||
* @return whether screen space refraction is enabled
|
||||
*/
|
||||
bool isScreenSpaceRefractionEnabled() const noexcept;
|
||||
|
||||
/**
|
||||
* Sets how many samples are to be used for MSAA in the post-process stage.
|
||||
* Default is 1 and disables MSAA.
|
||||
*
|
||||
* @param count 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.
|
||||
*
|
||||
* @note Anti-aliasing can also be performed in the post-processing stage, generally at lower
|
||||
* cost. See setAntialiasing.
|
||||
*
|
||||
* @see setAntialiasing
|
||||
*/
|
||||
void setSampleCount(uint8_t count = 1) noexcept;
|
||||
|
||||
/**
|
||||
* Returns the sample count set by setSampleCount(). Effective sample count could be different.
|
||||
* A value of 0 or 1 means MSAA is disabled.
|
||||
*
|
||||
* @return value set by setSampleCount().
|
||||
*/
|
||||
uint8_t getSampleCount() const noexcept;
|
||||
|
||||
/**
|
||||
* Enables or disables anti-aliasing in the post-processing stage. Enabled by default.
|
||||
* MSAA can be enabled in addition, see setSampleCount().
|
||||
*
|
||||
* @param type FXAA for enabling, NONE for disabling anti-aliasing.
|
||||
*
|
||||
* @note For MSAA anti-aliasing, see setSamplerCount().
|
||||
*
|
||||
* @see setSampleCount
|
||||
*/
|
||||
void setAntiAliasing(AntiAliasing type) noexcept;
|
||||
|
||||
/**
|
||||
* Queries whether anti-aliasing is enabled during the post-processing stage. To query
|
||||
* whether MSAA is enabled, see getSampleCount().
|
||||
*
|
||||
* @return The post-processing anti-aliasing method.
|
||||
*/
|
||||
AntiAliasing getAntiAliasing() const noexcept;
|
||||
|
||||
/**
|
||||
* Enables or disable temporal anti-aliasing (TAA). Disabled by default.
|
||||
*
|
||||
* @param options temporal anti-aliasing options
|
||||
*/
|
||||
void setTemporalAntiAliasingOptions(TemporalAntiAliasingOptions options) noexcept;
|
||||
|
||||
/**
|
||||
* Returns temporal anti-aliasing options.
|
||||
*
|
||||
* @return temporal anti-aliasing options
|
||||
*/
|
||||
TemporalAntiAliasingOptions const& getTemporalAntiAliasingOptions() const noexcept;
|
||||
|
||||
/**
|
||||
* Sets this View's color grading transforms.
|
||||
*
|
||||
* @param colorGrading Associate the specified ColorGrading to this View. A ColorGrading can be
|
||||
* associated to several View instances.\n
|
||||
* \p colorGrading can be nullptr to dissociate the currently set
|
||||
* ColorGrading from this View. Doing so will revert to the use of the
|
||||
* default color grading transforms.\n
|
||||
* The View doesn't take ownership of the ColorGrading pointer (which
|
||||
* acts as a reference).
|
||||
*
|
||||
* @note
|
||||
* There is no reference-counting.
|
||||
* Make sure to dissociate a ColorGrading from all Views before destroying it.
|
||||
*/
|
||||
void setColorGrading(ColorGrading* colorGrading) noexcept;
|
||||
|
||||
/**
|
||||
* Returns the color grading transforms currently associated to this view.
|
||||
* @return A pointer to the ColorGrading associated to this View.
|
||||
*/
|
||||
const ColorGrading* getColorGrading() const noexcept;
|
||||
|
||||
/**
|
||||
* Sets ambient occlusion options.
|
||||
*
|
||||
* @param options Options for ambient occlusion.
|
||||
*/
|
||||
void setAmbientOcclusionOptions(AmbientOcclusionOptions const& options) noexcept;
|
||||
|
||||
/**
|
||||
* Gets the ambient occlusion options.
|
||||
*
|
||||
* @return ambient occlusion options currently set.
|
||||
*/
|
||||
AmbientOcclusionOptions const& getAmbientOcclusionOptions() const noexcept;
|
||||
|
||||
/**
|
||||
* Enables or disables bloom in the post-processing stage. Disabled by default.
|
||||
*
|
||||
* @param options options
|
||||
*/
|
||||
void setBloomOptions(BloomOptions options) noexcept;
|
||||
|
||||
/**
|
||||
* Queries the bloom options.
|
||||
*
|
||||
* @return the current bloom options for this view.
|
||||
*/
|
||||
BloomOptions getBloomOptions() const noexcept;
|
||||
|
||||
/**
|
||||
* Enables or disables fog. Disabled by default.
|
||||
*
|
||||
* @param options options
|
||||
*/
|
||||
void setFogOptions(FogOptions options) noexcept;
|
||||
|
||||
/**
|
||||
* Queries the fog options.
|
||||
*
|
||||
* @return the current fog options for this view.
|
||||
*/
|
||||
FogOptions getFogOptions() const noexcept;
|
||||
|
||||
/**
|
||||
* Enables or disables Depth of Field. Disabled by default.
|
||||
*
|
||||
* @param options options
|
||||
*/
|
||||
void setDepthOfFieldOptions(DepthOfFieldOptions options) noexcept;
|
||||
|
||||
/**
|
||||
* Queries the depth of field options.
|
||||
*
|
||||
* @return the current depth of field options for this view.
|
||||
*/
|
||||
DepthOfFieldOptions getDepthOfFieldOptions() const noexcept;
|
||||
|
||||
/**
|
||||
* Enables or disables the vignetted effect in the post-processing stage. Disabled by default.
|
||||
*
|
||||
* @param options options
|
||||
*/
|
||||
void setVignetteOptions(VignetteOptions options) noexcept;
|
||||
|
||||
/**
|
||||
* Queries the vignette options.
|
||||
*
|
||||
* @return the current vignette options for this view.
|
||||
*/
|
||||
VignetteOptions getVignetteOptions() const noexcept;
|
||||
|
||||
/**
|
||||
* Enables or disables dithering in the post-processing stage. Enabled by default.
|
||||
*
|
||||
* @param dithering dithering type
|
||||
*/
|
||||
void setDithering(Dithering dithering) noexcept;
|
||||
|
||||
/**
|
||||
* Queries whether dithering is enabled during the post-processing stage.
|
||||
*
|
||||
* @return the current dithering type for this view.
|
||||
*/
|
||||
Dithering getDithering() const noexcept;
|
||||
|
||||
/**
|
||||
* Sets the dynamic resolution options for this view. Dynamic resolution options
|
||||
* controls whether dynamic resolution is enabled, and if it is, how it behaves.
|
||||
*
|
||||
* @param options The dynamic resolution options to use on this view
|
||||
*/
|
||||
void setDynamicResolutionOptions(DynamicResolutionOptions const& options) noexcept;
|
||||
|
||||
/**
|
||||
* Returns the dynamic resolution options associated with this view.
|
||||
* @return value set by setDynamicResolutionOptions().
|
||||
*/
|
||||
DynamicResolutionOptions getDynamicResolutionOptions() const noexcept;
|
||||
|
||||
/**
|
||||
* Sets the rendering quality for this view. Refer to RenderQuality for more
|
||||
* information about the different settings available.
|
||||
*
|
||||
* @param renderQuality The render quality to use on this view
|
||||
*/
|
||||
void setRenderQuality(RenderQuality const& renderQuality) noexcept;
|
||||
|
||||
/**
|
||||
* Returns the render quality used by this view.
|
||||
* @return value set by setRenderQuality().
|
||||
*/
|
||||
RenderQuality getRenderQuality() const noexcept;
|
||||
|
||||
/**
|
||||
* Sets options relative to dynamic lighting for this view.
|
||||
*
|
||||
* @param zLightNear Distance from the camera where the lights are expected to shine.
|
||||
* This parameter can affect performance and is useful because depending
|
||||
* on the scene, lights that shine close to the camera may not be
|
||||
* visible -- in this case, using a larger value can improve performance.
|
||||
* e.g. when standing and looking straight, several meters of the ground
|
||||
* isn't visible and if lights are expected to shine there, there is no
|
||||
* point using a short zLightNear. (Default 5m).
|
||||
*
|
||||
* @param zLightFar Distance from the camera after which lights are not expected to be visible.
|
||||
* Similarly to zLightNear, setting this value properly can improve
|
||||
* performance. (Default 100m).
|
||||
*
|
||||
*
|
||||
* Together zLightNear and zLightFar must be chosen so that the visible influence of lights
|
||||
* is spread between these two values.
|
||||
*
|
||||
*/
|
||||
void setDynamicLightingOptions(float zLightNear, float zLightFar) noexcept;
|
||||
|
||||
/*
|
||||
* Set the shadow mapping technique this View uses.
|
||||
*
|
||||
* The ShadowType affects all the shadows seen within the View.
|
||||
*
|
||||
* ShadowType::VSM imposes a restriction on marking renderables as only shadow receivers (but
|
||||
* not casters). To ensure correct shadowing with VSM, all shadow participant renderables should
|
||||
* be marked as both receivers and casters. Objects that are guaranteed to not cast shadows on
|
||||
* themselves or other objects (such as flat ground planes) can be set to not cast shadows,
|
||||
* which might improve shadow quality.
|
||||
*
|
||||
* @warning This API is still experimental and subject to change.
|
||||
*/
|
||||
void setShadowType(ShadowType shadow) noexcept;
|
||||
|
||||
/**
|
||||
* Sets VSM shadowing options that apply across the entire View.
|
||||
*
|
||||
* Additional light-specific VSM options can be set with LightManager::setShadowOptions.
|
||||
*
|
||||
* Only applicable when shadow type is set to ShadowType::VSM.
|
||||
*
|
||||
* @param options Options for shadowing.
|
||||
*
|
||||
* @see setShadowType
|
||||
*
|
||||
* @warning This API is still experimental and subject to change.
|
||||
*/
|
||||
void setVsmShadowOptions(VsmShadowOptions const& options) noexcept;
|
||||
|
||||
/**
|
||||
* Returns the VSM shadowing options associated with this View.
|
||||
*
|
||||
* @return value set by setVsmShadowOptions().
|
||||
*/
|
||||
VsmShadowOptions getVsmShadowOptions() const noexcept;
|
||||
|
||||
/**
|
||||
* Enables or disables post processing. Enabled by default.
|
||||
*
|
||||
* Post-processing includes:
|
||||
* - Bloom
|
||||
* - Tone-mapping & gamma encoding
|
||||
* - Dithering
|
||||
* - MSAA
|
||||
* - FXAA
|
||||
* - Dynamic scaling
|
||||
*
|
||||
* Disabling post-processing forgoes color correctness as well as anti-aliasing and
|
||||
* should only be used experimentally (e.g., for UI overlays).
|
||||
*
|
||||
* @param enabled true enables post processing, false disables it.
|
||||
*
|
||||
* @see setBloomOptions, setColorGrading, setAntiAliasing, setDithering, setSampleCount
|
||||
*/
|
||||
void setPostProcessingEnabled(bool enabled) noexcept;
|
||||
|
||||
//! Returns true if post-processing is enabled. See setPostProcessingEnabled() for more info.
|
||||
bool isPostProcessingEnabled() const noexcept;
|
||||
|
||||
/**
|
||||
* Inverts the winding order of front faces. By default front faces use a counter-clockwise
|
||||
* winding order. When the winding order is inverted, front faces are faces with a clockwise
|
||||
* winding order.
|
||||
*
|
||||
* Changing the winding order will directly affect the culling mode in materials
|
||||
* (see Material::getCullingMode()).
|
||||
*
|
||||
* Inverting the winding order of front faces is useful when rendering mirrored reflections
|
||||
* (water, mirror surfaces, front camera in AR, etc.).
|
||||
*
|
||||
* @param inverted True to invert front faces, false otherwise.
|
||||
*/
|
||||
void setFrontFaceWindingInverted(bool inverted) noexcept;
|
||||
|
||||
/**
|
||||
* Returns true if the winding order of front faces is inverted.
|
||||
* See setFrontFaceWindingInverted() for more information.
|
||||
*/
|
||||
bool isFrontFaceWindingInverted() const noexcept;
|
||||
|
||||
// for debugging...
|
||||
|
||||
//! debugging: allows to entirely disable frustum culling. (culling enabled by default).
|
||||
void setFrustumCullingEnabled(bool culling) noexcept;
|
||||
|
||||
//! debugging: returns whether frustum culling is enabled.
|
||||
bool isFrustumCullingEnabled() const noexcept;
|
||||
|
||||
//! debugging: sets the Camera used for rendering. It may be different from the culling camera.
|
||||
void setDebugCamera(Camera* camera) noexcept;
|
||||
|
||||
//! debugging: returns a Camera from the point of view of *the* dominant directional light used for shadowing.
|
||||
Camera const* getDirectionalLightCamera() const noexcept;
|
||||
|
||||
/**
|
||||
* List of available ambient occlusion techniques
|
||||
* @deprecated use AmbientOcclusionOptions::enabled instead
|
||||
*/
|
||||
enum class UTILS_DEPRECATED AmbientOcclusion : uint8_t {
|
||||
NONE = 0, //!< No Ambient Occlusion
|
||||
SSAO = 1 //!< Basic, sampling SSAO
|
||||
};
|
||||
|
||||
/**
|
||||
* Activates or deactivates ambient occlusion.
|
||||
* @deprecated use setAmbientOcclusionOptions() instead
|
||||
* @see setAmbientOcclusionOptions
|
||||
*
|
||||
* @param ambientOcclusion Type of ambient occlusion to use.
|
||||
*/
|
||||
UTILS_DEPRECATED
|
||||
void setAmbientOcclusion(AmbientOcclusion ambientOcclusion) noexcept;
|
||||
|
||||
/**
|
||||
* Queries the type of ambient occlusion active for this View.
|
||||
* @deprecated use getAmbientOcclusionOptions() instead
|
||||
* @see getAmbientOcclusionOptions
|
||||
*
|
||||
* @return ambient occlusion type.
|
||||
*/
|
||||
UTILS_DEPRECATED
|
||||
AmbientOcclusion getAmbientOcclusion() const noexcept;
|
||||
};
|
||||
|
||||
|
||||
} // namespace filament
|
||||
|
||||
#endif // TNT_FILAMENT_VIEW_H
|
||||
105
ios/include/filament/Viewport.h
Normal file
105
ios/include/filament/Viewport.h
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef TNT_FILAMENT_VIEWPORT_H
|
||||
#define TNT_FILAMENT_VIEWPORT_H
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <math/scalar.h>
|
||||
#include <math/mathfwd.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace filament {
|
||||
|
||||
/**
|
||||
* Viewport describes a view port in pixel coordinates
|
||||
*
|
||||
* A view port is represented by its left-bottom coordinate, width and height in pixels.
|
||||
*/
|
||||
class UTILS_PUBLIC Viewport : public backend::Viewport {
|
||||
public:
|
||||
/**
|
||||
* Creates a Viewport of zero width and height at the origin.
|
||||
*/
|
||||
Viewport() noexcept : backend::Viewport{} {}
|
||||
|
||||
Viewport(const Viewport& viewport) noexcept = default;
|
||||
Viewport(Viewport&& viewport) noexcept = default;
|
||||
Viewport& operator=(const Viewport& viewport) noexcept = default;
|
||||
Viewport& operator=(Viewport&& viewport) noexcept = default;
|
||||
|
||||
/**
|
||||
* Creates a Viewport from its left-bottom coordinates, width and height in pixels
|
||||
*
|
||||
* @param left left coordinate in pixel
|
||||
* @param bottom bottom coordinate in pixel
|
||||
* @param width width in pixel
|
||||
* @param height height in pixel
|
||||
*/
|
||||
Viewport(int32_t left, int32_t bottom, uint32_t width, uint32_t height) noexcept
|
||||
: backend::Viewport{ left, bottom, width, height } {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the area of the view port is null.
|
||||
*
|
||||
* @return true if either width or height is 0 pixel.
|
||||
*/
|
||||
bool empty() const noexcept { return !width || !height; }
|
||||
|
||||
/**
|
||||
* Computes a new scaled Viewport
|
||||
* @param s scaling factor on the x and y axes.
|
||||
* @return A new scaled Viewport. The coordinates and dimensions of the new Viewport are
|
||||
* rounded to the nearest integer value.
|
||||
*/
|
||||
Viewport scale(math::float2 s) const noexcept;
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Compares two Viewports for equality
|
||||
* @param lhs reference to the left hand side Viewport
|
||||
* @param rhs reference to the right hand side Viewport
|
||||
* @return true if \p rhs and \p lhs are identical.
|
||||
*/
|
||||
friend bool operator==(Viewport const& lhs, Viewport const& rhs) noexcept {
|
||||
return (&rhs == &lhs) ||
|
||||
(rhs.left == lhs.left && rhs.bottom == lhs.bottom &&
|
||||
rhs.width == lhs.width && rhs.height == lhs.height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two Viewports for inequality
|
||||
* @param lhs reference to the left hand side Viewport
|
||||
* @param rhs reference to the right hand side Viewport
|
||||
* @return true if \p rhs and \p lhs are different.
|
||||
*/
|
||||
friend bool operator!=(Viewport const& lhs, Viewport const& rhs) noexcept {
|
||||
return !(rhs == lhs);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace filament
|
||||
|
||||
#endif // TNT_FILAMENT_VIEWPORT_H
|
||||
120
ios/include/filameshio/MeshReader.h
Normal file
120
ios/include/filameshio/MeshReader.h
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* 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
|
||||
131
ios/include/geometry/SurfaceOrientation.h
Normal file
131
ios/include/geometry/SurfaceOrientation.h
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* 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
|
||||
104
ios/include/geometry/Transcoder.h
Normal file
104
ios/include/geometry/Transcoder.h
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* 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
|
||||
88
ios/include/gltfio/Animator.h
Normal file
88
ios/include/gltfio/Animator.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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 GLTFIO_ANIMATOR_H
|
||||
#define GLTFIO_ANIMATOR_H
|
||||
|
||||
#include <gltfio/FilamentAsset.h>
|
||||
#include <gltfio/FilamentInstance.h>
|
||||
|
||||
namespace gltfio {
|
||||
|
||||
struct FFilamentAsset;
|
||||
struct FFilamentInstance;
|
||||
struct AnimatorImpl;
|
||||
|
||||
/**
|
||||
* \class Animator Animator.h gltfio/Animator.h
|
||||
* \brief Updates matrices according to glTF \c animation and \c skin definitions.
|
||||
*
|
||||
* Animator can be used for two things:
|
||||
* - Updating matrices in filament::TransformManager components according to glTF \c animation definitions.
|
||||
* - Updating bone matrices in filament::RenderableManager components according to glTF \c skin definitions.
|
||||
*
|
||||
* For a usage example, see the documentation for AssetLoader.
|
||||
*/
|
||||
class UTILS_PUBLIC Animator {
|
||||
public:
|
||||
/**
|
||||
* Applies rotation, translation, and scale to entities that have been targeted by the given
|
||||
* animation definition. Uses filament::TransformManager.
|
||||
*
|
||||
* @param animationIndex Zero-based index for the \c animation of interest.
|
||||
* @param time Elapsed time of interest in seconds.
|
||||
*/
|
||||
void applyAnimation(size_t animationIndex, float time) const;
|
||||
|
||||
/**
|
||||
* Computes root-to-node transforms for all bone nodes, then passes
|
||||
* the results into filament::RenderableManager::setBones.
|
||||
* Uses filament::TransformManager and filament::RenderableManager.
|
||||
*
|
||||
* NOTE: this operation is independent of \c animation.
|
||||
*/
|
||||
void updateBoneMatrices();
|
||||
|
||||
/** Returns the number of \c animation definitions in the glTF asset. */
|
||||
size_t getAnimationCount() const;
|
||||
|
||||
/** Returns the duration of the specified glTF \c animation in seconds. */
|
||||
float getAnimationDuration(size_t animationIndex) const;
|
||||
|
||||
/**
|
||||
* Returns a weak reference to the string name of the specified \c animation, or an
|
||||
* empty string if none was specified.
|
||||
*/
|
||||
const char* getAnimationName(size_t animationIndex) const;
|
||||
|
||||
// For internal use only.
|
||||
void addInstance(FFilamentInstance* instance);
|
||||
|
||||
private:
|
||||
|
||||
/*! \cond PRIVATE */
|
||||
friend struct FFilamentAsset;
|
||||
friend struct FFilamentInstance;
|
||||
/*! \endcond */
|
||||
|
||||
Animator(FFilamentAsset* asset, FFilamentInstance* instance);
|
||||
~Animator();
|
||||
AnimatorImpl* mImpl;
|
||||
};
|
||||
|
||||
} // namespace gltfio
|
||||
|
||||
#endif // GLTFIO_ANIMATOR_H
|
||||
244
ios/include/gltfio/AssetLoader.h
Normal file
244
ios/include/gltfio/AssetLoader.h
Normal file
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
* 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 GLTFIO_ASSETLOADER_H
|
||||
#define GLTFIO_ASSETLOADER_H
|
||||
|
||||
#include <filament/Engine.h>
|
||||
#include <filament/Material.h>
|
||||
|
||||
#include <gltfio/FilamentAsset.h>
|
||||
#include <gltfio/FilamentInstance.h>
|
||||
#include <gltfio/MaterialProvider.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
namespace utils {
|
||||
class EntityManager;
|
||||
class NameComponentManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loader and pipeline for glTF 2.0 assets.
|
||||
*/
|
||||
namespace gltfio {
|
||||
|
||||
/**
|
||||
* \struct AssetConfiguration AssetLoader.h gltfio/AssetLoader.h
|
||||
* \brief Construction parameters for AssetLoader.
|
||||
*/
|
||||
struct AssetConfiguration {
|
||||
//! The engine that the loader should pass to builder objects (e.g.
|
||||
//! filament::VertexBuffer::Builder).
|
||||
class filament::Engine* engine;
|
||||
|
||||
//! Controls whether the loader uses filamat to generate materials on the fly, or loads a small
|
||||
//! set of precompiled ubershader materials. Deleting the MaterialProvider is the client's
|
||||
//! responsibility. See createMaterialGenerator() and createUbershaderLoader().
|
||||
MaterialProvider* materials;
|
||||
|
||||
//! Optional manager for associating string names with entities in the transform hierarchy.
|
||||
utils::NameComponentManager* names = nullptr;
|
||||
|
||||
//! Overrides the factory used for creating entities in the transform hierarchy. If this is not
|
||||
//! specified, AssetLoader will use the singleton EntityManager associated with the current
|
||||
//! process.
|
||||
utils::EntityManager* entities = nullptr;
|
||||
|
||||
//! Optional default node name for anonymous nodes
|
||||
char* defaultNodeName = nullptr;
|
||||
};
|
||||
|
||||
/**
|
||||
* \class AssetLoader AssetLoader.h gltfio/AssetLoader.h
|
||||
* \brief Consumes glTF content and produces FilamentAsset objects.
|
||||
*
|
||||
* AssetLoader consumes a blob of glTF 2.0 content (either JSON or GLB) and produces a FilamentAsset
|
||||
* object, which is a bundle of Filament entities, material instances, textures, vertex buffers,
|
||||
* and index buffers.
|
||||
*
|
||||
* Clients must use AssetLoader to create and destroy FilamentAsset objects.
|
||||
*
|
||||
* AssetLoader does not fetch external buffer data or create textures on its own. Clients can use
|
||||
* ResourceLoader for this, which obtains the URI list from the asset. This is demonstrated in the
|
||||
* code snippet below.
|
||||
*
|
||||
* AssetLoader also owns a cache of filament::Material objects that may be re-used across multiple
|
||||
* loads.
|
||||
*
|
||||
* Example usage:
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* auto engine = Engine::create();
|
||||
* auto materials = createMaterialGenerator(engine);
|
||||
* auto loader = AssetLoader::create({engine, materials});
|
||||
*
|
||||
* // Parse the glTF content and create Filament entities.
|
||||
* std::vector<uint8_t> content(...);
|
||||
* FilamentAsset* asset = loader->createAssetFromJson(content.data(), content.size());
|
||||
* content.clear();
|
||||
*
|
||||
* // Load buffers and textures from disk.
|
||||
* ResourceLoader({engine, ".", true}).loadResources(asset);
|
||||
*
|
||||
* // Obtain the simple animation interface.
|
||||
* Animator* animator = asset->getAnimator();
|
||||
*
|
||||
* // Free the glTF hierarchy as it is no longer needed.
|
||||
* asset->releaseSourceData();
|
||||
*
|
||||
* // Add renderables to the scene.
|
||||
* scene->addEntities(asset->getEntities(), asset->getEntityCount());
|
||||
*
|
||||
* // Execute the render loop and play the first animation.
|
||||
* do {
|
||||
* animator->applyAnimation(0, time);
|
||||
* animator->updateBoneMatrices();
|
||||
* if (renderer->beginFrame(swapChain)) {
|
||||
* renderer->render(view);
|
||||
* renderer->endFrame();
|
||||
* }
|
||||
* } while (!quit);
|
||||
*
|
||||
* scene->removeEntities(asset->getEntities(), asset->getEntityCount());
|
||||
* loader->destroyAsset(asset);
|
||||
* materials->destroyMaterials();
|
||||
* delete materials;
|
||||
* AssetLoader::destroy(&loader);
|
||||
* Engine::destroy(&engine);
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*/
|
||||
class UTILS_PUBLIC AssetLoader {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Creates an asset loader for the given configuration, which specifies the Filament engine.
|
||||
*
|
||||
* The engine is held weakly, used only for the creation and destruction of Filament objects.
|
||||
* The optional name component manager can be used to assign names to renderables.
|
||||
* The material source specifies whether to use filamat to generate materials on the fly, or to
|
||||
* load a small set of precompiled ubershader materials.
|
||||
*/
|
||||
static AssetLoader* create(const AssetConfiguration& config);
|
||||
|
||||
/**
|
||||
* Frees the loader.
|
||||
*
|
||||
* This does not not automatically free the cache of materials, nor
|
||||
* does it free the entities for created assets (see destroyAsset).
|
||||
*/
|
||||
static void destroy(AssetLoader** loader);
|
||||
|
||||
/**
|
||||
* Takes a pointer to the contents of a JSON-based glTF 2.0 file and returns a bundle
|
||||
* of Filament objects. Returns null on failure.
|
||||
*/
|
||||
FilamentAsset* createAssetFromJson(const uint8_t* bytes, uint32_t nbytes);
|
||||
|
||||
/**
|
||||
* Takes a pointer to the contents of a GLB glTF 2.0 file and returns a bundle
|
||||
* of Filament objects. Returns null on failure.
|
||||
*/
|
||||
FilamentAsset* createAssetFromBinary(const uint8_t* bytes, uint32_t nbytes);
|
||||
|
||||
/**
|
||||
* Consumes the contents of a glTF 2.0 file and produces a primary asset with one or more
|
||||
* instances. The primary asset has ownership over the instances.
|
||||
*
|
||||
* The returned instances share their textures, material instances, and vertex buffers with the
|
||||
* primary asset. However each instance has its own unique set of entities, transform
|
||||
* components, and renderable components. Instances are freed when the primary asset is freed.
|
||||
*
|
||||
* Light components are not instanced, they belong only to the primary asset.
|
||||
*
|
||||
* Clients must use ResourceLoader to load resources on the primary asset.
|
||||
*
|
||||
* The entity accessor and renderable stack API in the primary asset can be used to control the
|
||||
* union of all instances. The individual FilamentInstance objects can be used to access each
|
||||
* instance's partition of entities. Similarly, the Animator in the primary asset controls all
|
||||
* instances. To animate instances individually, use FilamentInstance::getAnimator().
|
||||
*
|
||||
* @param bytes the contents of a glTF 2.0 file (JSON or GLB)
|
||||
* @param numBytes the number of bytes in "bytes"
|
||||
* @param instances destination pointer, to be populated by the requested number of instances
|
||||
* @param numInstances requested number of instances
|
||||
* @return the primary asset that has ownership over all instances
|
||||
*/
|
||||
FilamentAsset* createInstancedAsset(const uint8_t* bytes, uint32_t numBytes,
|
||||
FilamentInstance** instances, size_t numInstances);
|
||||
|
||||
/**
|
||||
* Adds a new instance to an instanced asset.
|
||||
*
|
||||
* Use this with caution. It is more efficient to pre-allocate a max number of instances, and
|
||||
* gradually add them to the scene as needed. Instances can also be "recycled" by removing and
|
||||
* re-adding them to the scene.
|
||||
*
|
||||
* NOTE: destroyInstance() does not exist because gltfio favors flat arrays for storage of
|
||||
* entity lists and instance lists, which would be slow to shift. We also wish to discourage
|
||||
* create/destroy churn, as noted above.
|
||||
*
|
||||
* This cannot be called after FilamentAsset::releaseSourceData().
|
||||
* This cannot be called on a non-instanced asset.
|
||||
* See also AssetLoader::createInstancedAsset().
|
||||
*/
|
||||
FilamentInstance* createInstance(FilamentAsset* primary);
|
||||
|
||||
/**
|
||||
* Allows clients to enable diagnostic shading on newly-loaded assets.
|
||||
*/
|
||||
void enableDiagnostics(bool enable = true);
|
||||
|
||||
/**
|
||||
* Destroys the given asset and all of its associated Filament objects.
|
||||
*
|
||||
* This destroys entities, components, material instances, vertex buffers, index buffers,
|
||||
* and textures. This does not necessarily immediately free all source data, since
|
||||
* texture decoding or GPU uploading might be underway.
|
||||
*/
|
||||
void destroyAsset(const FilamentAsset* asset);
|
||||
|
||||
/**
|
||||
* Gets a weak reference to an array of cached materials, used internally to create material
|
||||
* instances for assets.
|
||||
*/
|
||||
const filament::Material* const* getMaterials() const noexcept;
|
||||
|
||||
/**
|
||||
* Gets the number of cached materials.
|
||||
*/
|
||||
size_t getMaterialsCount() const noexcept;
|
||||
|
||||
utils::NameComponentManager* getNames() const noexcept;
|
||||
|
||||
MaterialProvider* getMaterialProvider() const noexcept;
|
||||
|
||||
/*! \cond PRIVATE */
|
||||
protected:
|
||||
AssetLoader() noexcept = default;
|
||||
~AssetLoader() = default;
|
||||
|
||||
public:
|
||||
AssetLoader(AssetLoader const&) = delete;
|
||||
AssetLoader(AssetLoader&&) = delete;
|
||||
AssetLoader& operator=(AssetLoader const&) = delete;
|
||||
AssetLoader& operator=(AssetLoader&&) = delete;
|
||||
/*! \endcond */
|
||||
};
|
||||
|
||||
} // namespace gltfio
|
||||
|
||||
#endif // GLTFIO_ASSETLOADER_H
|
||||
251
ios/include/gltfio/FilamentAsset.h
Normal file
251
ios/include/gltfio/FilamentAsset.h
Normal file
@@ -0,0 +1,251 @@
|
||||
/*
|
||||
* 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 GLTFIO_FILAMENTASSET_H
|
||||
#define GLTFIO_FILAMENTASSET_H
|
||||
|
||||
#include <filament/Box.h>
|
||||
#include <filament/TextureSampler.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/Entity.h>
|
||||
|
||||
namespace filament {
|
||||
class Camera;
|
||||
class Engine;
|
||||
class MaterialInstance;
|
||||
}
|
||||
|
||||
namespace gltfio {
|
||||
|
||||
class Animator;
|
||||
class FilamentInstance;
|
||||
|
||||
/**
|
||||
* \class FilamentAsset FilamentAsset.h gltfio/FilamentAsset.h
|
||||
* \brief Owns a bundle of Filament objects that have been created by AssetLoader.
|
||||
*
|
||||
* For usage instructions, see the documentation for AssetLoader.
|
||||
*
|
||||
* This class owns a hierarchy of entities that have been loaded from a glTF asset. Every entity has
|
||||
* a filament::TransformManager component, and some entities also have \c Name, \c Renderable,
|
||||
* \c Light, or \c Camera components.
|
||||
*
|
||||
* In addition to the aforementioned entities, an asset has strong ownership over a list of
|
||||
* filament::VertexBuffer, filament::IndexBuffer, filament::MaterialInstance, filament::Texture,
|
||||
* and, optionally, a simple animation engine (gltfio::Animator).
|
||||
*
|
||||
* Clients must use ResourceLoader to create filament::Texture objects, compute tangent quaternions,
|
||||
* and upload data into vertex buffers and index buffers.
|
||||
*
|
||||
* \todo Only the default glTF scene is loaded, other glTF scenes are ignored.
|
||||
*/
|
||||
class UTILS_PUBLIC FilamentAsset {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Gets the list of entities, one for each glTF node. All of these have a Transform component.
|
||||
* Some of the returned entities may also have a Renderable component and/or a Light component.
|
||||
*/
|
||||
const utils::Entity* getEntities() const noexcept;
|
||||
|
||||
/**
|
||||
* Gets the number of entities returned by getEntities().
|
||||
*/
|
||||
size_t getEntityCount() const noexcept;
|
||||
|
||||
/**
|
||||
* Gets the list of entities in the scene representing lights. All of these have a Light component.
|
||||
*/
|
||||
const utils::Entity* getLightEntities() const noexcept;
|
||||
|
||||
/**
|
||||
* Gets the number of entities returned by getLightEntities().
|
||||
*/
|
||||
size_t getLightEntityCount() const noexcept;
|
||||
|
||||
/**
|
||||
* Gets the list of entities in the scene representing cameras. All of these have a \c Camera
|
||||
* component.
|
||||
*
|
||||
* Note about aspect ratios:
|
||||
* gltfio always uses an aspect ratio of 1.0 when setting the projection matrix for perspective
|
||||
* cameras. gltfio then sets the camera's scaling matrix with the aspect ratio specified in the
|
||||
* glTF file (if present).
|
||||
*
|
||||
* The camera's scaling matrix allows clients to adjust the aspect ratio independently from the
|
||||
* camera's projection.
|
||||
*
|
||||
* To change the aspect ratio of the glTF camera:
|
||||
*
|
||||
* camera->setScaling(double4 {1.0 / newAspectRatio, 1.0, 1.0, 1.0});
|
||||
*
|
||||
* @see filament::Camera::setScaling
|
||||
*/
|
||||
const utils::Entity* getCameraEntities() const noexcept;
|
||||
|
||||
/**
|
||||
* Gets the number of entities returned by getCameraEntities().
|
||||
*/
|
||||
size_t getCameraEntityCount() const noexcept;
|
||||
|
||||
/**
|
||||
* Gets the transform root for the asset, which has no matching glTF node.
|
||||
*
|
||||
* This node exists for convenience, allowing users to transform the entire asset. For instanced
|
||||
* assets, this is a "super root" where each of its children is a root in a particular instance.
|
||||
* This allows users to transform all instances en masse if they wish to do so.
|
||||
*/
|
||||
utils::Entity getRoot() const noexcept;
|
||||
|
||||
/**
|
||||
* Pops a ready renderable off the queue, or returns 0 if no renderables have become ready.
|
||||
*
|
||||
* NOTE: To determine the progress percentage or completion status, please use
|
||||
* ResourceLoader#asyncGetLoadProgress. To get the number of ready renderables,
|
||||
* please use popRenderables().
|
||||
*
|
||||
* This method allows clients to progressively add the asset's renderables to the scene as
|
||||
* textures gradually become ready through asynchronous loading. For example, on every frame
|
||||
* progressive applications can do something like this:
|
||||
*
|
||||
* while (utils::Entity e = popRenderable()) { scene.addEntity(e); }
|
||||
*
|
||||
* \see ResourceLoader#asyncBeginLoad
|
||||
* \see popRenderables()
|
||||
*/
|
||||
utils::Entity popRenderable() noexcept;
|
||||
|
||||
/**
|
||||
* Pops up to "count" ready renderables off the queue, or returns the available number.
|
||||
*
|
||||
* The given pointer should either be null or point to memory that can hold up to count
|
||||
* entities. If the pointer is null, returns the number of available renderables. Otherwise
|
||||
* returns the number of entities that have been written.
|
||||
*
|
||||
* \see ResourceLoader#asyncBeginLoad
|
||||
*/
|
||||
size_t popRenderables(utils::Entity* entities, size_t count) noexcept;
|
||||
|
||||
/** Gets all material instances. These are already bound to renderables. */
|
||||
const filament::MaterialInstance* const* getMaterialInstances() const noexcept;
|
||||
|
||||
/** Gets all material instances (non-const). These are already bound to renderables. */
|
||||
filament::MaterialInstance* const* getMaterialInstances() noexcept;
|
||||
|
||||
/** Gets the number of materials returned by getMaterialInstances(). */
|
||||
size_t getMaterialInstanceCount() const noexcept;
|
||||
|
||||
/** Gets resource URIs for all externally-referenced buffers. */
|
||||
const char* const* getResourceUris() const noexcept;
|
||||
|
||||
/** Gets the number of resource URIs returned by getResourceUris(). */
|
||||
size_t getResourceUriCount() const noexcept;
|
||||
|
||||
/** Gets the bounding box computed from the supplied min / max values in glTF accessors. */
|
||||
filament::Aabb getBoundingBox() const noexcept;
|
||||
|
||||
/** Gets the NameComponentManager label for the given entity, if it exists. */
|
||||
const char* getName(utils::Entity) const noexcept;
|
||||
|
||||
/** Returns the first entity with the given name, or 0 if none exist. */
|
||||
utils::Entity getFirstEntityByName(const char* name) noexcept;
|
||||
|
||||
/**
|
||||
* Gets a list of entities with the given name.
|
||||
*
|
||||
* @param name Null-terminated string to match.
|
||||
* @param entities Pointer to an array to populate.
|
||||
* @param maxCount Maximum number of entities to retrieve.
|
||||
*
|
||||
* @return If entities is non-null, the number of entities written to the entity pointer.
|
||||
* Otherwise this returns the number of entities with the given name.
|
||||
*/
|
||||
size_t getEntitiesByName(const char* name, utils::Entity* entities,
|
||||
size_t maxCount) const noexcept;
|
||||
|
||||
/**
|
||||
* Gets a list of entities whose names start with the given prefix.
|
||||
*
|
||||
* @param prefix Null-terminated prefix string to match.
|
||||
* @param entities Pointer to an array to populate.
|
||||
* @param maxCount Maximum number of entities to retrieve.
|
||||
*
|
||||
* @return If entities is non-null, the number of entities written to the entity pointer.
|
||||
* Otherwise this returns the number of entities with the given prefix.
|
||||
*/
|
||||
size_t getEntitiesByPrefix(const char* prefix, utils::Entity* entities,
|
||||
size_t maxCount) const noexcept;
|
||||
|
||||
/** Gets the glTF extras string for a specific node, or for the asset, if it exists. */
|
||||
const char* getExtras(utils::Entity entity = {}) const noexcept;
|
||||
|
||||
/**
|
||||
* Lazily creates the animation engine or returns it from the cache.
|
||||
*
|
||||
* The animator is owned by the asset and should not be manually deleted.
|
||||
* The first time this is called, it must be called before FilamentAsset::releaseSourceData().
|
||||
* If the asset is instanced, this returns a "primary" animator that controls all instances.
|
||||
* To animate each instance individually, use \see FilamentInstance.
|
||||
*/
|
||||
Animator* getAnimator() noexcept;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
utils::Entity getWireframe() noexcept;
|
||||
|
||||
/**
|
||||
* Returns the Filament engine associated with the AssetLoader that created this asset.
|
||||
*/
|
||||
filament::Engine* getEngine() const noexcept;
|
||||
|
||||
/**
|
||||
* Reclaims CPU-side memory for URI strings, binding lists, and raw animation data.
|
||||
*
|
||||
* This should only be called after ResourceLoader::loadResources().
|
||||
* If using Animator, this should be called after getAnimator().
|
||||
* If this is an instanced asset, this prevents creation of new instances.
|
||||
*/
|
||||
void releaseSourceData() noexcept;
|
||||
|
||||
/**
|
||||
* Returns a weak reference to the underlying cgltf hierarchy. This becomes invalid after
|
||||
* calling releaseSourceData().
|
||||
*/
|
||||
const void* getSourceAsset() noexcept;
|
||||
|
||||
/*! \cond PRIVATE */
|
||||
|
||||
FilamentInstance** getAssetInstances() noexcept;
|
||||
size_t getAssetInstanceCount() const noexcept;
|
||||
|
||||
protected:
|
||||
FilamentAsset() noexcept = default;
|
||||
~FilamentAsset() = default;
|
||||
|
||||
public:
|
||||
FilamentAsset(FilamentAsset const&) = delete;
|
||||
FilamentAsset(FilamentAsset&&) = delete;
|
||||
FilamentAsset& operator=(FilamentAsset const&) = delete;
|
||||
FilamentAsset& operator=(FilamentAsset&&) = delete;
|
||||
/*! \endcond */
|
||||
};
|
||||
|
||||
} // namespace gltfio
|
||||
|
||||
#endif // GLTFIO_FILAMENTASSET_H
|
||||
75
ios/include/gltfio/FilamentInstance.h
Normal file
75
ios/include/gltfio/FilamentInstance.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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 GLTFIO_FILAMENTINSTANCE_H
|
||||
#define GLTFIO_FILAMENTINSTANCE_H
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/Entity.h>
|
||||
|
||||
namespace gltfio {
|
||||
|
||||
class Animator;
|
||||
class FilamentAsset;
|
||||
|
||||
/**
|
||||
* \class FilamentInstance FilamentInstance.h gltfio/FilamentInstance.h
|
||||
* \brief Provides access to a hierarchy of entities that have been instanced from a glTF asset.
|
||||
*
|
||||
* Every entity has a filament::TransformManager component, and some entities also have \c Name or
|
||||
* \c Renderable components.
|
||||
*
|
||||
* \see AssetLoader::createInstancedAsset()
|
||||
*/
|
||||
class UTILS_PUBLIC FilamentInstance {
|
||||
public:
|
||||
/**
|
||||
* Gets the owner of this instance.
|
||||
*/
|
||||
FilamentAsset* getAsset() const noexcept;
|
||||
|
||||
/**
|
||||
* Gets the list of entities in this instance, one for each glTF node. All of these have a
|
||||
* Transform component. Some of the returned entities may also have a Renderable component or
|
||||
* Name component.
|
||||
*/
|
||||
const utils::Entity* getEntities() const noexcept;
|
||||
|
||||
/**
|
||||
* Gets the number of entities returned by getEntities().
|
||||
*/
|
||||
size_t getEntityCount() const noexcept;
|
||||
|
||||
/** Gets the transform root for the instance, which has no matching glTF node. */
|
||||
utils::Entity getRoot() const noexcept;
|
||||
|
||||
/**
|
||||
* Lazily creates the animation engine for the instance, or returns it from the cache.
|
||||
*
|
||||
* Note that an animator can be obtained either from an individual instance, or from the
|
||||
* originating FilamentAsset. In the latter case, the animation frame is shared amongst all
|
||||
* instances. If individual control is desired, users must obtain the animator from the
|
||||
* individual instances.
|
||||
*
|
||||
* The animator is owned by the asset and should not be manually deleted.
|
||||
* The first time this is called, it must be called before FilamentAsset::releaseSourceData().
|
||||
*/
|
||||
Animator* getAnimator() noexcept;
|
||||
};
|
||||
|
||||
} // namespace gltfio
|
||||
|
||||
#endif // GLTFIO_FILAMENTINSTANCE_H
|
||||
32
ios/include/gltfio/Image.h
Normal file
32
ios/include/gltfio/Image.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// gltfio supports PNG and JPEG, disable all other formats.
|
||||
#define STBI_NO_BMP
|
||||
#define STBI_NO_PSD
|
||||
#define STBI_NO_TGA
|
||||
#define STBI_NO_GIF
|
||||
#define STBI_NO_HDR
|
||||
#define STBI_NO_PIC
|
||||
#define STBI_NO_PNM
|
||||
|
||||
// For emscripten and Android builds, we never load from the file
|
||||
// system, so we-opt out of the stdio functionality in stb.
|
||||
#if defined(__EMSCRIPTEN__) || defined(ANDROID)
|
||||
#define STBI_NO_STDIO
|
||||
#endif
|
||||
|
||||
#include <stb_image.h>
|
||||
199
ios/include/gltfio/MaterialProvider.h
Normal file
199
ios/include/gltfio/MaterialProvider.h
Normal file
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
* 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 GLTFIO_MATERIALPROVIDER_H
|
||||
#define GLTFIO_MATERIALPROVIDER_H
|
||||
|
||||
#include <filament/Engine.h>
|
||||
#include <filament/Material.h>
|
||||
#include <filament/MaterialInstance.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <array>
|
||||
#include <string>
|
||||
|
||||
namespace gltfio {
|
||||
|
||||
enum class AlphaMode : uint8_t {
|
||||
OPAQUE,
|
||||
MASK,
|
||||
BLEND
|
||||
};
|
||||
|
||||
/**
|
||||
* \struct MaterialKey MaterialProvider.h gltfio/MaterialProvider.h
|
||||
* \brief Small POD structure that specifies the requirements for a glTF material.
|
||||
* \note This key is processed by MurmurHashFn so please make padding explicit.
|
||||
*/
|
||||
struct alignas(4) MaterialKey {
|
||||
// -- 32 bit boundary --
|
||||
bool doubleSided : 1;
|
||||
bool unlit : 1;
|
||||
bool hasVertexColors : 1;
|
||||
bool hasBaseColorTexture : 1;
|
||||
bool hasNormalTexture : 1;
|
||||
bool hasOcclusionTexture : 1;
|
||||
bool hasEmissiveTexture : 1;
|
||||
bool useSpecularGlossiness : 1;
|
||||
AlphaMode alphaMode : 4;
|
||||
bool enableDiagnostics : 4;
|
||||
union {
|
||||
struct {
|
||||
bool hasMetallicRoughnessTexture : 1;
|
||||
uint8_t metallicRoughnessUV : 7;
|
||||
};
|
||||
struct {
|
||||
bool hasSpecularGlossinessTexture : 1;
|
||||
uint8_t specularGlossinessUV : 7;
|
||||
};
|
||||
};
|
||||
uint8_t baseColorUV;
|
||||
// -- 32 bit boundary --
|
||||
bool hasClearCoatTexture : 1;
|
||||
uint8_t clearCoatUV : 7;
|
||||
bool hasClearCoatRoughnessTexture : 1;
|
||||
uint8_t clearCoatRoughnessUV : 7;
|
||||
bool hasClearCoatNormalTexture : 1;
|
||||
uint8_t clearCoatNormalUV : 7;
|
||||
bool hasClearCoat : 1;
|
||||
bool hasTransmission : 1;
|
||||
bool hasTextureTransforms : 6;
|
||||
// -- 32 bit boundary --
|
||||
uint8_t emissiveUV;
|
||||
uint8_t aoUV;
|
||||
uint8_t normalUV;
|
||||
bool hasTransmissionTexture : 1;
|
||||
uint8_t transmissionUV : 7;
|
||||
// -- 32 bit boundary --
|
||||
bool hasSheenColorTexture : 1;
|
||||
uint8_t sheenColorUV : 7;
|
||||
bool hasSheenRoughnessTexture : 1;
|
||||
uint8_t sheenRoughnessUV : 7;
|
||||
bool hasVolumeThicknessTexture : 1;
|
||||
uint8_t volumeThicknessUV : 7;
|
||||
bool hasSheen : 1;
|
||||
bool hasIOR : 1;
|
||||
bool hasVolume : 1;
|
||||
};
|
||||
|
||||
static_assert(sizeof(MaterialKey) == 16, "MaterialKey has unexpected padding.");
|
||||
|
||||
bool operator==(const MaterialKey& k1, const MaterialKey& k2);
|
||||
|
||||
// Define a mapping from a uv set index in the source asset to one of Filament's uv sets.
|
||||
enum UvSet : uint8_t { UNUSED, UV0, UV1 };
|
||||
constexpr int UvMapSize = 8;
|
||||
using UvMap = std::array<UvSet, UvMapSize>;
|
||||
|
||||
inline uint8_t getNumUvSets(const UvMap& uvmap) {
|
||||
return std::max({
|
||||
uvmap[0], uvmap[1], uvmap[2], uvmap[3],
|
||||
uvmap[4], uvmap[5], uvmap[6], uvmap[7],
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* \class MaterialProvider MaterialProvider.h gltfio/MaterialProvider.h
|
||||
* \brief Interface to a provider of glTF materials (has two implementations).
|
||||
*
|
||||
* - The \c MaterialGenerator implementation generates materials at run time (which can be slow) and
|
||||
* requires the filamat library, but produces streamlined shaders. See createMaterialGenerator().
|
||||
*
|
||||
* - The \c UbershaderLoader implementation uses a small number of pre-built materials with complex
|
||||
* fragment shaders, but does not require any run time work or usage of filamat. See
|
||||
* createUbershaderLoader().
|
||||
*
|
||||
* Both implementations of MaterialProvider maintain a small cache of materials which must be
|
||||
* explicitly freed using destroyMaterials(). These materials are not freed automatically when the
|
||||
* MaterialProvider is destroyed, which allows clients to take ownership if desired.
|
||||
*
|
||||
*/
|
||||
class UTILS_PUBLIC MaterialProvider {
|
||||
public:
|
||||
virtual ~MaterialProvider() {}
|
||||
|
||||
/**
|
||||
* Creates or fetches a compiled Filament material, then creates an instance from it.
|
||||
*
|
||||
* @param config Specifies requirements; might be mutated due to resource constraints.
|
||||
* @param uvmap Output argument that gets populated with a small table that maps from a glTF uv
|
||||
* index to a Filament uv index.
|
||||
* @param label Optional tag that is not a part of the cache key.
|
||||
*/
|
||||
virtual filament::MaterialInstance* createMaterialInstance(MaterialKey* config, UvMap* uvmap,
|
||||
const char* label = "material") = 0;
|
||||
|
||||
/**
|
||||
* Gets a weak reference to the array of cached materials.
|
||||
*/
|
||||
virtual const filament::Material* const* getMaterials() const noexcept = 0;
|
||||
|
||||
/**
|
||||
* Gets the number of cached materials.
|
||||
*/
|
||||
virtual size_t getMaterialsCount() const noexcept = 0;
|
||||
|
||||
/**
|
||||
* Destroys all cached materials.
|
||||
*
|
||||
* This is not called automatically when MaterialProvider is destroyed, which allows
|
||||
* clients to take ownership of the cache if desired.
|
||||
*/
|
||||
virtual void destroyMaterials() = 0;
|
||||
|
||||
/**
|
||||
* Returns true if the presence of the given vertex attribute is required.
|
||||
*
|
||||
* Some types of providers (e.g. ubershader) require dummy attribute values
|
||||
* if the glTF model does not provide them.
|
||||
*/
|
||||
virtual bool needsDummyData(filament::VertexAttribute attrib) const noexcept = 0;
|
||||
};
|
||||
|
||||
void constrainMaterial(MaterialKey* key, UvMap* uvmap);
|
||||
|
||||
void processShaderString(std::string* shader, const UvMap& uvmap,
|
||||
const MaterialKey& config);
|
||||
|
||||
/**
|
||||
* Creates a material provider that builds materials on the fly, composing GLSL at run time.
|
||||
*
|
||||
* @param optimizeShaders Optimizes shaders, but at significant cost to construction time.
|
||||
* @return New material provider that can build materials at run time.
|
||||
*
|
||||
* Requires \c libfilamat to be linked in. Not available in \c libgltfio_core.
|
||||
*
|
||||
* @see createUbershaderLoader
|
||||
*/
|
||||
UTILS_PUBLIC
|
||||
MaterialProvider* createMaterialGenerator(filament::Engine* engine, bool optimizeShaders = false);
|
||||
|
||||
/**
|
||||
* Creates a material provider that loads a small set of pre-built materials.
|
||||
*
|
||||
* @return New material provider that can quickly load a material from a cache.
|
||||
*
|
||||
* Requires \c libgltfio_resources to be linked in.
|
||||
*
|
||||
* @see createMaterialGenerator
|
||||
*/
|
||||
UTILS_PUBLIC
|
||||
MaterialProvider* createUbershaderLoader(filament::Engine* engine);
|
||||
|
||||
} // namespace gltfio
|
||||
|
||||
#endif // GLTFIO_MATERIALPROVIDER_H
|
||||
163
ios/include/gltfio/ResourceLoader.h
Normal file
163
ios/include/gltfio/ResourceLoader.h
Normal file
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* 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 GLTFIO_RESOURCELOADER_H
|
||||
#define GLTFIO_RESOURCELOADER_H
|
||||
|
||||
#include <gltfio/FilamentAsset.h>
|
||||
|
||||
#include <backend/BufferDescriptor.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
namespace filament {
|
||||
class Engine;
|
||||
}
|
||||
|
||||
namespace gltfio {
|
||||
|
||||
struct FFilamentAsset;
|
||||
class AssetPool;
|
||||
|
||||
/**
|
||||
* \struct ResourceConfiguration ResourceLoader.h gltfio/ResourceLoader.h
|
||||
* \brief Construction parameters for ResourceLoader.
|
||||
*/
|
||||
struct ResourceConfiguration {
|
||||
//! The engine that the loader should pass to builder objects (e.g.
|
||||
//! filament::Texture::Builder).
|
||||
class filament::Engine* engine;
|
||||
|
||||
//! Optional path or URI that points to the base glTF file. This is used solely
|
||||
//! to resolve relative paths. The string pointer is not retained.
|
||||
const char* gltfPath;
|
||||
|
||||
//! If true, adjusts skinning weights to sum to 1. Well formed glTF files do not need this,
|
||||
//! but it is useful for robustness.
|
||||
bool normalizeSkinningWeights;
|
||||
|
||||
//! 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.
|
||||
bool recomputeBoundingBoxes;
|
||||
};
|
||||
|
||||
/**
|
||||
* \class ResourceLoader ResourceLoader.h gltfio/ResourceLoader.h
|
||||
* \brief Prepares and uploads vertex buffers and textures to the GPU.
|
||||
*
|
||||
* For a usage example, see the documentation for AssetLoader.
|
||||
*
|
||||
* ResourceLoader must be destroyed on the same thread that calls filament::Renderer::render()
|
||||
* because it listens to filament::backend::BufferDescriptor callbacks in order to determine when to
|
||||
* free CPU-side data blobs.
|
||||
*
|
||||
* \todo If clients persist their ResourceLoader, Filament textures are currently re-created upon
|
||||
* subsequent re-loads of the same asset. To fix this, we would need to enable shared ownership
|
||||
* of Texture objects between ResourceLoader and FilamentAsset.
|
||||
*/
|
||||
class UTILS_PUBLIC ResourceLoader {
|
||||
public:
|
||||
using BufferDescriptor = filament::backend::BufferDescriptor;
|
||||
|
||||
ResourceLoader(const ResourceConfiguration& config);
|
||||
~ResourceLoader();
|
||||
|
||||
/**
|
||||
* Feeds the binary content of an external resource into the loader's URI cache.
|
||||
*
|
||||
* On some platforms, `ResourceLoader` does not know how to download external resources on its
|
||||
* own (external resources might come from a filesystem, a database, or the internet) so this
|
||||
* method allows clients to download external resources and push them to the loader.
|
||||
*
|
||||
* Every resource should be passed in before calling #loadResources or #asyncBeginLoad. See
|
||||
* also FilamentAsset#getResourceUris.
|
||||
*
|
||||
* When loading GLB files (as opposed to JSON-based glTF files), clients typically do not
|
||||
* need to call this method.
|
||||
*/
|
||||
void addResourceData(const char* uri, BufferDescriptor&& buffer);
|
||||
|
||||
/**
|
||||
* Checks if the given resource has already been added to the URI cache.
|
||||
*/
|
||||
bool hasResourceData(const char* uri) const;
|
||||
|
||||
/**
|
||||
* Frees memory by evicting the URI cache that was populated via addResourceData.
|
||||
*
|
||||
* This can be called only after a model is fully loaded or after loading has been cancelled.
|
||||
*/
|
||||
void evictResourceData();
|
||||
|
||||
/**
|
||||
* Loads resources for the given asset from the filesystem or data cache and "finalizes" the
|
||||
* asset by transforming the vertex data format if necessary, decoding image files, supplying
|
||||
* tangent data, etc.
|
||||
*
|
||||
* Returns false if resources have already been loaded, or if one or more resources could not
|
||||
* be loaded.
|
||||
*
|
||||
* Note: this method is synchronous and blocks until all textures have been decoded.
|
||||
* For an asynchronous alternative, see #asyncBeginLoad.
|
||||
*/
|
||||
bool loadResources(FilamentAsset* asset);
|
||||
|
||||
/**
|
||||
* Starts an asynchronous resource load.
|
||||
*
|
||||
* Returns false if the loading process was unable to start.
|
||||
*
|
||||
* This is an alternative to #loadResources and requires periodic calls to #asyncUpdateLoad.
|
||||
* On multi-threaded systems this creates threads for texture decoding.
|
||||
*/
|
||||
bool asyncBeginLoad(FilamentAsset* asset);
|
||||
|
||||
/**
|
||||
* Gets the status of an asynchronous resource load as a percentage in [0,1].
|
||||
*/
|
||||
float asyncGetLoadProgress() const;
|
||||
|
||||
/**
|
||||
* Updates an asynchronous load by performing any pending work that must take place
|
||||
* on the main thread.
|
||||
*
|
||||
* Clients must periodically call this until #asyncGetLoadProgress returns 100%.
|
||||
* After progress reaches 100%, calling this is harmless; it just does nothing.
|
||||
*/
|
||||
void asyncUpdateLoad();
|
||||
|
||||
/**
|
||||
* Cancels pending decoder jobs, frees all CPU-side texel data, and flushes the Engine.
|
||||
*
|
||||
* Calling this is only necessary if the asyncBeginLoad API was used
|
||||
* and cancellation is required before progress reaches 100%.
|
||||
*/
|
||||
void asyncCancelLoad();
|
||||
|
||||
private:
|
||||
bool loadResources(FFilamentAsset* asset, bool async);
|
||||
void applySparseData(FFilamentAsset* asset) const;
|
||||
void normalizeSkinningWeights(FFilamentAsset* asset) const;
|
||||
void updateBoundingBoxes(FFilamentAsset* asset) const;
|
||||
AssetPool* mPool;
|
||||
struct Impl;
|
||||
Impl* pImpl;
|
||||
};
|
||||
|
||||
} // namespace gltfio
|
||||
|
||||
#endif // GLTFIO_RESOURCELOADER_H
|
||||
|
||||
46
ios/include/gltfio/resources/gltfresources.h
Normal file
46
ios/include/gltfio/resources/gltfresources.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#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
|
||||
16
ios/include/gltfio/resources/gltfresources_lite.h
Normal file
16
ios/include/gltfio/resources/gltfresources_lite.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#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
|
||||
199
ios/include/ibl/Cubemap.h
Normal file
199
ios/include/ibl/Cubemap.h
Normal file
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
* 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 */
|
||||
91
ios/include/ibl/CubemapIBL.h
Normal file
91
ios/include/ibl/CubemapIBL.h
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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 */
|
||||
125
ios/include/ibl/CubemapSH.h
Normal file
125
ios/include/ibl/CubemapSH.h
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* 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 */
|
||||
124
ios/include/ibl/CubemapUtils.h
Normal file
124
ios/include/ibl/CubemapUtils.h
Normal file
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* 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 */
|
||||
77
ios/include/ibl/Image.h
Normal file
77
ios/include/ibl/Image.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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 */
|
||||
57
ios/include/ibl/utilities.h
Normal file
57
ios/include/ibl/utilities.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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 */
|
||||
381
ios/include/image/ColorTransform.h
Normal file
381
ios/include/image/ColorTransform.h
Normal file
@@ -0,0 +1,381 @@
|
||||
/*
|
||||
* 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 IMAGE_COLORTRANSFORM_H_
|
||||
#define IMAGE_COLORTRANSFORM_H_
|
||||
|
||||
#include <image/LinearImage.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <math/scalar.h>
|
||||
#include <math/vec3.h>
|
||||
#include <math/vec4.h>
|
||||
#include <math/half.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
namespace image {
|
||||
|
||||
template <typename T>
|
||||
uint32_t linearToRGB_10_11_11_REV(const T& linear) {
|
||||
using fp11 = filament::math::fp<0, 5, 6>;
|
||||
using fp10 = filament::math::fp<0, 5, 5>;
|
||||
// the max value for a RGB_11_11_10 is {65024, 65024, 64512} : (2 - 2^-M) * 2^(E-1)
|
||||
// we clamp to the min of that
|
||||
fp11 r = fp11::fromf(std::min(64512.0f, linear[0]));
|
||||
fp11 g = fp11::fromf(std::min(64512.0f, linear[1]));
|
||||
fp10 b = fp10::fromf(std::min(64512.0f, linear[2]));
|
||||
uint32_t ir = r.bits & 0x7FF;
|
||||
uint32_t ig = g.bits & 0x7FF;
|
||||
uint32_t ib = b.bits & 0x3FF;
|
||||
return (ib << 22) | (ig << 11) | ir;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline filament::math::float4 linearToRGBM(const T& linear) {
|
||||
using filament::math::float4;
|
||||
|
||||
float4 RGBM(linear[0], linear[1], linear[2], 1.0f);
|
||||
|
||||
// Linear to gamma space
|
||||
RGBM.rgb = sqrt(RGBM.rgb);
|
||||
// Set the range
|
||||
RGBM.rgb /= 16.0f;
|
||||
|
||||
float maxComponent = std::max(std::max(RGBM.r, RGBM.g), std::max(RGBM.b, 1e-6f));
|
||||
// Don't let M go below 1 in the [0..16] range
|
||||
RGBM.a = filament::math::clamp(maxComponent, 1.0f / 16.0f, 1.0f);
|
||||
RGBM.a = std::ceil(RGBM.a * 255.0f) / 255.0f;
|
||||
|
||||
RGBM.rgb = saturate(RGBM.rgb / RGBM.a);
|
||||
|
||||
return RGBM;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline filament::math::float3 RGBMtoLinear(const T& rgbm) {
|
||||
using filament::math::float3;
|
||||
|
||||
float3 linear(rgbm[0], rgbm[1], rgbm[2]);
|
||||
linear *= rgbm.a * 16.0f;
|
||||
// Gamma to linear space
|
||||
return linear * linear;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline filament::math::float3 linearTosRGB(const T& linear) {
|
||||
using filament::math::float3;
|
||||
constexpr float a = 0.055f;
|
||||
constexpr float a1 = 1.055f;
|
||||
constexpr float p = 1 / 2.4f;
|
||||
float3 sRGB;
|
||||
for (size_t i=0 ; i<3 ; i++) {
|
||||
if (linear[i] <= 0.0031308f) {
|
||||
sRGB[i] = linear[i] * 12.92f;
|
||||
} else {
|
||||
sRGB[i] = a1 * std::pow(linear[i], p) - a;
|
||||
}
|
||||
}
|
||||
return sRGB;
|
||||
}
|
||||
|
||||
inline float linearTosRGB(float linear) {
|
||||
if (linear <= 0.0031308f) {
|
||||
return linear * 12.92f;
|
||||
} else {
|
||||
constexpr float a = 0.055f;
|
||||
constexpr float a1 = 1.055f;
|
||||
constexpr float p = 1 / 2.4f;
|
||||
return a1 * std::pow(linear, p) - a;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T sRGBToLinear(const T& sRGB);
|
||||
|
||||
template<>
|
||||
inline filament::math::float3 sRGBToLinear(const filament::math::float3& sRGB) {
|
||||
using filament::math::float3;
|
||||
constexpr float a = 0.055f;
|
||||
constexpr float a1 = 1.055f;
|
||||
constexpr float p = 2.4f;
|
||||
float3 linear;
|
||||
for (size_t i=0 ; i<3 ; i++) {
|
||||
if (sRGB[i] <= 0.04045f) {
|
||||
linear[i] = sRGB[i] * (1.0f / 12.92f);
|
||||
} else {
|
||||
linear[i] = std::pow((sRGB[i] + a) / a1, p);
|
||||
}
|
||||
}
|
||||
return linear;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline filament::math::float4 sRGBToLinear(const filament::math::float4& sRGB) {
|
||||
using filament::math::float4;
|
||||
constexpr float a = 0.055f;
|
||||
constexpr float a1 = 1.055f;
|
||||
constexpr float p = 2.4f;
|
||||
float4 linear;
|
||||
for (size_t i=0 ; i<3 ; i++) {
|
||||
if (sRGB[i] <= 0.04045f) {
|
||||
linear[i] = sRGB[i] * (1.0f / 12.92f);
|
||||
} else {
|
||||
linear[i] = std::pow((sRGB[i] + a) / a1, p);
|
||||
}
|
||||
}
|
||||
linear[3] = sRGB[3];
|
||||
return linear;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T linearToSRGB(const T& color);
|
||||
|
||||
template<>
|
||||
inline filament::math::float3 linearToSRGB(const filament::math::float3& color) {
|
||||
using filament::math::float3;
|
||||
float3 sRGBColor{color};
|
||||
#pragma nounroll
|
||||
for (size_t i = 0; i < sRGBColor.size(); i++) {
|
||||
sRGBColor[i] = (sRGBColor[i] <= 0.0031308f) ?
|
||||
sRGBColor[i] * 12.92f : (powf(sRGBColor[i], 1.0f / 2.4f) * 1.055f) - 0.055f;
|
||||
}
|
||||
return sRGBColor;
|
||||
}
|
||||
|
||||
// Creates a n-channel sRGB image from a linear floating-point image.
|
||||
// The source image can have more than N channels, but only the first N are converted to sRGB.
|
||||
template<typename T, int N = 3>
|
||||
std::unique_ptr<uint8_t[]> fromLinearTosRGB(const LinearImage& image) {
|
||||
const size_t w = image.getWidth();
|
||||
const size_t h = image.getHeight();
|
||||
const size_t nchan = image.getChannels();
|
||||
assert(nchan >= N);
|
||||
std::unique_ptr<uint8_t[]> dst(new uint8_t[w * h * N * sizeof(T)]);
|
||||
T* d = reinterpret_cast<T*>(dst.get());
|
||||
for (size_t y = 0; y < h; ++y) {
|
||||
float const* p = image.getPixelRef(0, y);
|
||||
for (size_t x = 0; x < w; ++x, p += nchan, d += N) {
|
||||
for (int n = 0; n < N; n++) {
|
||||
float source = n < 3 ? linearTosRGB(p[n]) : p[n];
|
||||
float target = filament::math::saturate(source) * std::numeric_limits<T>::max() + 0.5f;
|
||||
d[n] = T(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
// Creates a N-channel RGB u8 image from a f32 image.
|
||||
template<typename T, int N = 3>
|
||||
std::unique_ptr<uint8_t[]> fromLinearToRGB(const LinearImage& image) {
|
||||
size_t w = image.getWidth();
|
||||
size_t h = image.getHeight();
|
||||
size_t channels = image.getChannels();
|
||||
assert(channels >= N);
|
||||
std::unique_ptr<uint8_t[]> dst(new uint8_t[w * h * N * sizeof(T)]);
|
||||
T* d = reinterpret_cast<T*>(dst.get());
|
||||
for (size_t y = 0; y < h; ++y) {
|
||||
float const* p = image.getPixelRef(0, y);
|
||||
for (size_t x = 0; x < w; ++x, p += channels, d += N) {
|
||||
for (int n = 0; n < N; n++) {
|
||||
float target = filament::math::saturate(p[n]) * std::numeric_limits<T>::max() + 0.5f;
|
||||
d[n] = T(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
// Creates a 4-channel RGBM u8 image from a f32 image.
|
||||
// The source image can have three or more channels, but only the first three are honored.
|
||||
template <typename T>
|
||||
std::unique_ptr<uint8_t[]> fromLinearToRGBM(const LinearImage& image) {
|
||||
using namespace filament::math;
|
||||
size_t w = image.getWidth();
|
||||
size_t h = image.getHeight();
|
||||
UTILS_UNUSED_IN_RELEASE size_t channels = image.getChannels();
|
||||
assert(channels >= 3);
|
||||
std::unique_ptr<uint8_t[]> dst(new uint8_t[w * h * 4 * sizeof(T)]);
|
||||
T* d = reinterpret_cast<T*>(dst.get());
|
||||
for (size_t y = 0; y < h; ++y) {
|
||||
for (size_t x = 0; x < w; ++x, d += 4) {
|
||||
auto src = image.get<float3>((uint32_t) x, (uint32_t) y);
|
||||
float4 l(linearToRGBM(*src) * std::numeric_limits<T>::max() + 0.5f);
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
d[i] = T(l[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
// Creates a 3-channel RGB_10_11_11_REV image from a f32 image.
|
||||
// The source image can have three or more channels, but only the first three are honored.
|
||||
inline std::unique_ptr<uint8_t[]> fromLinearToRGB_10_11_11_REV(const LinearImage& image) {
|
||||
using namespace filament::math;
|
||||
size_t w = image.getWidth();
|
||||
size_t h = image.getHeight();
|
||||
UTILS_UNUSED_IN_RELEASE size_t channels = image.getChannels();
|
||||
assert(channels >= 3);
|
||||
std::unique_ptr<uint8_t[]> dst(new uint8_t[w * h * sizeof(uint32_t)]);
|
||||
uint8_t* d = dst.get();
|
||||
for (size_t y = 0; y < h; ++y) {
|
||||
for (size_t x = 0; x < w; ++x, d += sizeof(uint32_t)) {
|
||||
auto src = image.get<float3>((uint32_t)x, (uint32_t)y);
|
||||
uint32_t v = linearToRGB_10_11_11_REV(*src);
|
||||
*reinterpret_cast<uint32_t*>(d) = v;
|
||||
}
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
// Creates a packed single-channel integer-based image from a floating-point image.
|
||||
// For example if T is uint8_t, then this performs a transformation from [0,1] to [0,255].
|
||||
template <typename T>
|
||||
std::unique_ptr<uint8_t[]> fromLinearToGrayscale(const LinearImage& image) {
|
||||
const size_t w = image.getWidth();
|
||||
const size_t h = image.getHeight();
|
||||
assert(image.getChannels() == 1);
|
||||
std::unique_ptr<uint8_t[]> dst(new uint8_t[w * h * sizeof(T)]);
|
||||
T* d = reinterpret_cast<T*>(dst.get());
|
||||
for (size_t y = 0; y < h; ++y) {
|
||||
float const* p = image.getPixelRef(0, y);
|
||||
for (size_t x = 0; x < w; ++x, ++p, ++d) {
|
||||
const float gray = filament::math::saturate(*p) * std::numeric_limits<T>::max() + 0.5f;
|
||||
d[0] = T(gray);
|
||||
}
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
// Constructs a 3-channel LinearImage from an untyped data blob.
|
||||
// The "proc" lambda converts a single color component into a float.
|
||||
// The "transform" lambda performs an arbitrary float-to-float transformation.
|
||||
template<typename T, typename PROCESS, typename TRANSFORM>
|
||||
static LinearImage toLinear(size_t w, size_t h, size_t bpr,
|
||||
const uint8_t* src, PROCESS proc, TRANSFORM transform) {
|
||||
LinearImage result((uint32_t) w, (uint32_t) h, 3);
|
||||
auto d = result.get< filament::math::float3>();
|
||||
for (size_t y = 0; y < h; ++y) {
|
||||
T const* p = reinterpret_cast<T const*>(src + y * bpr);
|
||||
for (size_t x = 0; x < w; ++x, p += 3) {
|
||||
filament::math::float3 sRGB(proc(p[0]), proc(p[1]), proc(p[2]));
|
||||
sRGB /= std::numeric_limits<T>::max();
|
||||
*d++ = transform(sRGB);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Constructs a 3-channel LinearImage from an untyped data blob.
|
||||
// The "proc" lambda converts a single color component into a float.
|
||||
// The "transform" lambda performs an arbitrary float-to-float transformation.
|
||||
template<typename T, typename PROCESS, typename TRANSFORM>
|
||||
static LinearImage toLinear(size_t w, size_t h, size_t bpr,
|
||||
const std::unique_ptr<uint8_t[]>& src, PROCESS proc, TRANSFORM transform) {
|
||||
return toLinear<T>(w, h, bpr, src.get(), proc, transform);
|
||||
}
|
||||
|
||||
// Constructs a 4-channel LinearImage from an untyped data blob.
|
||||
// The "proc" lambda converts a single color component into a float.
|
||||
// the "transform" lambda performs an arbitrary float-to-float transformation.
|
||||
template<typename T, typename PROCESS, typename TRANSFORM>
|
||||
static LinearImage toLinearWithAlpha(size_t w, size_t h, size_t bpr,
|
||||
const uint8_t* src, PROCESS proc, TRANSFORM transform) {
|
||||
LinearImage result((uint32_t) w, (uint32_t) h, 4);
|
||||
auto d = result.get< filament::math::float4>();
|
||||
for (size_t y = 0; y < h; ++y) {
|
||||
T const* p = reinterpret_cast<T const*>(src + y * bpr);
|
||||
for (size_t x = 0; x < w; ++x, p += 4) {
|
||||
filament::math::float4 sRGB(proc(p[0]), proc(p[1]), proc(p[2]), proc(p[3]));
|
||||
sRGB /= std::numeric_limits<T>::max();
|
||||
*d++ = transform(sRGB);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Constructs a 4-channel LinearImage from an untyped data blob.
|
||||
// The "proc" lambda converts a single color component into a float.
|
||||
// the "transform" lambda performs an arbitrary float-to-float transformation.
|
||||
template<typename T, typename PROCESS, typename TRANSFORM>
|
||||
static LinearImage toLinearWithAlpha(size_t w, size_t h, size_t bpr,
|
||||
const std::unique_ptr<uint8_t[]>& src, PROCESS proc, TRANSFORM transform) {
|
||||
return toLinearWithAlpha<T>(w, h, bpr, src.get(), proc, transform);
|
||||
}
|
||||
|
||||
// Constructs a 3-channel LinearImage from RGBM data.
|
||||
inline LinearImage toLinearFromRGBM( filament::math::float4 const* src, uint32_t w, uint32_t h) {
|
||||
LinearImage result(w, h, 3);
|
||||
auto dst = result.get< filament::math::float3>();
|
||||
for (uint32_t row = 0; row < h; ++row) {
|
||||
for (uint32_t col = 0; col < w; ++col, ++src, ++dst) {
|
||||
*dst = RGBMtoLinear(*src);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
inline LinearImage fromLinearToRGBM(const LinearImage& image) {
|
||||
assert(image.getChannels() == 3);
|
||||
const uint32_t w = image.getWidth(), h = image.getHeight();
|
||||
LinearImage result(w, h, 4);
|
||||
auto src = image.get< filament::math::float3>();
|
||||
auto dst = result.get< filament::math::float4>();
|
||||
for (uint32_t row = 0; row < h; ++row) {
|
||||
for (uint32_t col = 0; col < w; ++col, ++src, ++dst) {
|
||||
*dst = linearToRGBM(*src);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static LinearImage toLinearWithAlpha(size_t w, size_t h, size_t bpr, const uint8_t* src) {
|
||||
LinearImage result(w, h, 4);
|
||||
filament::math::float4* d = reinterpret_cast<filament::math::float4*>(result.getPixelRef(0, 0));
|
||||
for (size_t y = 0; y < h; ++y) {
|
||||
T const* p = reinterpret_cast<T const*>(src + y * bpr);
|
||||
for (size_t x = 0; x < w; ++x, p += 4) {
|
||||
filament::math::float3 sRGB(p[0], p[1], p[2]);
|
||||
sRGB /= std::numeric_limits<T>::max();
|
||||
*d++ = filament::math::float4(sRGBToLinear(sRGB), 1.0f);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static LinearImage toLinear(size_t w, size_t h, size_t bpr, const uint8_t* src) {
|
||||
LinearImage result(w, h, 3);
|
||||
filament::math::float3* d = reinterpret_cast<filament::math::float3*>(result.getPixelRef(0, 0));
|
||||
for (size_t y = 0; y < h; ++y) {
|
||||
T const* p = reinterpret_cast<T const*>(src + y * bpr);
|
||||
for (size_t x = 0; x < w; ++x, p += 3) {
|
||||
filament::math::float3 sRGB(p[0], p[1], p[2]);
|
||||
sRGB /= std::numeric_limits<T>::max();
|
||||
*d++ = sRGBToLinear(sRGB);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace Image
|
||||
|
||||
#endif // IMAGE_COLORTRANSFORM_H_
|
||||
91
ios/include/image/ImageOps.h
Normal file
91
ios/include/image/ImageOps.h
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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 IMAGE_IMAGEOPS_H
|
||||
#define IMAGE_IMAGEOPS_H
|
||||
|
||||
#include <image/LinearImage.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <initializer_list>
|
||||
|
||||
namespace image {
|
||||
|
||||
// Concatenates images horizontally to create a filmstrip atlas, similar to numpy's hstack.
|
||||
UTILS_PUBLIC LinearImage horizontalStack(std::initializer_list<LinearImage> images);
|
||||
UTILS_PUBLIC LinearImage horizontalStack(LinearImage const* img, size_t count);
|
||||
|
||||
// Concatenates images vertically to create a filmstrip atlas, similar to numpy's vstack.
|
||||
UTILS_PUBLIC LinearImage verticalStack(std::initializer_list<LinearImage> images);
|
||||
UTILS_PUBLIC LinearImage verticalStack(LinearImage const* img, size_t count);
|
||||
|
||||
// Horizontally or vertically mirror the given image.
|
||||
UTILS_PUBLIC LinearImage horizontalFlip(const LinearImage& image);
|
||||
UTILS_PUBLIC LinearImage verticalFlip(const LinearImage& image);
|
||||
|
||||
// Transforms normals (components live in [-1,+1]) into colors (components live in [0,+1]).
|
||||
UTILS_PUBLIC LinearImage vectorsToColors(const LinearImage& image);
|
||||
UTILS_PUBLIC LinearImage colorsToVectors(const LinearImage& image);
|
||||
|
||||
// Creates a single-channel image by extracting the selected channel.
|
||||
UTILS_PUBLIC LinearImage extractChannel(const LinearImage& image, uint32_t channel);
|
||||
|
||||
// Constructs a multi-channel image by copying data from a sequence of single-channel images.
|
||||
UTILS_PUBLIC LinearImage combineChannels(std::initializer_list<LinearImage> images);
|
||||
UTILS_PUBLIC LinearImage combineChannels(LinearImage const* img, size_t count);
|
||||
|
||||
// Generates a new image with rows & columns swapped.
|
||||
UTILS_PUBLIC LinearImage transpose(const LinearImage& image);
|
||||
|
||||
// Extracts pixels by specifying a crop window where (0,0) is the top-left corner of the image.
|
||||
// The boundary is specified as Left Top Right Bottom.
|
||||
UTILS_PUBLIC
|
||||
LinearImage cropRegion(const LinearImage& image, uint32_t l, uint32_t t, uint32_t r, uint32_t b);
|
||||
|
||||
// Lexicographically compares two images, similar to memcmp.
|
||||
UTILS_PUBLIC int compare(const LinearImage& a, const LinearImage& b, float epsilon = 0.0f);
|
||||
|
||||
// Sets all pixels in all channels to the given value.
|
||||
UTILS_PUBLIC void clearToValue(LinearImage& img, float value);
|
||||
|
||||
// Called by the coordinate field generator to query if a pixel is within the region of interest.
|
||||
using PresenceCallback = bool(*)(const LinearImage& img, uint32_t col, uint32_t row, void* user);
|
||||
|
||||
// Generates a two-channel field of non-normalized coordinates that indicate the nearest pixel
|
||||
// whose presence function returns true. This is the first step before generating a distance
|
||||
// field or generalized Voronoi map.
|
||||
UTILS_PUBLIC
|
||||
LinearImage computeCoordField(const LinearImage& src, PresenceCallback presence, void* user);
|
||||
|
||||
// Generates a single-channel Euclidean distance field with positive values outside the region
|
||||
// of interest in the source image, and zero values inside. If sqrt is false, the computed
|
||||
// distances are squared. If signed distance (SDF) is desired, this function can be called a second
|
||||
// time using an inverted source field.
|
||||
UTILS_PUBLIC LinearImage edtFromCoordField(const LinearImage& coordField, bool sqrt);
|
||||
|
||||
// Dereferences the given coordinate field. Useful for creating Voronoi diagrams or dilated images.
|
||||
UTILS_PUBLIC
|
||||
LinearImage voronoiFromCoordField(const LinearImage& coordField, const LinearImage& src);
|
||||
|
||||
// Copies content of a source image into a target image. Requires width/height/channels to match.
|
||||
UTILS_PUBLIC void blitImage(LinearImage& target, const LinearImage& source);
|
||||
|
||||
} // namespace image
|
||||
|
||||
|
||||
#endif /* IMAGE_LINEARIMAGE_H */
|
||||
164
ios/include/image/ImageSampler.h
Normal file
164
ios/include/image/ImageSampler.h
Normal file
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* 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 IMAGE_IMAGESAMPLER_H
|
||||
#define IMAGE_IMAGESAMPLER_H
|
||||
|
||||
#include <image/LinearImage.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
namespace image {
|
||||
|
||||
/**
|
||||
* Value of a single point sample, allocated according to the number of image channels.
|
||||
*/
|
||||
struct UTILS_PUBLIC SingleSample {
|
||||
float& operator[](int index) { return *(data + index); }
|
||||
float* data = nullptr;
|
||||
~SingleSample();
|
||||
};
|
||||
|
||||
/**
|
||||
* Controls the weighted average used across a window of source samples.
|
||||
*/
|
||||
enum class Filter {
|
||||
DEFAULT, // Selects MITCHELL or LANCZOS dynamically.
|
||||
BOX, // Computes the un-weighted average over the filter radius.
|
||||
NEAREST, // Copies the source sample nearest to the center of the filter.
|
||||
HERMITE, // Also known as "smoothstep", has some nice properties.
|
||||
GAUSSIAN_SCALARS, // Standard Gaussian filter with sigma = 0.5
|
||||
GAUSSIAN_NORMALS, // Same as GAUSSIAN_SCALARS, but interpolates unitized vectors.
|
||||
MITCHELL, // Cubic resampling per Mitchell-Netravali, default for magnification.
|
||||
LANCZOS, // Popular sinc-based filter, default for minification.
|
||||
MINIMUM // Takes a min val rather than avg, perhaps useful for depth maps and SDF's.
|
||||
};
|
||||
|
||||
/**
|
||||
* Defines a viewport inside the texture such that (0,0) is at the top-left corner of the top-left
|
||||
* pixel, and (1,1) is at the bottom-right corner of the bottom-corner pixel.
|
||||
*/
|
||||
struct Region {
|
||||
float left;
|
||||
float top;
|
||||
float right;
|
||||
float bottom;
|
||||
};
|
||||
|
||||
/**
|
||||
* Transforms the texel fetching operation when sampling from adjacent images.
|
||||
*/
|
||||
enum class Orientation {
|
||||
STANDARD = 0,
|
||||
FLIP_X = 1 << 0,
|
||||
FLIP_Y = 1 << 1,
|
||||
FLIP_XY = FLIP_X | FLIP_Y
|
||||
};
|
||||
|
||||
/**
|
||||
* Specifies how to generate samples that lie outside the boundaries of the source region.
|
||||
*/
|
||||
struct Boundary {
|
||||
enum {
|
||||
EXCLUDE, // Ignore the samples and renormalize the filter. This is probably what you want.
|
||||
REGION, // Keep samples that are outside sourceRegion if they are still within the image.
|
||||
CLAMP, // Pretend the edge pixel is repeated forever. Gives edge pixels more weight.
|
||||
REPEAT, // Resample from the region, wrapping back to the front of the row or column.
|
||||
MIRROR, // Resample from the region but assume that it has been flipped.
|
||||
COLOR, // Use the specified constant color.
|
||||
NEIGHBOR // Sample from an adjacent image.
|
||||
} mode = EXCLUDE;
|
||||
SingleSample color; // Used only if mode = COLOR
|
||||
LinearImage* neighbor = nullptr; // Used only if mode = NEIGHBOR
|
||||
Orientation orientation; // Used only if mode = NEIGHBOR
|
||||
};
|
||||
|
||||
/**
|
||||
* Configuration for the resampleImage function. Provides reasonable defaults.
|
||||
*/
|
||||
struct ImageSampler {
|
||||
Filter horizontalFilter = Filter::DEFAULT;
|
||||
Filter verticalFilter = Filter::DEFAULT;
|
||||
Region sourceRegion = {0, 0, 1, 1};
|
||||
float filterRadiusMultiplier = 1;
|
||||
Boundary east;
|
||||
Boundary north;
|
||||
Boundary west;
|
||||
Boundary south;
|
||||
};
|
||||
|
||||
/**
|
||||
* Resizes or blurs the given linear image, producing a new linear image with the given dimensions.
|
||||
*/
|
||||
UTILS_PUBLIC
|
||||
LinearImage resampleImage(const LinearImage& source, uint32_t width, uint32_t height,
|
||||
const ImageSampler& sampler);
|
||||
|
||||
/**
|
||||
* Resizes the given linear image using a simplified API that takes target dimensions and filter.
|
||||
*/
|
||||
UTILS_PUBLIC
|
||||
LinearImage resampleImage(const LinearImage& source, uint32_t width, uint32_t height,
|
||||
Filter filter = Filter::DEFAULT);
|
||||
|
||||
/**
|
||||
* Computes a single sample for the given texture coordinate and writes the resulting color
|
||||
* components into the given output holder.
|
||||
*
|
||||
* For decent performance, do not call this across the entire image, instead call resampleImage.
|
||||
* On the first call, pass in a default SingleSample to allocate the result holder. For example:
|
||||
*
|
||||
* SingleSample result;
|
||||
* computeSingleSample(img, 0.5f, 0.5f, &result);
|
||||
* printf("r g b = %f %f %f\n", result[0], result[1], result[2]);
|
||||
* computeSingleSample(img, 0.9f, 0.1f, &result);
|
||||
* printf("r g b = %f %f %f\n", result[0], result[1], result[2]);
|
||||
*
|
||||
* The x y coordinates live in "texture space" such that (0.0f, 0.0f) is the upper-left boundary of
|
||||
* the top-left pixel and (+1.0f, +1.0f) is the lower-right boundary of the bottom-right pixel.
|
||||
*/
|
||||
UTILS_PUBLIC
|
||||
void computeSingleSample(const LinearImage& source, float x, float y, SingleSample* result,
|
||||
Filter filter = Filter::BOX);
|
||||
|
||||
/**
|
||||
* Generates a sequence of miplevels using the requested filter. To determine the number of mips
|
||||
* it would take to get down to 1x1, see getMipmapCount.
|
||||
*
|
||||
* Source image need not be power-of-two. In the result vector, the half-size image is returned at
|
||||
* index 0, the quarter-size image is at index 1, etc. Please note that the original-sized image is
|
||||
* not included.
|
||||
*/
|
||||
UTILS_PUBLIC
|
||||
void generateMipmaps(const LinearImage& source, Filter, LinearImage* result, uint32_t mipCount);
|
||||
|
||||
/**
|
||||
* Returns the number of miplevels it would take to downsample the given image down to 1x1. This
|
||||
* number does not include the original image (i.e. mip 0).
|
||||
*/
|
||||
UTILS_PUBLIC
|
||||
uint32_t getMipmapCount(const LinearImage& source);
|
||||
|
||||
/**
|
||||
* Given the string name of a filter, converts it to uppercase and returns the corresponding
|
||||
* enum value. If no corresponding enumerant exists, returns DEFAULT.
|
||||
*/
|
||||
UTILS_PUBLIC
|
||||
Filter filterFromString(const char* name);
|
||||
|
||||
} // namespace image
|
||||
|
||||
#endif /* IMAGE_IMAGESAMPLER_H */
|
||||
279
ios/include/image/KtxBundle.h
Normal file
279
ios/include/image/KtxBundle.h
Normal file
@@ -0,0 +1,279 @@
|
||||
/*
|
||||
* 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 IMAGE_KTXBUNDLE_H
|
||||
#define IMAGE_KTXBUNDLE_H
|
||||
|
||||
#include <math/vec3.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
namespace image {
|
||||
|
||||
struct KtxInfo {
|
||||
uint32_t endianness;
|
||||
uint32_t glType;
|
||||
uint32_t glTypeSize;
|
||||
uint32_t glFormat;
|
||||
uint32_t glInternalFormat;
|
||||
uint32_t glBaseInternalFormat;
|
||||
uint32_t pixelWidth;
|
||||
uint32_t pixelHeight;
|
||||
uint32_t pixelDepth;
|
||||
};
|
||||
|
||||
struct KtxBlobIndex {
|
||||
uint32_t mipLevel;
|
||||
uint32_t arrayIndex;
|
||||
uint32_t cubeFace;
|
||||
};
|
||||
|
||||
struct KtxBlobList;
|
||||
struct KtxMetadata;
|
||||
|
||||
/**
|
||||
* KtxBundle is a structured set of opaque data blobs that can be passed straight to the GPU, such
|
||||
* that a single bundle corresponds to a single texture object. It is well suited for storing
|
||||
* block-compressed texture data.
|
||||
*
|
||||
* One bundle may be comprised of several mipmap levels, cubemap faces, and array elements. The
|
||||
* number of blobs is immutable, and is determined as follows.
|
||||
*
|
||||
* blob_count = mip_count * array_length * (cubemap ? 6 : 1)
|
||||
*
|
||||
* Bundles can be quickly serialized to a certain file format (see below link), but this class lives
|
||||
* in the image lib rather than imageio because it has no dependencies, and does not support CPU
|
||||
* decoding.
|
||||
*
|
||||
* https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/
|
||||
*/
|
||||
class UTILS_PUBLIC KtxBundle {
|
||||
public:
|
||||
|
||||
~KtxBundle();
|
||||
|
||||
/**
|
||||
* Creates a hierarchy of empty texture blobs, to be filled later via setBlob().
|
||||
*/
|
||||
KtxBundle(uint32_t numMipLevels, uint32_t arrayLength, bool isCubemap);
|
||||
|
||||
/**
|
||||
* Creates a new bundle by deserializing the given data.
|
||||
*
|
||||
* Typically, this constructor is used to consume the contents of a KTX file.
|
||||
*/
|
||||
KtxBundle(uint8_t const* bytes, uint32_t nbytes);
|
||||
|
||||
/**
|
||||
* Serializes the bundle into the given target memory. Returns false if there's not enough
|
||||
* memory.
|
||||
*
|
||||
* Typically, this method is used to write out the contents of a KTX file.
|
||||
*/
|
||||
bool serialize(uint8_t* destination, uint32_t numBytes) const;
|
||||
|
||||
/**
|
||||
* Computes the size (in bytes) of the serialized bundle.
|
||||
*/
|
||||
uint32_t getSerializedLength() const;
|
||||
|
||||
/**
|
||||
* Gets or sets information about the texture object, such as format and type.
|
||||
*/
|
||||
KtxInfo const& getInfo() const { return mInfo; }
|
||||
KtxInfo& info() { return mInfo; }
|
||||
|
||||
/**
|
||||
* Gets or sets key/value metadata.
|
||||
*/
|
||||
const char* getMetadata(const char* key, size_t* valueSize = nullptr) const;
|
||||
void setMetadata(const char* key, const char* value);
|
||||
|
||||
/**
|
||||
* Parses the key="sh" metadata and returns 3 bands of data.
|
||||
*
|
||||
* Assumes 3 bands for a total of 9 RGB coefficients.
|
||||
* Returns true if successful.
|
||||
*/
|
||||
bool getSphericalHarmonics(filament::math::float3* result);
|
||||
|
||||
/**
|
||||
* Gets the number of miplevels (this is never zero).
|
||||
*/
|
||||
uint32_t getNumMipLevels() const { return mNumMipLevels; }
|
||||
|
||||
/**
|
||||
* Gets the number of array elements (this is never zero).
|
||||
*/
|
||||
uint32_t getArrayLength() const { return mArrayLength; }
|
||||
|
||||
/**
|
||||
* Returns whether or not this is a cubemap.
|
||||
*/
|
||||
bool isCubemap() const { return mNumCubeFaces > 1; }
|
||||
|
||||
/**
|
||||
* Retrieves a weak reference to a given data blob. Returns false if the given blob index is out
|
||||
* of bounds, or if the blob at the given index is empty.
|
||||
*/
|
||||
bool getBlob(KtxBlobIndex index, uint8_t** data, uint32_t* size) const;
|
||||
|
||||
/**
|
||||
* Copies the given data into the blob at the given index, replacing whatever is already there.
|
||||
* Returns false if the given blob index is out of bounds.
|
||||
*/
|
||||
bool setBlob(KtxBlobIndex index, uint8_t const* data, uint32_t size);
|
||||
|
||||
/**
|
||||
* Allocates the blob at the given index to the given number of bytes. This allows subsequent
|
||||
* calls to setBlob to be thread-safe.
|
||||
*/
|
||||
bool allocateBlob(KtxBlobIndex index, uint32_t size);
|
||||
|
||||
// The following constants help clients populate the "info" struct. Most of them have corollary
|
||||
// constants in the OpenGL headers.
|
||||
|
||||
static constexpr uint32_t R8 = 0x8229;
|
||||
static constexpr uint32_t R8_SNORM = 0x8F94;
|
||||
static constexpr uint32_t R8UI = 0x8232;
|
||||
static constexpr uint32_t R8I = 0x8231;
|
||||
static constexpr uint32_t STENCIL_INDEX8 = 0x8D48;
|
||||
static constexpr uint32_t R16F = 0x822D;
|
||||
static constexpr uint32_t R16UI = 0x8234;
|
||||
static constexpr uint32_t R16I = 0x8233;
|
||||
static constexpr uint32_t RG8 = 0x822B;
|
||||
static constexpr uint32_t RG8_SNORM = 0x8F95;
|
||||
static constexpr uint32_t RG8UI = 0x8238;
|
||||
static constexpr uint32_t RG8I = 0x8237;
|
||||
static constexpr uint32_t RGB565 = 0x8D62;
|
||||
static constexpr uint32_t RGB5_A1 = 0x8057;
|
||||
static constexpr uint32_t RGBA4 = 0x8056;
|
||||
static constexpr uint32_t DEPTH_COMPONENT16 = 0x81A5;
|
||||
static constexpr uint32_t RGB8 = 0x8051;
|
||||
static constexpr uint32_t SRGB8 = 0x8C41;
|
||||
static constexpr uint32_t RGB8_SNORM = 0x8F96;
|
||||
static constexpr uint32_t RGB8UI = 0x8D7D;
|
||||
static constexpr uint32_t RGB8I = 0x8D8F;
|
||||
static constexpr uint32_t DEPTH_COMPONENT24 = 0x81A6;
|
||||
static constexpr uint32_t R32F = 0x822E;
|
||||
static constexpr uint32_t R32UI = 0x8236;
|
||||
static constexpr uint32_t R32I = 0x8235;
|
||||
static constexpr uint32_t RG16F = 0x822F;
|
||||
static constexpr uint32_t RG16UI = 0x823A;
|
||||
static constexpr uint32_t RG16I = 0x8239;
|
||||
static constexpr uint32_t R11F_G11F_B10F = 0x8C3A;
|
||||
static constexpr uint32_t RGB9_E5 = 0x8C3D;
|
||||
static constexpr uint32_t RGBA8 = 0x8058;
|
||||
static constexpr uint32_t SRGB8_ALPHA8 = 0x8C43;
|
||||
static constexpr uint32_t RGBA8_SNORM = 0x8F97;
|
||||
static constexpr uint32_t RGB10_A2 = 0x8059;
|
||||
static constexpr uint32_t RGBA8UI = 0x8D7C;
|
||||
static constexpr uint32_t RGBA8I = 0x8D8E;
|
||||
static constexpr uint32_t DEPTH_COMPONENT32F = 0x8CAC;
|
||||
static constexpr uint32_t DEPTH24_STENCIL8 = 0x88F0;
|
||||
static constexpr uint32_t DEPTH32F_STENCIL8 = 0x8CAD;
|
||||
static constexpr uint32_t RGB16F = 0x881B;
|
||||
static constexpr uint32_t RGB16UI = 0x8D77;
|
||||
static constexpr uint32_t RGB16I = 0x8D89;
|
||||
static constexpr uint32_t RG32F = 0x8230;
|
||||
static constexpr uint32_t RG32UI = 0x823C;
|
||||
static constexpr uint32_t RG32I = 0x823B;
|
||||
static constexpr uint32_t RGBA16F = 0x881A;
|
||||
static constexpr uint32_t RGBA16UI = 0x8D76;
|
||||
static constexpr uint32_t RGBA16I = 0x8D88;
|
||||
static constexpr uint32_t RGB32F = 0x8815;
|
||||
static constexpr uint32_t RGB32UI = 0x8D71;
|
||||
static constexpr uint32_t RGB32I = 0x8D83;
|
||||
static constexpr uint32_t RGBA32F = 0x8814;
|
||||
static constexpr uint32_t RGBA32UI = 0x8D70;
|
||||
static constexpr uint32_t RGBA32I = 0x8D82;
|
||||
|
||||
static constexpr uint32_t RED = 0x1903;
|
||||
static constexpr uint32_t RG = 0x8227;
|
||||
static constexpr uint32_t RGB = 0x1907;
|
||||
static constexpr uint32_t RGBA = 0x1908;
|
||||
static constexpr uint32_t BGR = 0x80E0;
|
||||
static constexpr uint32_t BGRA = 0x80E1;
|
||||
static constexpr uint32_t LUMINANCE = 0x1909;
|
||||
static constexpr uint32_t LUMINANCE_ALPHA = 0x190A;
|
||||
|
||||
static constexpr uint32_t UNSIGNED_BYTE = 0x1401;
|
||||
static constexpr uint32_t UNSIGNED_SHORT = 0x1403;
|
||||
static constexpr uint32_t HALF_FLOAT = 0x140B;
|
||||
static constexpr uint32_t FLOAT = 0x1406;
|
||||
|
||||
static constexpr uint32_t ENDIAN_DEFAULT = 0x04030201;
|
||||
|
||||
static constexpr uint32_t RGB_S3TC_DXT1 = 0x83F0;
|
||||
static constexpr uint32_t RGBA_S3TC_DXT1 = 0x83F1;
|
||||
static constexpr uint32_t RGBA_S3TC_DXT3 = 0x83F2;
|
||||
static constexpr uint32_t RGBA_S3TC_DXT5 = 0x83F3;
|
||||
|
||||
static constexpr uint32_t RGBA_ASTC_4x4 = 0x93B0;
|
||||
static constexpr uint32_t RGBA_ASTC_5x4 = 0x93B1;
|
||||
static constexpr uint32_t RGBA_ASTC_5x5 = 0x93B2;
|
||||
static constexpr uint32_t RGBA_ASTC_6x5 = 0x93B3;
|
||||
static constexpr uint32_t RGBA_ASTC_6x6 = 0x93B4;
|
||||
static constexpr uint32_t RGBA_ASTC_8x5 = 0x93B5;
|
||||
static constexpr uint32_t RGBA_ASTC_8x6 = 0x93B6;
|
||||
static constexpr uint32_t RGBA_ASTC_8x8 = 0x93B7;
|
||||
static constexpr uint32_t RGBA_ASTC_10x5 = 0x93B8;
|
||||
static constexpr uint32_t RGBA_ASTC_10x6 = 0x93B9;
|
||||
static constexpr uint32_t RGBA_ASTC_10x8 = 0x93BA;
|
||||
static constexpr uint32_t RGBA_ASTC_10x10 = 0x93BB;
|
||||
static constexpr uint32_t RGBA_ASTC_12x10 = 0x93BC;
|
||||
static constexpr uint32_t RGBA_ASTC_12x12 = 0x93BD;
|
||||
static constexpr uint32_t SRGB8_ALPHA8_ASTC_4x4 = 0x93D0;
|
||||
static constexpr uint32_t SRGB8_ALPHA8_ASTC_5x4 = 0x93D1;
|
||||
static constexpr uint32_t SRGB8_ALPHA8_ASTC_5x5 = 0x93D2;
|
||||
static constexpr uint32_t SRGB8_ALPHA8_ASTC_6x5 = 0x93D3;
|
||||
static constexpr uint32_t SRGB8_ALPHA8_ASTC_6x6 = 0x93D4;
|
||||
static constexpr uint32_t SRGB8_ALPHA8_ASTC_8x5 = 0x93D5;
|
||||
static constexpr uint32_t SRGB8_ALPHA8_ASTC_8x6 = 0x93D6;
|
||||
static constexpr uint32_t SRGB8_ALPHA8_ASTC_8x8 = 0x93D7;
|
||||
static constexpr uint32_t SRGB8_ALPHA8_ASTC_10x5 = 0x93D8;
|
||||
static constexpr uint32_t SRGB8_ALPHA8_ASTC_10x6 = 0x93D9;
|
||||
static constexpr uint32_t SRGB8_ALPHA8_ASTC_10x8 = 0x93DA;
|
||||
static constexpr uint32_t SRGB8_ALPHA8_ASTC_10x10 = 0x93DB;
|
||||
static constexpr uint32_t SRGB8_ALPHA8_ASTC_12x10 = 0x93DC;
|
||||
static constexpr uint32_t SRGB8_ALPHA8_ASTC_12x12 = 0x93DD;
|
||||
|
||||
static constexpr uint32_t R11_EAC = 0x9270;
|
||||
static constexpr uint32_t SIGNED_R11_EAC = 0x9271;
|
||||
static constexpr uint32_t RG11_EAC = 0x9272;
|
||||
static constexpr uint32_t SIGNED_RG11_EAC = 0x9273;
|
||||
static constexpr uint32_t RGB8_ETC2 = 0x9274;
|
||||
static constexpr uint32_t SRGB8_ETC2 = 0x9275;
|
||||
static constexpr uint32_t RGB8_ALPHA1_ETC2 = 0x9276;
|
||||
static constexpr uint32_t SRGB8_ALPHA1_ETC = 0x9277;
|
||||
static constexpr uint32_t RGBA8_ETC2_EAC = 0x9278;
|
||||
static constexpr uint32_t SRGB8_ALPHA8_ETC2_EAC = 0x9279;
|
||||
|
||||
private:
|
||||
image::KtxInfo mInfo = {};
|
||||
uint32_t mNumMipLevels;
|
||||
uint32_t mArrayLength;
|
||||
uint32_t mNumCubeFaces;
|
||||
std::unique_ptr<KtxBlobList> mBlobs;
|
||||
std::unique_ptr<KtxMetadata> mMetadata;
|
||||
};
|
||||
|
||||
} // namespace image
|
||||
|
||||
#endif /* IMAGE_KTXBUNDLE_H */
|
||||
367
ios/include/image/KtxUtility.h
Normal file
367
ios/include/image/KtxUtility.h
Normal file
@@ -0,0 +1,367 @@
|
||||
/*
|
||||
* 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 IMAGE_KTXUTILITY_H
|
||||
#define IMAGE_KTXUTILITY_H
|
||||
|
||||
#include <filament/Engine.h>
|
||||
#include <filament/Texture.h>
|
||||
|
||||
#include <image/KtxBundle.h>
|
||||
|
||||
namespace image {
|
||||
|
||||
/**
|
||||
* Allows clients to create Filament textures from KtxBundle objects.
|
||||
*
|
||||
* Note that libimage does not have a dependency on libfilament, so for simplicity this is a
|
||||
* header-only library with inlined functions.
|
||||
*/
|
||||
namespace ktx {
|
||||
|
||||
using Texture = filament::Texture;
|
||||
using Engine = filament::Engine;
|
||||
|
||||
using TextureFormat = Texture::InternalFormat;
|
||||
using CompressedPixelDataType = Texture::CompressedType;
|
||||
using PixelDataType = Texture::Type;
|
||||
using PixelDataFormat = Texture::Format;
|
||||
using PixelBufferDescriptor = Texture::PixelBufferDescriptor;
|
||||
|
||||
using Callback = void(*)(void* userdata);
|
||||
|
||||
CompressedPixelDataType toCompressedPixelDataType(const KtxInfo& info);
|
||||
PixelDataType toPixelDataType(const KtxInfo& info);
|
||||
PixelDataFormat toPixelDataFormat(const KtxInfo& info);
|
||||
bool isCompressed(const KtxInfo& info);
|
||||
TextureFormat toTextureFormat(const KtxInfo& info);
|
||||
TextureFormat toSrgbTextureFormat(TextureFormat tex);
|
||||
|
||||
/**
|
||||
* Creates a Texture object from a KTX file and populates all of its faces and miplevels.
|
||||
*
|
||||
* @param engine Used to create the Filament Texture
|
||||
* @param ktx In-memory representation of a KTX file
|
||||
* @param srgb Forces the KTX-specified format into an SRGB format if possible
|
||||
* @param callback Gets called after all texture data has been uploaded to the GPU
|
||||
* @param userdata Passed into the callback
|
||||
*/
|
||||
inline Texture* createTexture(Engine* engine, const KtxBundle& ktx, bool srgb,
|
||||
Callback callback, void* userdata) {
|
||||
using Sampler = Texture::Sampler;
|
||||
const auto& ktxinfo = ktx.getInfo();
|
||||
const uint32_t nmips = ktx.getNumMipLevels();
|
||||
const auto cdatatype = toCompressedPixelDataType(ktxinfo);
|
||||
const auto datatype = toPixelDataType(ktxinfo);
|
||||
const auto dataformat = toPixelDataFormat(ktxinfo);
|
||||
|
||||
auto texformat = toTextureFormat(ktxinfo);
|
||||
if (srgb) {
|
||||
texformat = toSrgbTextureFormat(texformat);
|
||||
}
|
||||
|
||||
Texture* texture = Texture::Builder()
|
||||
.width(ktxinfo.pixelWidth)
|
||||
.height(ktxinfo.pixelHeight)
|
||||
.levels(static_cast<uint8_t>(nmips))
|
||||
.sampler(ktx.isCubemap() ? Sampler::SAMPLER_CUBEMAP : Sampler::SAMPLER_2D)
|
||||
.format(texformat)
|
||||
.build(*engine);
|
||||
|
||||
struct Userdata {
|
||||
uint32_t remainingBuffers;
|
||||
Callback callback;
|
||||
void* userdata;
|
||||
};
|
||||
|
||||
Userdata* cbuser = new Userdata({nmips, callback, userdata});
|
||||
|
||||
PixelBufferDescriptor::Callback cb = [](void*, size_t, void* cbuserptr) {
|
||||
Userdata* cbuser = (Userdata*) cbuserptr;
|
||||
if (--cbuser->remainingBuffers == 0) {
|
||||
if (cbuser->callback) {
|
||||
cbuser->callback(cbuser->userdata);
|
||||
}
|
||||
delete cbuser;
|
||||
}
|
||||
};
|
||||
|
||||
uint8_t* data;
|
||||
uint32_t size;
|
||||
|
||||
if (isCompressed(ktxinfo)) {
|
||||
if (ktx.isCubemap()) {
|
||||
for (uint32_t level = 0; level < nmips; ++level) {
|
||||
ktx.getBlob({level, 0, 0}, &data, &size);
|
||||
PixelBufferDescriptor pbd(data, size * 6, cdatatype, size, cb, cbuser);
|
||||
texture->setImage(*engine, level, std::move(pbd), Texture::FaceOffsets(size));
|
||||
}
|
||||
return texture;
|
||||
}
|
||||
for (uint32_t level = 0; level < nmips; ++level) {
|
||||
ktx.getBlob({level, 0, 0}, &data, &size);
|
||||
PixelBufferDescriptor pbd(data, size, cdatatype, size, cb, cbuser);
|
||||
texture->setImage(*engine, level, std::move(pbd));
|
||||
}
|
||||
return texture;
|
||||
}
|
||||
|
||||
if (ktx.isCubemap()) {
|
||||
for (uint32_t level = 0; level < nmips; ++level) {
|
||||
ktx.getBlob({level, 0, 0}, &data, &size);
|
||||
PixelBufferDescriptor pbd(data, size * 6, dataformat, datatype, cb, cbuser);
|
||||
texture->setImage(*engine, level, std::move(pbd), Texture::FaceOffsets(size));
|
||||
}
|
||||
return texture;
|
||||
}
|
||||
|
||||
for (uint32_t level = 0; level < nmips; ++level) {
|
||||
ktx.getBlob({level, 0, 0}, &data, &size);
|
||||
PixelBufferDescriptor pbd(data, size, dataformat, datatype, cb, cbuser);
|
||||
texture->setImage(*engine, level, std::move(pbd));
|
||||
}
|
||||
return texture;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Texture object from a KTX bundle, populates all of its faces and miplevels,
|
||||
* and automatically destroys the bundle after all the texture data has been uploaded.
|
||||
*
|
||||
* @param engine Used to create the Filament Texture
|
||||
* @param ktx In-memory representation of a KTX file
|
||||
* @param srgb Forces the KTX-specified format into an SRGB format if possible
|
||||
*/
|
||||
inline Texture* createTexture(Engine* engine, KtxBundle* ktx, bool srgb) {
|
||||
auto freeKtx = [] (void* userdata) {
|
||||
KtxBundle* ktx = (KtxBundle*) userdata;
|
||||
delete ktx;
|
||||
};
|
||||
return createTexture(engine, *ktx, srgb, freeKtx, ktx);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T toCompressedFilamentEnum(uint32_t format) {
|
||||
switch (format) {
|
||||
case KtxBundle::RGB_S3TC_DXT1: return T::DXT1_RGB;
|
||||
case KtxBundle::RGBA_S3TC_DXT1: return T::DXT1_RGBA;
|
||||
case KtxBundle::RGBA_S3TC_DXT3: return T::DXT3_RGBA;
|
||||
case KtxBundle::RGBA_S3TC_DXT5: return T::DXT5_RGBA;
|
||||
case KtxBundle::RGBA_ASTC_4x4: return T::RGBA_ASTC_4x4;
|
||||
case KtxBundle::RGBA_ASTC_5x4: return T::RGBA_ASTC_5x4;
|
||||
case KtxBundle::RGBA_ASTC_5x5: return T::RGBA_ASTC_5x5;
|
||||
case KtxBundle::RGBA_ASTC_6x5: return T::RGBA_ASTC_6x5;
|
||||
case KtxBundle::RGBA_ASTC_6x6: return T::RGBA_ASTC_6x6;
|
||||
case KtxBundle::RGBA_ASTC_8x5: return T::RGBA_ASTC_8x5;
|
||||
case KtxBundle::RGBA_ASTC_8x6: return T::RGBA_ASTC_8x6;
|
||||
case KtxBundle::RGBA_ASTC_8x8: return T::RGBA_ASTC_8x8;
|
||||
case KtxBundle::RGBA_ASTC_10x5: return T::RGBA_ASTC_10x5;
|
||||
case KtxBundle::RGBA_ASTC_10x6: return T::RGBA_ASTC_10x6;
|
||||
case KtxBundle::RGBA_ASTC_10x8: return T::RGBA_ASTC_10x8;
|
||||
case KtxBundle::RGBA_ASTC_10x10: return T::RGBA_ASTC_10x10;
|
||||
case KtxBundle::RGBA_ASTC_12x10: return T::RGBA_ASTC_12x10;
|
||||
case KtxBundle::RGBA_ASTC_12x12: return T::RGBA_ASTC_12x12;
|
||||
case KtxBundle::SRGB8_ALPHA8_ASTC_4x4: return T::SRGB8_ALPHA8_ASTC_4x4;
|
||||
case KtxBundle::SRGB8_ALPHA8_ASTC_5x4: return T::SRGB8_ALPHA8_ASTC_5x4;
|
||||
case KtxBundle::SRGB8_ALPHA8_ASTC_5x5: return T::SRGB8_ALPHA8_ASTC_5x5;
|
||||
case KtxBundle::SRGB8_ALPHA8_ASTC_6x5: return T::SRGB8_ALPHA8_ASTC_6x5;
|
||||
case KtxBundle::SRGB8_ALPHA8_ASTC_6x6: return T::SRGB8_ALPHA8_ASTC_6x6;
|
||||
case KtxBundle::SRGB8_ALPHA8_ASTC_8x5: return T::SRGB8_ALPHA8_ASTC_8x5;
|
||||
case KtxBundle::SRGB8_ALPHA8_ASTC_8x6: return T::SRGB8_ALPHA8_ASTC_8x6;
|
||||
case KtxBundle::SRGB8_ALPHA8_ASTC_8x8: return T::SRGB8_ALPHA8_ASTC_8x8;
|
||||
case KtxBundle::SRGB8_ALPHA8_ASTC_10x5: return T::SRGB8_ALPHA8_ASTC_10x5;
|
||||
case KtxBundle::SRGB8_ALPHA8_ASTC_10x6: return T::SRGB8_ALPHA8_ASTC_10x6;
|
||||
case KtxBundle::SRGB8_ALPHA8_ASTC_10x8: return T::SRGB8_ALPHA8_ASTC_10x8;
|
||||
case KtxBundle::SRGB8_ALPHA8_ASTC_10x10: return T::SRGB8_ALPHA8_ASTC_10x10;
|
||||
case KtxBundle::SRGB8_ALPHA8_ASTC_12x10: return T::SRGB8_ALPHA8_ASTC_12x10;
|
||||
case KtxBundle::SRGB8_ALPHA8_ASTC_12x12: return T::SRGB8_ALPHA8_ASTC_12x12;
|
||||
case KtxBundle::R11_EAC: return T::EAC_R11;
|
||||
case KtxBundle::SIGNED_R11_EAC: return T::EAC_R11_SIGNED;
|
||||
case KtxBundle::RG11_EAC: return T::EAC_RG11;
|
||||
case KtxBundle::SIGNED_RG11_EAC: return T::EAC_RG11_SIGNED;
|
||||
case KtxBundle::RGB8_ETC2: return T::ETC2_RGB8;
|
||||
case KtxBundle::SRGB8_ETC2: return T::ETC2_SRGB8;
|
||||
case KtxBundle::RGB8_ALPHA1_ETC2: return T::ETC2_RGB8_A1;
|
||||
case KtxBundle::SRGB8_ALPHA1_ETC: return T::ETC2_SRGB8_A1;
|
||||
case KtxBundle::RGBA8_ETC2_EAC: return T::ETC2_EAC_RGBA8;
|
||||
case KtxBundle::SRGB8_ALPHA8_ETC2_EAC: return T::ETC2_EAC_SRGBA8;
|
||||
}
|
||||
return (T) 0xffff;
|
||||
}
|
||||
|
||||
inline CompressedPixelDataType toCompressedPixelDataType(const KtxInfo& info) {
|
||||
return toCompressedFilamentEnum<CompressedPixelDataType>(info.glInternalFormat);
|
||||
}
|
||||
|
||||
inline PixelDataType toPixelDataType(const KtxInfo& info) {
|
||||
switch (info.glType) {
|
||||
case KtxBundle::UNSIGNED_BYTE: return PixelDataType::UBYTE;
|
||||
case KtxBundle::UNSIGNED_SHORT: return PixelDataType::USHORT;
|
||||
case KtxBundle::HALF_FLOAT: return PixelDataType::HALF;
|
||||
case KtxBundle::FLOAT: return PixelDataType::FLOAT;
|
||||
case KtxBundle::R11F_G11F_B10F: return PixelDataType::UINT_10F_11F_11F_REV;
|
||||
}
|
||||
return (PixelDataType) 0xff;
|
||||
}
|
||||
|
||||
inline PixelDataFormat toPixelDataFormat(const KtxInfo& info) {
|
||||
switch (info.glFormat) {
|
||||
case KtxBundle::LUMINANCE:
|
||||
case KtxBundle::RED: return PixelDataFormat::R;
|
||||
case KtxBundle::RG: return PixelDataFormat::RG;
|
||||
case KtxBundle::RGB: return PixelDataFormat::RGB;
|
||||
case KtxBundle::RGBA: return PixelDataFormat::RGBA;
|
||||
// glFormat should NOT be a sized format according to the spec
|
||||
// however cmgen was generating incorrect files until after Filament 1.8.0
|
||||
// so we keep this line here to preserve compatibility with older assets
|
||||
case KtxBundle::R11F_G11F_B10F: return PixelDataFormat::RGB;
|
||||
}
|
||||
return (PixelDataFormat) 0xff;
|
||||
}
|
||||
|
||||
inline bool isCompressed(const KtxInfo& info) {
|
||||
return info.glFormat == 0;
|
||||
}
|
||||
|
||||
inline TextureFormat toSrgbTextureFormat(TextureFormat format) {
|
||||
switch(format) {
|
||||
// Non-compressed
|
||||
case Texture::InternalFormat::RGB8:
|
||||
return Texture::InternalFormat::SRGB8;
|
||||
case Texture::InternalFormat::RGBA8:
|
||||
return Texture::InternalFormat::SRGB8_A8;
|
||||
|
||||
// ASTC
|
||||
case Texture::InternalFormat::RGBA_ASTC_4x4:
|
||||
return Texture::InternalFormat::SRGB8_ALPHA8_ASTC_4x4;
|
||||
case Texture::InternalFormat::RGBA_ASTC_5x4:
|
||||
return Texture::InternalFormat::SRGB8_ALPHA8_ASTC_5x4;
|
||||
case Texture::InternalFormat::RGBA_ASTC_5x5:
|
||||
return Texture::InternalFormat::SRGB8_ALPHA8_ASTC_5x5;
|
||||
case Texture::InternalFormat::RGBA_ASTC_6x5:
|
||||
return Texture::InternalFormat::SRGB8_ALPHA8_ASTC_6x5;
|
||||
case Texture::InternalFormat::RGBA_ASTC_6x6:
|
||||
return Texture::InternalFormat::SRGB8_ALPHA8_ASTC_6x6;
|
||||
case Texture::InternalFormat::RGBA_ASTC_8x5:
|
||||
return Texture::InternalFormat::SRGB8_ALPHA8_ASTC_8x5;
|
||||
case Texture::InternalFormat::RGBA_ASTC_8x6:
|
||||
return Texture::InternalFormat::SRGB8_ALPHA8_ASTC_8x6;
|
||||
case Texture::InternalFormat::RGBA_ASTC_8x8:
|
||||
return Texture::InternalFormat::SRGB8_ALPHA8_ASTC_8x8;
|
||||
case Texture::InternalFormat::RGBA_ASTC_10x5:
|
||||
return Texture::InternalFormat::SRGB8_ALPHA8_ASTC_10x5;
|
||||
case Texture::InternalFormat::RGBA_ASTC_10x6:
|
||||
return Texture::InternalFormat::SRGB8_ALPHA8_ASTC_10x6;
|
||||
case Texture::InternalFormat::RGBA_ASTC_10x8:
|
||||
return Texture::InternalFormat::SRGB8_ALPHA8_ASTC_10x8;
|
||||
case Texture::InternalFormat::RGBA_ASTC_10x10:
|
||||
return Texture::InternalFormat::SRGB8_ALPHA8_ASTC_10x10;
|
||||
case Texture::InternalFormat::RGBA_ASTC_12x10:
|
||||
return Texture::InternalFormat::SRGB8_ALPHA8_ASTC_12x10;
|
||||
case Texture::InternalFormat::RGBA_ASTC_12x12:
|
||||
return Texture::InternalFormat::SRGB8_ALPHA8_ASTC_12x12;
|
||||
|
||||
// ETC2
|
||||
case Texture::InternalFormat::ETC2_RGB8:
|
||||
return Texture::InternalFormat::ETC2_SRGB8;
|
||||
case Texture::InternalFormat::ETC2_RGB8_A1:
|
||||
return Texture::InternalFormat::ETC2_SRGB8_A1;
|
||||
case Texture::InternalFormat::ETC2_EAC_RGBA8:
|
||||
return Texture::InternalFormat::ETC2_EAC_SRGBA8;
|
||||
|
||||
// DXT
|
||||
case Texture::InternalFormat::DXT1_RGB:
|
||||
return Texture::InternalFormat::DXT1_SRGB;
|
||||
case Texture::InternalFormat::DXT1_RGBA:
|
||||
return Texture::InternalFormat::DXT1_SRGBA;
|
||||
case Texture::InternalFormat::DXT3_RGBA:
|
||||
return Texture::InternalFormat::DXT3_SRGBA;
|
||||
case Texture::InternalFormat::DXT5_RGBA:
|
||||
return Texture::InternalFormat::DXT5_SRGBA;
|
||||
|
||||
default:
|
||||
return format;
|
||||
}
|
||||
}
|
||||
|
||||
inline TextureFormat toTextureFormat(const KtxInfo& info) {
|
||||
switch (info.glInternalFormat) {
|
||||
case KtxBundle::RED: return TextureFormat::R8;
|
||||
case KtxBundle::RG: return TextureFormat::RG8;
|
||||
case KtxBundle::RGB: return TextureFormat::RGB8;
|
||||
case KtxBundle::RGBA: return TextureFormat::RGBA8;
|
||||
case KtxBundle::LUMINANCE: return TextureFormat::R8;
|
||||
case KtxBundle::LUMINANCE_ALPHA: return TextureFormat::RG8;
|
||||
case KtxBundle::R8: return TextureFormat::R8;
|
||||
case KtxBundle::R8_SNORM: return TextureFormat::R8_SNORM;
|
||||
case KtxBundle::R8UI: return TextureFormat::R8UI;
|
||||
case KtxBundle::R8I: return TextureFormat::R8I;
|
||||
case KtxBundle::STENCIL_INDEX8: return TextureFormat::STENCIL8;
|
||||
case KtxBundle::R16F: return TextureFormat::R16F;
|
||||
case KtxBundle::R16UI: return TextureFormat::R16UI;
|
||||
case KtxBundle::R16I: return TextureFormat::R16I;
|
||||
case KtxBundle::RG8: return TextureFormat::RG8;
|
||||
case KtxBundle::RG8_SNORM: return TextureFormat::RG8_SNORM;
|
||||
case KtxBundle::RG8UI: return TextureFormat::RG8UI;
|
||||
case KtxBundle::RG8I: return TextureFormat::RG8I;
|
||||
case KtxBundle::RGB565: return TextureFormat::RGB565;
|
||||
case KtxBundle::RGB9_E5: return TextureFormat::RGB9_E5;
|
||||
case KtxBundle::RGB5_A1: return TextureFormat::RGB5_A1;
|
||||
case KtxBundle::RGBA4: return TextureFormat::RGBA4;
|
||||
case KtxBundle::DEPTH_COMPONENT16: return TextureFormat::DEPTH16;
|
||||
case KtxBundle::RGB8: return TextureFormat::RGB8;
|
||||
case KtxBundle::SRGB8: return TextureFormat::SRGB8;
|
||||
case KtxBundle::RGB8_SNORM: return TextureFormat::RGB8_SNORM;
|
||||
case KtxBundle::RGB8UI: return TextureFormat::RGB8UI;
|
||||
case KtxBundle::RGB8I: return TextureFormat::RGB8I;
|
||||
case KtxBundle::R32F: return TextureFormat::R32F;
|
||||
case KtxBundle::R32UI: return TextureFormat::R32UI;
|
||||
case KtxBundle::R32I: return TextureFormat::R32I;
|
||||
case KtxBundle::RG16F: return TextureFormat::RG16F;
|
||||
case KtxBundle::RG16UI: return TextureFormat::RG16UI;
|
||||
case KtxBundle::RG16I: return TextureFormat::RG16I;
|
||||
case KtxBundle::R11F_G11F_B10F: return TextureFormat::R11F_G11F_B10F;
|
||||
case KtxBundle::RGBA8: return TextureFormat::RGBA8;
|
||||
case KtxBundle::SRGB8_ALPHA8: return TextureFormat::SRGB8_A8;
|
||||
case KtxBundle::RGBA8_SNORM: return TextureFormat::RGBA8_SNORM;
|
||||
case KtxBundle::RGB10_A2: return TextureFormat::RGB10_A2;
|
||||
case KtxBundle::RGBA8UI: return TextureFormat::RGBA8UI;
|
||||
case KtxBundle::RGBA8I: return TextureFormat::RGBA8I;
|
||||
case KtxBundle::DEPTH24_STENCIL8: return TextureFormat::DEPTH24_STENCIL8;
|
||||
case KtxBundle::DEPTH32F_STENCIL8: return TextureFormat::DEPTH32F_STENCIL8;
|
||||
case KtxBundle::RGB16F: return TextureFormat::RGB16F;
|
||||
case KtxBundle::RGB16UI: return TextureFormat::RGB16UI;
|
||||
case KtxBundle::RGB16I: return TextureFormat::RGB16I;
|
||||
case KtxBundle::RG32F: return TextureFormat::RG32F;
|
||||
case KtxBundle::RG32UI: return TextureFormat::RG32UI;
|
||||
case KtxBundle::RG32I: return TextureFormat::RG32I;
|
||||
case KtxBundle::RGBA16F: return TextureFormat::RGBA16F;
|
||||
case KtxBundle::RGBA16UI: return TextureFormat::RGBA16UI;
|
||||
case KtxBundle::RGBA16I: return TextureFormat::RGBA16I;
|
||||
case KtxBundle::RGB32F: return TextureFormat::RGB32F;
|
||||
case KtxBundle::RGB32UI: return TextureFormat::RGB32UI;
|
||||
case KtxBundle::RGB32I: return TextureFormat::RGB32I;
|
||||
case KtxBundle::RGBA32F: return TextureFormat::RGBA32F;
|
||||
case KtxBundle::RGBA32UI: return TextureFormat::RGBA32UI;
|
||||
case KtxBundle::RGBA32I: return TextureFormat::RGBA32I;
|
||||
}
|
||||
return toCompressedFilamentEnum<TextureFormat>(info.glInternalFormat);
|
||||
}
|
||||
|
||||
} // namespace ktx
|
||||
|
||||
} // namespace image
|
||||
|
||||
#endif
|
||||
121
ios/include/image/LinearImage.h
Normal file
121
ios/include/image/LinearImage.h
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* 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 IMAGE_LINEARIMAGE_H
|
||||
#define IMAGE_LINEARIMAGE_H
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
/**
|
||||
* Types and free functions for the Filament core imaging library, primarily used for offline tools,
|
||||
* but with minimal dependencies to support potential use by the renderer.
|
||||
*/
|
||||
namespace image {
|
||||
|
||||
/**
|
||||
* LinearImage is a handle to packed floating point data arranged into a row-major grid.
|
||||
*
|
||||
* We use this object as input/output for core algorithms that wish to be agnostic of source and
|
||||
* destination formats. The number of channels is arbitrary (1 or more) but we often use 3-channel
|
||||
* images to represent color data.
|
||||
*
|
||||
* The underlying pixel data has shared ownership semantics to allow clients to easily pass around
|
||||
* the image object without incurring a deep copy. Shared access to pixels is not thread safe.
|
||||
*
|
||||
* By convention, we do not use channel major order (i.e. planar). However we provide a free
|
||||
* function in ImageOps to combine planar data. Pixels are stored such that the row stride is simply
|
||||
* width * channels * sizeof(float).
|
||||
*/
|
||||
class UTILS_PUBLIC LinearImage {
|
||||
public:
|
||||
|
||||
~LinearImage();
|
||||
|
||||
/**
|
||||
* Allocates a zeroed-out image.
|
||||
*/
|
||||
LinearImage(uint32_t width, uint32_t height, uint32_t channels);
|
||||
|
||||
/**
|
||||
* Makes a shallow copy with shared pixel data.
|
||||
*/
|
||||
LinearImage(const LinearImage& that);
|
||||
LinearImage& operator=(const LinearImage& that);
|
||||
|
||||
/**
|
||||
* Creates an empty (invalid) image.
|
||||
*/
|
||||
LinearImage() : mDataRef(nullptr), mData(nullptr), mWidth(0), mHeight(0), mChannels(0) {}
|
||||
operator bool() const { return mData != nullptr; }
|
||||
|
||||
/**
|
||||
* Gets a pointer to the underlying pixel data.
|
||||
*/
|
||||
float* getPixelRef() { return mData; }
|
||||
template<typename T> T* get() { return reinterpret_cast<T*>(mData); }
|
||||
|
||||
/**
|
||||
* Gets a pointer to immutable pixel data.
|
||||
*/
|
||||
float const* getPixelRef() const { return mData; }
|
||||
template<typename T> T const* get() const { return reinterpret_cast<T const*>(mData); }
|
||||
|
||||
/**
|
||||
* Gets a pointer to the pixel data at the given column and row. (not bounds checked)
|
||||
*/
|
||||
float* getPixelRef(uint32_t column, uint32_t row) {
|
||||
return mData + (column + row * mWidth) * mChannels;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T* get(uint32_t column, uint32_t row) {
|
||||
return reinterpret_cast<T*>(getPixelRef(column, row));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a pointer to the immutable pixel data at the given column and row. (not bounds checked)
|
||||
*/
|
||||
float const* getPixelRef(uint32_t column, uint32_t row) const {
|
||||
return mData + (column + row * mWidth) * mChannels;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T const* get(uint32_t column, uint32_t row) const {
|
||||
return reinterpret_cast<T const*>(getPixelRef(column, row));
|
||||
}
|
||||
|
||||
uint32_t getWidth() const { return mWidth; }
|
||||
uint32_t getHeight() const { return mHeight; }
|
||||
uint32_t getChannels() const { return mChannels; }
|
||||
void reset() { *this = LinearImage(); }
|
||||
bool isValid() const { return mData; }
|
||||
|
||||
private:
|
||||
|
||||
struct SharedReference;
|
||||
SharedReference* mDataRef = nullptr;
|
||||
|
||||
float* mData;
|
||||
uint32_t mWidth;
|
||||
uint32_t mHeight;
|
||||
uint32_t mChannels;
|
||||
};
|
||||
|
||||
} // namespace image
|
||||
|
||||
#endif /* IMAGE_LINEARIMAGE_H */
|
||||
807
ios/include/math/TMatHelpers.h
Normal file
807
ios/include/math/TMatHelpers.h
Normal file
@@ -0,0 +1,807 @@
|
||||
/*
|
||||
* Copyright 2013 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 MATH_TMATHELPERS_H_
|
||||
#define MATH_TMATHELPERS_H_
|
||||
|
||||
#include <math/compiler.h>
|
||||
#include <math/quat.h>
|
||||
#include <math/TVecHelpers.h>
|
||||
|
||||
#include <algorithm> // for std::swap
|
||||
#include <cmath> // for std:: namespace
|
||||
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
namespace filament {
|
||||
namespace math {
|
||||
namespace details {
|
||||
// -------------------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* No user serviceable parts here.
|
||||
*
|
||||
* Don't use this file directly, instead include math/mat*.h
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Matrix utilities
|
||||
*/
|
||||
|
||||
namespace matrix {
|
||||
|
||||
/*
|
||||
* Matrix inversion
|
||||
*/
|
||||
template<typename MATRIX>
|
||||
constexpr MATRIX MATH_PURE gaussJordanInverse(MATRIX src) {
|
||||
typedef typename MATRIX::value_type T;
|
||||
constexpr unsigned int N = MATRIX::NUM_ROWS;
|
||||
MATRIX inverted;
|
||||
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
// look for largest element in i'th column
|
||||
size_t swap = i;
|
||||
T t = src[i][i] < 0 ? -src[i][i] : src[i][i];
|
||||
for (size_t j = i + 1; j < N; ++j) {
|
||||
const T t2 = src[j][i] < 0 ? -src[j][i] : src[j][i];
|
||||
if (t2 > t) {
|
||||
swap = j;
|
||||
t = t2;
|
||||
}
|
||||
}
|
||||
|
||||
if (swap != i) {
|
||||
// swap columns.
|
||||
std::swap(src[i], src[swap]);
|
||||
std::swap(inverted[i], inverted[swap]);
|
||||
}
|
||||
|
||||
const T denom(src[i][i]);
|
||||
for (size_t k = 0; k < N; ++k) {
|
||||
src[i][k] /= denom;
|
||||
inverted[i][k] /= denom;
|
||||
}
|
||||
|
||||
// Factor out the lower triangle
|
||||
for (size_t j = 0; j < N; ++j) {
|
||||
if (j != i) {
|
||||
const T t = src[j][i];
|
||||
for (size_t k = 0; k < N; ++k) {
|
||||
src[j][k] -= src[i][k] * t;
|
||||
inverted[j][k] -= inverted[i][k] * t;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return inverted;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// 2x2 matrix inverse is easy.
|
||||
template<typename MATRIX>
|
||||
constexpr MATRIX MATH_PURE fastInverse2(const MATRIX& x) {
|
||||
typedef typename MATRIX::value_type T;
|
||||
|
||||
// Assuming the input matrix is:
|
||||
// | a b |
|
||||
// | c d |
|
||||
//
|
||||
// The analytic inverse is
|
||||
// | d -b |
|
||||
// | -c a | / (a d - b c)
|
||||
//
|
||||
// Importantly, our matrices are column-major!
|
||||
|
||||
MATRIX inverted{};
|
||||
|
||||
const T a = x[0][0];
|
||||
const T c = x[0][1];
|
||||
const T b = x[1][0];
|
||||
const T d = x[1][1];
|
||||
|
||||
const T det((a * d) - (b * c));
|
||||
inverted[0][0] = d / det;
|
||||
inverted[0][1] = -c / det;
|
||||
inverted[1][0] = -b / det;
|
||||
inverted[1][1] = a / det;
|
||||
return inverted;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// From the Wikipedia article on matrix inversion's section on fast 3x3
|
||||
// matrix inversion:
|
||||
// http://en.wikipedia.org/wiki/Invertible_matrix#Inversion_of_3.C3.973_matrices
|
||||
template<typename MATRIX>
|
||||
constexpr MATRIX MATH_PURE fastInverse3(const MATRIX& x) {
|
||||
typedef typename MATRIX::value_type T;
|
||||
|
||||
// Assuming the input matrix is:
|
||||
// | a b c |
|
||||
// | d e f |
|
||||
// | g h i |
|
||||
//
|
||||
// The analytic inverse is
|
||||
// | A B C |^T
|
||||
// | D E F |
|
||||
// | G H I | / determinant
|
||||
//
|
||||
// Which is
|
||||
// | A D G |
|
||||
// | B E H |
|
||||
// | C F I | / determinant
|
||||
//
|
||||
// Where:
|
||||
// A = (ei - fh), B = (fg - di), C = (dh - eg)
|
||||
// D = (ch - bi), E = (ai - cg), F = (bg - ah)
|
||||
// G = (bf - ce), H = (cd - af), I = (ae - bd)
|
||||
//
|
||||
// and the determinant is a*A + b*B + c*C (The rule of Sarrus)
|
||||
//
|
||||
// Importantly, our matrices are column-major!
|
||||
|
||||
MATRIX inverted{};
|
||||
|
||||
const T a = x[0][0];
|
||||
const T b = x[1][0];
|
||||
const T c = x[2][0];
|
||||
const T d = x[0][1];
|
||||
const T e = x[1][1];
|
||||
const T f = x[2][1];
|
||||
const T g = x[0][2];
|
||||
const T h = x[1][2];
|
||||
const T i = x[2][2];
|
||||
|
||||
// Do the full analytic inverse
|
||||
const T A = e * i - f * h;
|
||||
const T B = f * g - d * i;
|
||||
const T C = d * h - e * g;
|
||||
inverted[0][0] = A; // A
|
||||
inverted[0][1] = B; // B
|
||||
inverted[0][2] = C; // C
|
||||
inverted[1][0] = c * h - b * i; // D
|
||||
inverted[1][1] = a * i - c * g; // E
|
||||
inverted[1][2] = b * g - a * h; // F
|
||||
inverted[2][0] = b * f - c * e; // G
|
||||
inverted[2][1] = c * d - a * f; // H
|
||||
inverted[2][2] = a * e - b * d; // I
|
||||
|
||||
const T det(a * A + b * B + c * C);
|
||||
for (size_t col = 0; col < 3; ++col) {
|
||||
for (size_t row = 0; row < 3; ++row) {
|
||||
inverted[col][row] /= det;
|
||||
}
|
||||
}
|
||||
|
||||
return inverted;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Determinant and cofactor
|
||||
|
||||
// this is just a dummy matrix helper
|
||||
template<typename T, size_t ORDER>
|
||||
class Matrix {
|
||||
T m[ORDER][ORDER];
|
||||
public:
|
||||
constexpr auto operator[](size_t i) const noexcept { return m[i]; }
|
||||
|
||||
constexpr auto& operator[](size_t i) noexcept { return m[i]; }
|
||||
|
||||
static constexpr Matrix<T, ORDER - 1> submatrix(Matrix in, size_t row, size_t col) noexcept {
|
||||
size_t colCount = 0, rowCount = 0;
|
||||
Matrix<T, ORDER - 1> dest{};
|
||||
for (size_t i = 0; i < ORDER; i++) {
|
||||
if (i != row) {
|
||||
colCount = 0;
|
||||
for (size_t j = 0; j < ORDER; j++) {
|
||||
if (j != col) {
|
||||
dest[rowCount][colCount] = in[i][j];
|
||||
colCount++;
|
||||
}
|
||||
}
|
||||
rowCount++;
|
||||
}
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, size_t O>
|
||||
struct Determinant {
|
||||
static constexpr T determinant(Matrix<T, O> in) {
|
||||
T det = {};
|
||||
for (size_t i = 0; i < O; i++) {
|
||||
T m = Determinant<T, O - 1>::determinant(Matrix<T, O>::submatrix(in, 0, i));
|
||||
T factor = (i % 2 == 1) ? T(-1) : T(1);
|
||||
det += factor * in[0][i] * m;
|
||||
}
|
||||
return det;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Determinant<T, 3> {
|
||||
static constexpr T determinant(Matrix<T, 3> in) {
|
||||
return
|
||||
in[0][0] * in[1][1] * in[2][2] +
|
||||
in[1][0] * in[2][1] * in[0][2] +
|
||||
in[2][0] * in[0][1] * in[1][2] -
|
||||
in[2][0] * in[1][1] * in[0][2] -
|
||||
in[1][0] * in[0][1] * in[2][2] -
|
||||
in[0][0] * in[2][1] * in[1][2];
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Determinant<T, 2> {
|
||||
static constexpr T determinant(Matrix<T, 2> in) {
|
||||
return in[0][0] * in[1][1] - in[0][1] * in[1][0];
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Determinant<T, 1> {
|
||||
static constexpr T determinant(Matrix<T, 1> in) { return in[0][0]; }
|
||||
};
|
||||
|
||||
template<typename MATRIX>
|
||||
constexpr MATRIX MATH_PURE cofactor(const MATRIX& m) {
|
||||
typedef typename MATRIX::value_type T;
|
||||
|
||||
MATRIX out;
|
||||
constexpr size_t order = MATRIX::NUM_COLS;
|
||||
|
||||
Matrix<T, order> in{};
|
||||
for (size_t i = 0; i < order; i++) {
|
||||
for (size_t j = 0; j < order; j++) {
|
||||
in[i][j] = m[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < order; i++) {
|
||||
for (size_t j = 0; j < order; j++) {
|
||||
T factor = ((i + j) % 2 == 1) ? T(-1) : T(1);
|
||||
out[i][j] = Determinant<T, order - 1>::determinant(
|
||||
Matrix<T, order>::submatrix(in, i, j)) * factor;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
template<typename MATRIX>
|
||||
constexpr MATRIX MATH_PURE fastCofactor2(const MATRIX& m) {
|
||||
typedef typename MATRIX::value_type T;
|
||||
|
||||
// Assuming the input matrix is:
|
||||
// | a b |
|
||||
// | c d |
|
||||
//
|
||||
// The cofactor are
|
||||
// | d -c |
|
||||
// | -b a |
|
||||
//
|
||||
// Importantly, our matrices are column-major!
|
||||
|
||||
MATRIX cof{};
|
||||
|
||||
const T a = m[0][0];
|
||||
const T c = m[0][1];
|
||||
const T b = m[1][0];
|
||||
const T d = m[1][1];
|
||||
|
||||
cof[0][0] = d;
|
||||
cof[0][1] = -b;
|
||||
cof[1][0] = -c;
|
||||
cof[1][1] = a;
|
||||
return cof;
|
||||
}
|
||||
|
||||
template<typename MATRIX>
|
||||
constexpr MATRIX MATH_PURE fastCofactor3(const MATRIX& m) {
|
||||
typedef typename MATRIX::value_type T;
|
||||
|
||||
// Assuming the input matrix is:
|
||||
// | a b c |
|
||||
// | d e f |
|
||||
// | g h i |
|
||||
//
|
||||
// The cofactor are
|
||||
// | A B C |
|
||||
// | D E F |
|
||||
// | G H I |
|
||||
|
||||
// Where:
|
||||
// A = (ei - fh), B = (fg - di), C = (dh - eg)
|
||||
// D = (ch - bi), E = (ai - cg), F = (bg - ah)
|
||||
// G = (bf - ce), H = (cd - af), I = (ae - bd)
|
||||
|
||||
// Importantly, our matrices are column-major!
|
||||
|
||||
MATRIX cof{};
|
||||
|
||||
const T a = m[0][0];
|
||||
const T b = m[1][0];
|
||||
const T c = m[2][0];
|
||||
const T d = m[0][1];
|
||||
const T e = m[1][1];
|
||||
const T f = m[2][1];
|
||||
const T g = m[0][2];
|
||||
const T h = m[1][2];
|
||||
const T i = m[2][2];
|
||||
|
||||
cof[0][0] = e * i - f * h; // A
|
||||
cof[0][1] = c * h - b * i; // D
|
||||
cof[0][2] = b * f - c * e; // G
|
||||
cof[1][0] = f * g - d * i; // B
|
||||
cof[1][1] = a * i - c * g; // E
|
||||
cof[1][2] = c * d - a * f; // H
|
||||
cof[2][0] = d * h - e * g; // C
|
||||
cof[2][1] = b * g - a * h; // F
|
||||
cof[2][2] = a * e - b * d; // I
|
||||
|
||||
return cof;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Cofactor function which switches on the matrix size.
|
||||
*/
|
||||
template<typename MATRIX,
|
||||
typename = std::enable_if_t<MATRIX::NUM_ROWS == MATRIX::NUM_COLS, int>>
|
||||
inline constexpr MATRIX MATH_PURE cof(const MATRIX& matrix) {
|
||||
return (MATRIX::NUM_ROWS == 2) ? fastCofactor2<MATRIX>(matrix) :
|
||||
((MATRIX::NUM_ROWS == 3) ? fastCofactor3<MATRIX>(matrix) :
|
||||
cofactor<MATRIX>(matrix));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determinant of a matrix
|
||||
*/
|
||||
template<typename MATRIX,
|
||||
typename = std::enable_if_t<MATRIX::NUM_ROWS == MATRIX::NUM_COLS, int>>
|
||||
inline constexpr typename MATRIX::value_type MATH_PURE det(const MATRIX& matrix) {
|
||||
typedef typename MATRIX::value_type T;
|
||||
constexpr unsigned int N = MATRIX::NUM_ROWS;
|
||||
Matrix<T, N> in{};
|
||||
for (size_t i = 0; i < N; i++) {
|
||||
for (size_t j = 0; j < N; j++) {
|
||||
in[i][j] = matrix[i][j];
|
||||
}
|
||||
}
|
||||
return Determinant<typename MATRIX::value_type, MATRIX::NUM_COLS>::determinant(in);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inversion function which switches on the matrix size.
|
||||
* @warning This function assumes the matrix is invertible. The result is
|
||||
* undefined if it is not. It is the responsibility of the caller to
|
||||
* make sure the matrix is not singular.
|
||||
*/
|
||||
template<typename MATRIX,
|
||||
typename = std::enable_if_t<MATRIX::NUM_ROWS == MATRIX::NUM_COLS, int>>
|
||||
inline constexpr MATRIX MATH_PURE inverse(const MATRIX& matrix) {
|
||||
return (MATRIX::NUM_ROWS == 2) ? fastInverse2<MATRIX>(matrix) :
|
||||
((MATRIX::NUM_ROWS == 3) ? fastInverse3<MATRIX>(matrix) :
|
||||
gaussJordanInverse<MATRIX>(matrix));
|
||||
}
|
||||
|
||||
template<typename MATRIX_R, typename MATRIX_A, typename MATRIX_B,
|
||||
typename = std::enable_if_t<
|
||||
MATRIX_A::NUM_COLS == MATRIX_B::NUM_ROWS &&
|
||||
MATRIX_R::NUM_COLS == MATRIX_B::NUM_COLS &&
|
||||
MATRIX_R::NUM_ROWS == MATRIX_A::NUM_ROWS, int>>
|
||||
constexpr MATRIX_R MATH_PURE multiply(MATRIX_A lhs, MATRIX_B rhs) {
|
||||
// pre-requisite:
|
||||
// lhs : D columns, R rows
|
||||
// rhs : C columns, D rows
|
||||
// res : C columns, R rows
|
||||
MATRIX_R res{};
|
||||
for (size_t col = 0; col < MATRIX_R::NUM_COLS; ++col) {
|
||||
res[col] = lhs * rhs[col];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename MATRIX,
|
||||
typename = std::enable_if_t<MATRIX::NUM_ROWS == MATRIX::NUM_COLS, int>>
|
||||
inline constexpr MATRIX MATH_PURE transpose(MATRIX m) {
|
||||
// for now we only handle square matrix transpose
|
||||
MATRIX result{};
|
||||
for (size_t col = 0; col < MATRIX::NUM_COLS; ++col) {
|
||||
for (size_t row = 0; row < MATRIX::NUM_ROWS; ++row) {
|
||||
result[col][row] = m[row][col];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename MATRIX,
|
||||
typename = std::enable_if_t<MATRIX::NUM_ROWS == MATRIX::NUM_COLS, int>>
|
||||
inline constexpr typename MATRIX::value_type MATH_PURE trace(MATRIX m) {
|
||||
typename MATRIX::value_type result{};
|
||||
for (size_t col = 0; col < MATRIX::NUM_COLS; ++col) {
|
||||
result += m[col][col];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename MATRIX,
|
||||
typename = std::enable_if_t<MATRIX::NUM_ROWS == MATRIX::NUM_COLS, int>>
|
||||
inline constexpr typename MATRIX::col_type MATH_PURE diag(MATRIX m) {
|
||||
typename MATRIX::col_type result{};
|
||||
for (size_t col = 0; col < MATRIX::NUM_COLS; ++col) {
|
||||
result[col] = m[col][col];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// This is taken from the Imath MatrixAlgo code, and is identical to Eigen.
|
||||
template<typename MATRIX>
|
||||
TQuaternion<typename MATRIX::value_type> extractQuat(const MATRIX& mat) {
|
||||
typedef typename MATRIX::value_type T;
|
||||
|
||||
TQuaternion<T> quat(TQuaternion<T>::NO_INIT);
|
||||
|
||||
// Compute the trace to see if it is positive or not.
|
||||
const T trace = mat[0][0] + mat[1][1] + mat[2][2];
|
||||
|
||||
// check the sign of the trace
|
||||
if (MATH_LIKELY(trace > 0)) {
|
||||
// trace is positive
|
||||
T s = std::sqrt(trace + 1);
|
||||
quat.w = T(0.5) * s;
|
||||
s = T(0.5) / s;
|
||||
quat.x = (mat[1][2] - mat[2][1]) * s;
|
||||
quat.y = (mat[2][0] - mat[0][2]) * s;
|
||||
quat.z = (mat[0][1] - mat[1][0]) * s;
|
||||
} else {
|
||||
// trace is negative
|
||||
|
||||
// Find the index of the greatest diagonal
|
||||
size_t i = 0;
|
||||
if (mat[1][1] > mat[0][0]) { i = 1; }
|
||||
if (mat[2][2] > mat[i][i]) { i = 2; }
|
||||
|
||||
// Get the next indices: (n+1)%3
|
||||
static constexpr size_t next_ijk[3] = { 1, 2, 0 };
|
||||
size_t j = next_ijk[i];
|
||||
size_t k = next_ijk[j];
|
||||
T s = std::sqrt((mat[i][i] - (mat[j][j] + mat[k][k])) + 1);
|
||||
quat[i] = T(0.5) * s;
|
||||
if (s != 0) {
|
||||
s = T(0.5) / s;
|
||||
}
|
||||
quat.w = (mat[j][k] - mat[k][j]) * s;
|
||||
quat[j] = (mat[i][j] + mat[j][i]) * s;
|
||||
quat[k] = (mat[i][k] + mat[k][i]) * s;
|
||||
}
|
||||
return quat;
|
||||
}
|
||||
|
||||
} // namespace matrix
|
||||
|
||||
// -------------------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* TMatProductOperators implements basic arithmetic and basic compound assignments
|
||||
* operators on a vector of type BASE<T>.
|
||||
*
|
||||
* BASE only needs to implement operator[] and size().
|
||||
* By simply inheriting from TMatProductOperators<BASE, T> BASE will automatically
|
||||
* get all the functionality here.
|
||||
*/
|
||||
|
||||
template<template<typename> class BASE, typename T,
|
||||
template<typename> class VEC>
|
||||
class TMatProductOperators {
|
||||
public:
|
||||
// matrix *= matrix
|
||||
template<typename U>
|
||||
constexpr BASE<T>& operator*=(const BASE<U>& rhs) {
|
||||
BASE<T>& lhs(static_cast< BASE<T>& >(*this));
|
||||
lhs = matrix::multiply<BASE<T>>(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
// matrix *= scalar
|
||||
template<typename U, typename = enable_if_arithmetic_t<U>>
|
||||
constexpr BASE<T>& operator*=(U v) {
|
||||
BASE<T>& lhs(static_cast< BASE<T>& >(*this));
|
||||
for (size_t col = 0; col < BASE<T>::NUM_COLS; ++col) {
|
||||
lhs[col] *= v;
|
||||
}
|
||||
return lhs;
|
||||
}
|
||||
|
||||
// matrix /= scalar
|
||||
template<typename U, typename = enable_if_arithmetic_t<U>>
|
||||
constexpr BASE<T>& operator/=(U v) {
|
||||
BASE<T>& lhs(static_cast< BASE<T>& >(*this));
|
||||
for (size_t col = 0; col < BASE<T>::NUM_COLS; ++col) {
|
||||
lhs[col] /= v;
|
||||
}
|
||||
return lhs;
|
||||
}
|
||||
|
||||
private:
|
||||
/*
|
||||
* NOTE: the functions below ARE NOT member methods. They are friend functions
|
||||
* with they definition inlined with their declaration. This makes these
|
||||
* template functions available to the compiler when (and only when) this class
|
||||
* is instantiated, at which point they're only templated on the 2nd parameter
|
||||
* (the first one, BASE<T> being known).
|
||||
*/
|
||||
|
||||
// matrix * matrix
|
||||
template<typename U>
|
||||
friend inline constexpr BASE<arithmetic_result_t<T, U>> MATH_PURE
|
||||
operator*(BASE<T> lhs, BASE<U> rhs) {
|
||||
return matrix::multiply<BASE<arithmetic_result_t<T, U>>>(lhs, rhs);
|
||||
}
|
||||
|
||||
// matrix * vector
|
||||
template<typename U>
|
||||
friend inline constexpr typename BASE<arithmetic_result_t<T, U>>::col_type MATH_PURE
|
||||
operator*(const BASE<T>& lhs, const VEC<U>& rhs) {
|
||||
typename BASE<arithmetic_result_t<T, U>>::col_type result{};
|
||||
for (size_t col = 0; col < BASE<T>::NUM_COLS; ++col) {
|
||||
result += lhs[col] * rhs[col];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// row-vector * matrix
|
||||
template<typename U>
|
||||
friend inline constexpr typename BASE<arithmetic_result_t<T, U>>::row_type MATH_PURE
|
||||
operator*(const VEC<U>& lhs, const BASE<T>& rhs) {
|
||||
typename BASE<arithmetic_result_t<T, U>>::row_type result{};
|
||||
for (size_t col = 0; col < BASE<T>::NUM_COLS; ++col) {
|
||||
result[col] = dot(lhs, rhs[col]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// matrix * scalar
|
||||
template<typename U, typename = enable_if_arithmetic_t <U>>
|
||||
friend inline constexpr BASE<arithmetic_result_t < T, U>> MATH_PURE
|
||||
operator*(const BASE<T>& lhs, U rhs) {
|
||||
BASE<arithmetic_result_t<T, U>> result{};
|
||||
for (size_t col = 0; col < BASE<T>::NUM_COLS; ++col) {
|
||||
result[col] = lhs[col] * rhs;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// scalar * matrix
|
||||
template<typename U, typename = enable_if_arithmetic_t<U>>
|
||||
friend inline constexpr BASE<arithmetic_result_t<T, U>> MATH_PURE
|
||||
operator*(U rhs, const BASE<T>& lhs) {
|
||||
return lhs * rhs;
|
||||
}
|
||||
|
||||
// matrix / scalar
|
||||
template<typename U, typename = enable_if_arithmetic_t<U>>
|
||||
friend inline constexpr BASE<arithmetic_result_t<T, U>> MATH_PURE
|
||||
operator/(const BASE<T>& lhs, U rhs) {
|
||||
BASE<arithmetic_result_t<T, U>> result{};
|
||||
for (size_t col = 0; col < BASE<T>::NUM_COLS; ++col) {
|
||||
result[col] = lhs[col] / rhs;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* TMatSquareFunctions implements functions on a matrix of type BASE<T>.
|
||||
*
|
||||
* BASE only needs to implement:
|
||||
* - operator[]
|
||||
* - col_type
|
||||
* - row_type
|
||||
* - COL_SIZE
|
||||
* - ROW_SIZE
|
||||
*
|
||||
* By simply inheriting from TMatSquareFunctions<BASE, T> BASE will automatically
|
||||
* get all the functionality here.
|
||||
*/
|
||||
|
||||
template<template<typename U> class BASE, typename T>
|
||||
class TMatSquareFunctions {
|
||||
private:
|
||||
/*
|
||||
* NOTE: the functions below ARE NOT member methods. They are friend functions
|
||||
* with they definition inlined with their declaration. This makes these
|
||||
* template functions available to the compiler when (and only when) this class
|
||||
* is instantiated, at which point they're only templated on the 2nd parameter
|
||||
* (the first one, BASE<T> being known).
|
||||
*/
|
||||
friend inline constexpr BASE<T> MATH_PURE inverse(const BASE<T>& matrix) {
|
||||
return matrix::inverse(matrix);
|
||||
}
|
||||
|
||||
friend inline constexpr BASE<T> MATH_PURE cof(const BASE<T>& matrix) {
|
||||
return matrix::cof(matrix);
|
||||
}
|
||||
|
||||
friend inline constexpr BASE<T> MATH_PURE transpose(BASE<T> m) {
|
||||
return matrix::transpose(m);
|
||||
}
|
||||
|
||||
friend inline constexpr T MATH_PURE trace(BASE<T> m) {
|
||||
return matrix::trace(m);
|
||||
}
|
||||
|
||||
friend inline constexpr T MATH_PURE det(const BASE<T>& m) {
|
||||
return matrix::det(m);
|
||||
}
|
||||
|
||||
// unclear why we have to use 'auto' here. 'typename BASE<T>::col_type' produces
|
||||
// error: no type named 'col_type' in 'filament::math::details::TMat44<float>'
|
||||
friend inline constexpr auto MATH_PURE diag(const BASE<T>& m) {
|
||||
return matrix::diag(m);
|
||||
}
|
||||
};
|
||||
|
||||
template<template<typename U> class BASE, typename T>
|
||||
class TMatHelpers {
|
||||
public:
|
||||
constexpr inline size_t getColumnSize() const { return BASE<T>::COL_SIZE; }
|
||||
constexpr inline size_t getRowSize() const { return BASE<T>::ROW_SIZE; }
|
||||
constexpr inline size_t getColumnCount() const { return BASE<T>::NUM_COLS; }
|
||||
constexpr inline size_t getRowCount() const { return BASE<T>::NUM_ROWS; }
|
||||
constexpr inline size_t size() const { return BASE<T>::ROW_SIZE; } // for TVec*<>
|
||||
|
||||
// array access
|
||||
constexpr T const* asArray() const {
|
||||
return &static_cast<BASE<T> const &>(*this)[0][0];
|
||||
}
|
||||
|
||||
// element access
|
||||
inline constexpr T const& operator()(size_t row, size_t col) const {
|
||||
return static_cast<BASE<T> const &>(*this)[col][row];
|
||||
}
|
||||
|
||||
inline T& operator()(size_t row, size_t col) {
|
||||
return static_cast<BASE<T>&>(*this)[col][row];
|
||||
}
|
||||
|
||||
private:
|
||||
constexpr friend inline BASE<T> MATH_PURE abs(BASE<T> m) {
|
||||
for (size_t col = 0; col < BASE<T>::NUM_COLS; ++col) {
|
||||
m[col] = abs(m[col]);
|
||||
}
|
||||
return m;
|
||||
}
|
||||
};
|
||||
|
||||
// functions for 3x3 and 4x4 matrices
|
||||
template<template<typename U> class BASE, typename T>
|
||||
class TMatTransform {
|
||||
public:
|
||||
inline constexpr TMatTransform() {
|
||||
static_assert(BASE<T>::NUM_ROWS == 3 || BASE<T>::NUM_ROWS == 4, "3x3 or 4x4 matrices only");
|
||||
}
|
||||
|
||||
template<typename A, typename VEC, typename = enable_if_arithmetic_t<A>>
|
||||
static BASE<T> rotation(A radian, VEC about) {
|
||||
BASE<T> r;
|
||||
T c = std::cos(radian);
|
||||
T s = std::sin(radian);
|
||||
if (about[0] == 1 && about[1] == 0 && about[2] == 0) {
|
||||
r[1][1] = c; r[2][2] = c;
|
||||
r[1][2] = s; r[2][1] = -s;
|
||||
} else if (about[0] == 0 && about[1] == 1 && about[2] == 0) {
|
||||
r[0][0] = c; r[2][2] = c;
|
||||
r[2][0] = s; r[0][2] = -s;
|
||||
} else if (about[0] == 0 && about[1] == 0 && about[2] == 1) {
|
||||
r[0][0] = c; r[1][1] = c;
|
||||
r[0][1] = s; r[1][0] = -s;
|
||||
} else {
|
||||
VEC nabout = normalize(about);
|
||||
typename VEC::value_type x = nabout[0];
|
||||
typename VEC::value_type y = nabout[1];
|
||||
typename VEC::value_type z = nabout[2];
|
||||
T nc = 1 - c;
|
||||
T xy = x * y;
|
||||
T yz = y * z;
|
||||
T zx = z * x;
|
||||
T xs = x * s;
|
||||
T ys = y * s;
|
||||
T zs = z * s;
|
||||
r[0][0] = x*x*nc + c; r[1][0] = xy*nc - zs; r[2][0] = zx*nc + ys;
|
||||
r[0][1] = xy*nc + zs; r[1][1] = y*y*nc + c; r[2][1] = yz*nc - xs;
|
||||
r[0][2] = zx*nc - ys; r[1][2] = yz*nc + xs; r[2][2] = z*z*nc + c;
|
||||
|
||||
// Clamp results to -1, 1.
|
||||
for (size_t col = 0; col < 3; ++col) {
|
||||
for (size_t row = 0; row < 3; ++row) {
|
||||
r[col][row] = std::min(std::max(r[col][row], T(-1)), T(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a matrix from euler angles using YPR around YXZ respectively
|
||||
* @param yaw about Y axis
|
||||
* @param pitch about X axis
|
||||
* @param roll about Z axis
|
||||
*/
|
||||
template<typename Y, typename P, typename R, typename = enable_if_arithmetic_t<Y, P, R>>
|
||||
static BASE<T> eulerYXZ(Y yaw, P pitch, R roll) {
|
||||
return eulerZYX(roll, pitch, yaw);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a matrix from euler angles using YPR around ZYX respectively
|
||||
* @param roll about X axis
|
||||
* @param pitch about Y axis
|
||||
* @param yaw about Z axis
|
||||
*
|
||||
* The euler angles are applied in ZYX order. i.e: a vector is first rotated
|
||||
* about X (roll) then Y (pitch) and then Z (yaw).
|
||||
*/
|
||||
template<typename Y, typename P, typename R, typename = enable_if_arithmetic_t<Y, P, R>>
|
||||
static BASE<T> eulerZYX(Y yaw, P pitch, R roll) {
|
||||
BASE<T> r;
|
||||
T cy = std::cos(yaw);
|
||||
T sy = std::sin(yaw);
|
||||
T cp = std::cos(pitch);
|
||||
T sp = std::sin(pitch);
|
||||
T cr = std::cos(roll);
|
||||
T sr = std::sin(roll);
|
||||
T cc = cr * cy;
|
||||
T cs = cr * sy;
|
||||
T sc = sr * cy;
|
||||
T ss = sr * sy;
|
||||
r[0][0] = cp * cy;
|
||||
r[0][1] = cp * sy;
|
||||
r[0][2] = -sp;
|
||||
r[1][0] = sp * sc - cs;
|
||||
r[1][1] = sp * ss + cc;
|
||||
r[1][2] = cp * sr;
|
||||
r[2][0] = sp * cc + ss;
|
||||
r[2][1] = sp * cs - sc;
|
||||
r[2][2] = cp * cr;
|
||||
|
||||
// Clamp results to -1, 1.
|
||||
for (size_t col = 0; col < 3; ++col) {
|
||||
for (size_t row = 0; row < 3; ++row) {
|
||||
r[col][row] = std::min(std::max(r[col][row], T(-1)), T(1));
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
TQuaternion <T> toQuaternion() const {
|
||||
return matrix::extractQuat(static_cast<const BASE<T>&>(*this));
|
||||
}
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------------
|
||||
} // namespace details
|
||||
} // namespace math
|
||||
} // namespace filament
|
||||
|
||||
#endif // MATH_TMATHELPERS_H_
|
||||
292
ios/include/math/TQuatHelpers.h
Normal file
292
ios/include/math/TQuatHelpers.h
Normal file
@@ -0,0 +1,292 @@
|
||||
/*
|
||||
* Copyright 2013 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 MATH_TQUATHELPERS_H_
|
||||
#define MATH_TQUATHELPERS_H_
|
||||
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <math/compiler.h>
|
||||
#include <math/scalar.h>
|
||||
#include <math/vec3.h>
|
||||
|
||||
namespace filament {
|
||||
namespace math {
|
||||
namespace details {
|
||||
// -------------------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* No user serviceable parts here.
|
||||
*
|
||||
* Don't use this file directly, instead include math/quat.h
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* TQuatProductOperators implements basic arithmetic and basic compound assignment
|
||||
* operators on a quaternion of type BASE<T>.
|
||||
*
|
||||
* BASE only needs to implement operator[] and size().
|
||||
* By simply inheriting from TQuatProductOperators<BASE, T> BASE will automatically
|
||||
* get all the functionality here.
|
||||
*/
|
||||
|
||||
template<template<typename T> class QUATERNION, typename T>
|
||||
class TQuatProductOperators {
|
||||
public:
|
||||
/* compound assignment from a another quaternion of the same size but different
|
||||
* element type.
|
||||
*/
|
||||
template<typename OTHER>
|
||||
constexpr QUATERNION<T>& operator*=(const QUATERNION<OTHER>& r) {
|
||||
QUATERNION<T>& q = static_cast<QUATERNION<T>&>(*this);
|
||||
q = q * r;
|
||||
return q;
|
||||
}
|
||||
|
||||
/* compound assignment products by a scalar
|
||||
*/
|
||||
constexpr QUATERNION<T>& operator*=(T v) {
|
||||
QUATERNION<T>& lhs = static_cast<QUATERNION<T>&>(*this);
|
||||
for (size_t i = 0; i < QUATERNION<T>::size(); i++) {
|
||||
lhs[i] *= v;
|
||||
}
|
||||
return lhs;
|
||||
}
|
||||
|
||||
constexpr QUATERNION<T>& operator/=(T v) {
|
||||
QUATERNION<T>& lhs = static_cast<QUATERNION<T>&>(*this);
|
||||
for (size_t i = 0; i < QUATERNION<T>::size(); i++) {
|
||||
lhs[i] /= v;
|
||||
}
|
||||
return lhs;
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: the functions below ARE NOT member methods. They are friend functions
|
||||
* with they definition inlined with their declaration. This makes these
|
||||
* template functions available to the compiler when (and only when) this class
|
||||
* is instantiated, at which point they're only templated on the 2nd parameter
|
||||
* (the first one, BASE<T> being known).
|
||||
*/
|
||||
|
||||
/* The operators below handle operation between quaternion of the same size
|
||||
* but of a different element type.
|
||||
*/
|
||||
template<typename RT>
|
||||
friend inline
|
||||
constexpr QUATERNION<T> MATH_PURE operator*(const QUATERNION<T>& q, const QUATERNION<RT>& r) {
|
||||
// could be written as:
|
||||
// return QUATERNION<T>(
|
||||
// q.w*r.w - dot(q.xyz, r.xyz),
|
||||
// q.w*r.xyz + r.w*q.xyz + cross(q.xyz, r.xyz));
|
||||
|
||||
return QUATERNION<T>(
|
||||
q.w * r.w - q.x * r.x - q.y * r.y - q.z * r.z,
|
||||
q.w * r.x + q.x * r.w + q.y * r.z - q.z * r.y,
|
||||
q.w * r.y - q.x * r.z + q.y * r.w + q.z * r.x,
|
||||
q.w * r.z + q.x * r.y - q.y * r.x + q.z * r.w);
|
||||
}
|
||||
|
||||
template<typename RT>
|
||||
friend inline
|
||||
constexpr TVec3<T> MATH_PURE operator*(const QUATERNION<T>& q, const TVec3<RT>& v) {
|
||||
// note: if q is known to be a unit quaternion, then this simplifies to:
|
||||
// TVec3<T> t = 2 * cross(q.xyz, v)
|
||||
// return v + (q.w * t) + cross(q.xyz, t)
|
||||
return imaginary(q * QUATERNION<T>(v, 0) * inverse(q));
|
||||
}
|
||||
|
||||
|
||||
/* For quaternions, we use explicit "by a scalar" products because it's much faster
|
||||
* than going (implicitly) through the quaternion multiplication.
|
||||
* For reference: we could use the code below instead, but it would be a lot slower.
|
||||
* friend inline
|
||||
* constexpr BASE<T> MATH_PURE operator *(const BASE<T>& q, const BASE<T>& r) {
|
||||
* return BASE<T>(
|
||||
* q.w*r.w - q.x*r.x - q.y*r.y - q.z*r.z,
|
||||
* q.w*r.x + q.x*r.w + q.y*r.z - q.z*r.y,
|
||||
* q.w*r.y - q.x*r.z + q.y*r.w + q.z*r.x,
|
||||
* q.w*r.z + q.x*r.y - q.y*r.x + q.z*r.w);
|
||||
*
|
||||
*/
|
||||
friend inline
|
||||
constexpr QUATERNION<T> MATH_PURE operator*(QUATERNION<T> q, T scalar) {
|
||||
// don't pass q by reference because we need a copy anyways
|
||||
return q *= scalar;
|
||||
}
|
||||
|
||||
friend inline
|
||||
constexpr QUATERNION<T> MATH_PURE operator*(T scalar, QUATERNION<T> q) {
|
||||
// don't pass q by reference because we need a copy anyways
|
||||
return q *= scalar;
|
||||
}
|
||||
|
||||
friend inline
|
||||
constexpr QUATERNION<T> MATH_PURE operator/(QUATERNION<T> q, T scalar) {
|
||||
// don't pass q by reference because we need a copy anyways
|
||||
return q /= scalar;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* TQuatFunctions implements functions on a quaternion of type BASE<T>.
|
||||
*
|
||||
* BASE only needs to implement operator[] and size().
|
||||
* By simply inheriting from TQuatFunctions<BASE, T> BASE will automatically
|
||||
* get all the functionality here.
|
||||
*/
|
||||
template<template<typename T> class QUATERNION, typename T>
|
||||
class TQuatFunctions {
|
||||
public:
|
||||
/*
|
||||
* NOTE: the functions below ARE NOT member methods. They are friend functions
|
||||
* with they definition inlined with their declaration. This makes these
|
||||
* template functions available to the compiler when (and only when) this class
|
||||
* is instantiated, at which point they're only templated on the 2nd parameter
|
||||
* (the first one, BASE<T> being known).
|
||||
*/
|
||||
|
||||
template<typename RT>
|
||||
friend inline
|
||||
constexpr T MATH_PURE dot(const QUATERNION<T>& p, const QUATERNION<RT>& q) {
|
||||
return p.x * q.x +
|
||||
p.y * q.y +
|
||||
p.z * q.z +
|
||||
p.w * q.w;
|
||||
}
|
||||
|
||||
friend inline
|
||||
T MATH_PURE norm(const QUATERNION<T>& q) {
|
||||
return std::sqrt(dot(q, q));
|
||||
}
|
||||
|
||||
friend inline
|
||||
T MATH_PURE length(const QUATERNION<T>& q) {
|
||||
return norm(q);
|
||||
}
|
||||
|
||||
friend inline
|
||||
constexpr T MATH_PURE length2(const QUATERNION<T>& q) {
|
||||
return dot(q, q);
|
||||
}
|
||||
|
||||
friend inline
|
||||
QUATERNION<T> MATH_PURE normalize(const QUATERNION<T>& q) {
|
||||
return length(q) ? q / length(q) : QUATERNION<T>(static_cast<T>(1));
|
||||
}
|
||||
|
||||
friend inline
|
||||
constexpr QUATERNION<T> MATH_PURE conj(const QUATERNION<T>& q) {
|
||||
return QUATERNION<T>(q.w, -q.x, -q.y, -q.z);
|
||||
}
|
||||
|
||||
friend inline
|
||||
constexpr QUATERNION<T> MATH_PURE inverse(const QUATERNION<T>& q) {
|
||||
return conj(q) * (1 / dot(q, q));
|
||||
}
|
||||
|
||||
friend inline
|
||||
constexpr T MATH_PURE real(const QUATERNION<T>& q) {
|
||||
return q.w;
|
||||
}
|
||||
|
||||
friend inline
|
||||
constexpr TVec3<T> MATH_PURE imaginary(const QUATERNION<T>& q) {
|
||||
return q.xyz;
|
||||
}
|
||||
|
||||
friend inline
|
||||
constexpr QUATERNION<T> MATH_PURE unreal(const QUATERNION<T>& q) {
|
||||
return QUATERNION<T>(q.xyz, 0);
|
||||
}
|
||||
|
||||
friend inline
|
||||
constexpr QUATERNION<T> MATH_PURE cross(const QUATERNION<T>& p, const QUATERNION<T>& q) {
|
||||
return unreal(p * q);
|
||||
}
|
||||
|
||||
friend inline
|
||||
QUATERNION<T> MATH_PURE exp(const QUATERNION<T>& q) {
|
||||
const T nq(norm(q.xyz));
|
||||
return std::exp(q.w) * QUATERNION<T>((sin(nq) / nq) * q.xyz, cos(nq));
|
||||
}
|
||||
|
||||
friend inline
|
||||
QUATERNION<T> MATH_PURE log(const QUATERNION<T>& q) {
|
||||
const T nq(norm(q));
|
||||
return QUATERNION<T>((std::acos(q.w / nq) / norm(q.xyz)) * q.xyz, std::log(nq));
|
||||
}
|
||||
|
||||
friend inline
|
||||
QUATERNION<T> MATH_PURE pow(const QUATERNION<T>& q, T a) {
|
||||
// could also be computed as: exp(a*log(q));
|
||||
const T nq(norm(q));
|
||||
const T theta(a * std::acos(q.w / nq));
|
||||
return std::pow(nq, a) * QUATERNION<T>(normalize(q.xyz) * std::sin(theta), std::cos(theta));
|
||||
}
|
||||
|
||||
friend inline
|
||||
QUATERNION<T> MATH_PURE slerp(const QUATERNION<T>& p, const QUATERNION<T>& q, T t) {
|
||||
// could also be computed as: pow(q * inverse(p), t) * p;
|
||||
const T d = dot(p, q);
|
||||
const T absd = std::abs(d);
|
||||
static constexpr T value_eps = T(10) * std::numeric_limits<T>::epsilon();
|
||||
// Prevent blowing up when slerping between two quaternions that are very near each other.
|
||||
if ((T(1) - absd) < value_eps) {
|
||||
return normalize(lerp(d < 0 ? -p : p, q, t));
|
||||
}
|
||||
const T npq = std::sqrt(dot(p, p) * dot(q, q)); // ||p|| * ||q||
|
||||
const T a = std::acos(filament::math::clamp(absd / npq, T(-1), T(1)));
|
||||
const T a0 = a * (1 - t);
|
||||
const T a1 = a * t;
|
||||
const T sina = sin(a);
|
||||
if (sina < value_eps) {
|
||||
return normalize(lerp(p, q, t));
|
||||
}
|
||||
const T isina = 1 / sina;
|
||||
const T s0 = std::sin(a0) * isina;
|
||||
const T s1 = std::sin(a1) * isina;
|
||||
// ensure we're taking the "short" side
|
||||
return normalize(s0 * p + ((d < 0) ? (-s1) : (s1)) * q);
|
||||
}
|
||||
|
||||
friend inline
|
||||
constexpr QUATERNION<T> MATH_PURE lerp(const QUATERNION<T>& p, const QUATERNION<T>& q, T t) {
|
||||
return ((1 - t) * p) + (t * q);
|
||||
}
|
||||
|
||||
friend inline
|
||||
constexpr QUATERNION<T> MATH_PURE nlerp(const QUATERNION<T>& p, const QUATERNION<T>& q, T t) {
|
||||
return normalize(lerp(p, q, t));
|
||||
}
|
||||
|
||||
friend inline
|
||||
constexpr QUATERNION<T> MATH_PURE positive(const QUATERNION<T>& q) {
|
||||
return q.w < 0 ? -q : q;
|
||||
}
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------------
|
||||
} // namespace details
|
||||
} // namespace math
|
||||
} // namespace filament
|
||||
|
||||
#endif // MATH_TQUATHELPERS_H_
|
||||
625
ios/include/math/TVecHelpers.h
Normal file
625
ios/include/math/TVecHelpers.h
Normal file
@@ -0,0 +1,625 @@
|
||||
/*
|
||||
* Copyright 2013 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 MATH_TVECHELPERS_H_
|
||||
#define MATH_TVECHELPERS_H_
|
||||
|
||||
#include <math/compiler.h>
|
||||
|
||||
#include <cmath> // for std:: namespace
|
||||
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
namespace filament {
|
||||
namespace math {
|
||||
namespace details {
|
||||
// -------------------------------------------------------------------------------------
|
||||
|
||||
template<typename U>
|
||||
inline constexpr U min(U a, U b) noexcept {
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
inline constexpr U max(U a, U b) noexcept {
|
||||
return a > b ? a : b;
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
struct arithmetic_result {
|
||||
using type = decltype(std::declval<T>() + std::declval<U>());
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
using arithmetic_result_t = typename arithmetic_result<T, U>::type;
|
||||
|
||||
template<typename A, typename B = int, typename C = int, typename D = int>
|
||||
using enable_if_arithmetic_t = std::enable_if_t<
|
||||
is_arithmetic<A>::value &&
|
||||
is_arithmetic<B>::value &&
|
||||
is_arithmetic<C>::value &&
|
||||
is_arithmetic<D>::value>;
|
||||
|
||||
/*
|
||||
* No user serviceable parts here.
|
||||
*
|
||||
* Don't use this file directly, instead include math/vec{2|3|4}.h
|
||||
*/
|
||||
|
||||
/*
|
||||
* TVec{Add|Product}Operators implements basic arithmetic and basic compound assignments
|
||||
* operators on a vector of type BASE<T>.
|
||||
*
|
||||
* BASE only needs to implement operator[] and size().
|
||||
* By simply inheriting from TVec{Add|Product}Operators<BASE, T> BASE will automatically
|
||||
* get all the functionality here.
|
||||
*/
|
||||
|
||||
template<template<typename T> class VECTOR, typename T>
|
||||
class TVecAddOperators {
|
||||
public:
|
||||
/* compound assignment from a another vector of the same size but different
|
||||
* element type.
|
||||
*/
|
||||
template<typename U>
|
||||
constexpr VECTOR<T>& operator+=(const VECTOR<U>& v) {
|
||||
VECTOR<T>& lhs = static_cast<VECTOR<T>&>(*this);
|
||||
for (size_t i = 0; i < lhs.size(); i++) {
|
||||
lhs[i] += v[i];
|
||||
}
|
||||
return lhs;
|
||||
}
|
||||
|
||||
template<typename U, typename = enable_if_arithmetic_t<U>>
|
||||
constexpr VECTOR<T>& operator+=(U v) {
|
||||
return operator+=(VECTOR<U>(v));
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
constexpr VECTOR<T>& operator-=(const VECTOR<U>& v) {
|
||||
VECTOR<T>& lhs = static_cast<VECTOR<T>&>(*this);
|
||||
for (size_t i = 0; i < lhs.size(); i++) {
|
||||
lhs[i] -= v[i];
|
||||
}
|
||||
return lhs;
|
||||
}
|
||||
|
||||
template<typename U, typename = enable_if_arithmetic_t<U>>
|
||||
constexpr VECTOR<T>& operator-=(U v) {
|
||||
return operator-=(VECTOR<U>(v));
|
||||
}
|
||||
|
||||
private:
|
||||
/*
|
||||
* NOTE: the functions below ARE NOT member methods. They are friend functions
|
||||
* with they definition inlined with their declaration. This makes these
|
||||
* template functions available to the compiler when (and only when) this class
|
||||
* is instantiated, at which point they're only templated on the 2nd parameter
|
||||
* (the first one, BASE<T> being known).
|
||||
*/
|
||||
|
||||
template<typename U>
|
||||
friend inline constexpr
|
||||
VECTOR<arithmetic_result_t<T, U>> MATH_PURE operator+(const VECTOR<T>& lv, const VECTOR<U>& rv) {
|
||||
VECTOR<arithmetic_result_t<T, U>> res(lv);
|
||||
res += rv;
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename U, typename = enable_if_arithmetic_t<U>>
|
||||
friend inline constexpr
|
||||
VECTOR<arithmetic_result_t<T, U>> MATH_PURE operator+(const VECTOR<T>& lv, U rv) {
|
||||
return lv + VECTOR<U>(rv);
|
||||
}
|
||||
|
||||
template<typename U, typename = enable_if_arithmetic_t<U>>
|
||||
friend inline constexpr
|
||||
VECTOR<arithmetic_result_t<T, U>> MATH_PURE operator+(U lv, const VECTOR<T>& rv) {
|
||||
return VECTOR<U>(lv) + rv;
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
friend inline constexpr
|
||||
VECTOR<arithmetic_result_t<T, U>> MATH_PURE operator-(const VECTOR<T>& lv, const VECTOR<U>& rv) {
|
||||
VECTOR<arithmetic_result_t<T, U>> res(lv);
|
||||
res -= rv;
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename U, typename = enable_if_arithmetic_t<U>>
|
||||
friend inline constexpr
|
||||
VECTOR<arithmetic_result_t<T, U>> MATH_PURE operator-(const VECTOR<T>& lv, U rv) {
|
||||
return lv - VECTOR<U>(rv);
|
||||
}
|
||||
|
||||
template<typename U, typename = enable_if_arithmetic_t<U>>
|
||||
friend inline constexpr
|
||||
VECTOR<arithmetic_result_t<T, U>> MATH_PURE operator-(U lv, const VECTOR<T>& rv) {
|
||||
return VECTOR<U>(lv) - rv;
|
||||
}
|
||||
};
|
||||
|
||||
template<template<typename T> class VECTOR, typename T>
|
||||
class TVecProductOperators {
|
||||
public:
|
||||
/* compound assignment from a another vector of the same size but different
|
||||
* element type.
|
||||
*/
|
||||
template<typename U>
|
||||
constexpr VECTOR<T>& operator*=(const VECTOR<U>& v) {
|
||||
VECTOR<T>& lhs = static_cast<VECTOR<T>&>(*this);
|
||||
for (size_t i = 0; i < lhs.size(); i++) {
|
||||
lhs[i] *= v[i];
|
||||
}
|
||||
return lhs;
|
||||
}
|
||||
|
||||
template<typename U, typename = enable_if_arithmetic_t<U>>
|
||||
constexpr VECTOR<T>& operator*=(U v) {
|
||||
return operator*=(VECTOR<U>(v));
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
constexpr VECTOR<T>& operator/=(const VECTOR<U>& v) {
|
||||
VECTOR<T>& lhs = static_cast<VECTOR<T>&>(*this);
|
||||
for (size_t i = 0; i < lhs.size(); i++) {
|
||||
lhs[i] /= v[i];
|
||||
}
|
||||
return lhs;
|
||||
}
|
||||
|
||||
template<typename U, typename = enable_if_arithmetic_t<U>>
|
||||
constexpr VECTOR<T>& operator/=(U v) {
|
||||
return operator/=(VECTOR<U>(v));
|
||||
}
|
||||
|
||||
private:
|
||||
/*
|
||||
* NOTE: the functions below ARE NOT member methods. They are friend functions
|
||||
* with they definition inlined with their declaration. This makes these
|
||||
* template functions available to the compiler when (and only when) this class
|
||||
* is instantiated, at which point they're only templated on the 2nd parameter
|
||||
* (the first one, BASE<T> being known).
|
||||
*/
|
||||
|
||||
template<typename U>
|
||||
friend inline constexpr
|
||||
VECTOR<arithmetic_result_t<T, U>> MATH_PURE operator*(const VECTOR<T>& lv, const VECTOR<U>& rv) {
|
||||
VECTOR<arithmetic_result_t<T, U>> res(lv);
|
||||
res *= rv;
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename U, typename = enable_if_arithmetic_t<U>>
|
||||
friend inline constexpr
|
||||
VECTOR<arithmetic_result_t<T, U>> MATH_PURE operator*(const VECTOR<T>& lv, U rv) {
|
||||
return lv * VECTOR<U>(rv);
|
||||
}
|
||||
|
||||
template<typename U, typename = enable_if_arithmetic_t<U>>
|
||||
friend inline constexpr
|
||||
VECTOR<arithmetic_result_t<T, U>> MATH_PURE operator*(U lv, const VECTOR<T>& rv) {
|
||||
return VECTOR<U>(lv) * rv;
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
friend inline constexpr
|
||||
VECTOR<arithmetic_result_t<T, U>> MATH_PURE operator/(const VECTOR<T>& lv, const VECTOR<U>& rv) {
|
||||
VECTOR<arithmetic_result_t<T, U>> res(lv);
|
||||
res /= rv;
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename U, typename = enable_if_arithmetic_t<U>>
|
||||
friend inline constexpr
|
||||
VECTOR<arithmetic_result_t<T, U>> MATH_PURE operator/(const VECTOR<T>& lv, U rv) {
|
||||
return lv / VECTOR<U>(rv);
|
||||
}
|
||||
|
||||
template<typename U, typename = enable_if_arithmetic_t<U>>
|
||||
friend inline constexpr
|
||||
VECTOR<arithmetic_result_t<T, U>> MATH_PURE operator/(U lv, const VECTOR<T>& rv) {
|
||||
return VECTOR<U>(lv) / rv;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* TVecUnaryOperators implements unary operators on a vector of type BASE<T>.
|
||||
*
|
||||
* BASE only needs to implement operator[] and size().
|
||||
* By simply inheriting from TVecUnaryOperators<BASE, T> BASE will automatically
|
||||
* get all the functionality here.
|
||||
*
|
||||
* These operators are implemented as friend functions of TVecUnaryOperators<BASE, T>
|
||||
*/
|
||||
template<template<typename T> class VECTOR, typename T>
|
||||
class TVecUnaryOperators {
|
||||
public:
|
||||
constexpr VECTOR<T> operator-() const {
|
||||
VECTOR<T> r{};
|
||||
VECTOR<T> const& rv(static_cast<VECTOR<T> const&>(*this));
|
||||
for (size_t i = 0; i < r.size(); i++) {
|
||||
r[i] = -rv[i];
|
||||
}
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* TVecComparisonOperators implements relational/comparison operators
|
||||
* on a vector of type BASE<T>.
|
||||
*
|
||||
* BASE only needs to implement operator[] and size().
|
||||
* By simply inheriting from TVecComparisonOperators<BASE, T> BASE will automatically
|
||||
* get all the functionality here.
|
||||
*/
|
||||
template<template<typename T> class VECTOR, typename T>
|
||||
class TVecComparisonOperators {
|
||||
private:
|
||||
/*
|
||||
* NOTE: the functions below ARE NOT member methods. They are friend functions
|
||||
* with they definition inlined with their declaration. This makes these
|
||||
* template functions available to the compiler when (and only when) this class
|
||||
* is instantiated, at which point they're only templated on the 2nd parameter
|
||||
* (the first one, BASE<T> being known).
|
||||
*/
|
||||
template<typename U>
|
||||
friend inline constexpr
|
||||
bool MATH_PURE operator==(const VECTOR<T>& lv, const VECTOR<U>& rv) {
|
||||
// w/ inlining we end-up with many branches that will pollute the BPU cache
|
||||
MATH_NOUNROLL
|
||||
for (size_t i = 0; i < lv.size(); i++) {
|
||||
if (lv[i] != rv[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
friend inline constexpr
|
||||
bool MATH_PURE operator!=(const VECTOR<T>& lv, const VECTOR<U>& rv) {
|
||||
return !operator==(lv, rv);
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
friend inline constexpr
|
||||
VECTOR<bool> MATH_PURE equal(const VECTOR<T>& lv, const VECTOR<U>& rv) {
|
||||
VECTOR<bool> r{};
|
||||
for (size_t i = 0; i < lv.size(); i++) {
|
||||
r[i] = lv[i] == rv[i];
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
friend inline constexpr
|
||||
VECTOR<bool> MATH_PURE notEqual(const VECTOR<T>& lv, const VECTOR<U>& rv) {
|
||||
VECTOR<bool> r{};
|
||||
for (size_t i = 0; i < lv.size(); i++) {
|
||||
r[i] = lv[i] != rv[i];
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
friend inline constexpr
|
||||
VECTOR<bool> MATH_PURE lessThan(const VECTOR<T>& lv, const VECTOR<U>& rv) {
|
||||
VECTOR<bool> r{};
|
||||
for (size_t i = 0; i < lv.size(); i++) {
|
||||
r[i] = lv[i] < rv[i];
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
friend inline constexpr
|
||||
VECTOR<bool> MATH_PURE lessThanEqual(const VECTOR<T>& lv, const VECTOR<U>& rv) {
|
||||
VECTOR<bool> r{};
|
||||
for (size_t i = 0; i < lv.size(); i++) {
|
||||
r[i] = lv[i] <= rv[i];
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
friend inline constexpr
|
||||
VECTOR<bool> MATH_PURE greaterThan(const VECTOR<T>& lv, const VECTOR<U>& rv) {
|
||||
VECTOR<bool> r;
|
||||
for (size_t i = 0; i < lv.size(); i++) {
|
||||
r[i] = lv[i] > rv[i];
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
friend inline
|
||||
VECTOR<bool> MATH_PURE greaterThanEqual(const VECTOR<T>& lv, const VECTOR<U>& rv) {
|
||||
VECTOR<bool> r{};
|
||||
for (size_t i = 0; i < lv.size(); i++) {
|
||||
r[i] = lv[i] >= rv[i];
|
||||
}
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* TVecFunctions implements functions on a vector of type BASE<T>.
|
||||
*
|
||||
* BASE only needs to implement operator[] and size().
|
||||
* By simply inheriting from TVecFunctions<BASE, T> BASE will automatically
|
||||
* get all the functionality here.
|
||||
*/
|
||||
template<template<typename T> class VECTOR, typename T>
|
||||
class TVecFunctions {
|
||||
private:
|
||||
/*
|
||||
* NOTE: the functions below ARE NOT member methods. They are friend functions
|
||||
* with they definition inlined with their declaration. This makes these
|
||||
* template functions available to the compiler when (and only when) this class
|
||||
* is instantiated, at which point they're only templated on the 2nd parameter
|
||||
* (the first one, BASE<T> being known).
|
||||
*/
|
||||
template<typename U>
|
||||
friend constexpr inline
|
||||
arithmetic_result_t<T, U> MATH_PURE dot(const VECTOR<T>& lv, const VECTOR<U>& rv) {
|
||||
arithmetic_result_t<T, U> r{};
|
||||
for (size_t i = 0; i < lv.size(); i++) {
|
||||
r += lv[i] * rv[i];
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
friend inline T MATH_PURE norm(const VECTOR<T>& lv) {
|
||||
return std::sqrt(dot(lv, lv));
|
||||
}
|
||||
|
||||
friend inline T MATH_PURE length(const VECTOR<T>& lv) {
|
||||
return norm(lv);
|
||||
}
|
||||
|
||||
friend inline constexpr T MATH_PURE norm2(const VECTOR<T>& lv) {
|
||||
return dot(lv, lv);
|
||||
}
|
||||
|
||||
friend inline constexpr T MATH_PURE length2(const VECTOR<T>& lv) {
|
||||
return norm2(lv);
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
friend inline constexpr
|
||||
arithmetic_result_t<T, U> MATH_PURE distance(const VECTOR<T>& lv, const VECTOR<U>& rv) {
|
||||
return length(rv - lv);
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
friend inline constexpr
|
||||
arithmetic_result_t<T, U> MATH_PURE distance2(const VECTOR<T>& lv, const VECTOR<U>& rv) {
|
||||
return length2(rv - lv);
|
||||
}
|
||||
|
||||
friend inline VECTOR<T> MATH_PURE normalize(const VECTOR<T>& lv) {
|
||||
return lv * (T(1) / length(lv));
|
||||
}
|
||||
|
||||
friend inline VECTOR<T> MATH_PURE rcp(VECTOR<T> v) {
|
||||
return T(1) / v;
|
||||
}
|
||||
|
||||
friend inline constexpr VECTOR<T> MATH_PURE abs(VECTOR<T> v) {
|
||||
for (size_t i = 0; i < v.size(); i++) {
|
||||
v[i] = v[i] < 0 ? -v[i] : v[i];
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
friend inline VECTOR<T> MATH_PURE floor(VECTOR<T> v) {
|
||||
for (size_t i = 0; i < v.size(); i++) {
|
||||
v[i] = std::floor(v[i]);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
friend inline VECTOR<T> MATH_PURE ceil(VECTOR<T> v) {
|
||||
for (size_t i = 0; i < v.size(); i++) {
|
||||
v[i] = std::ceil(v[i]);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
friend inline VECTOR<T> MATH_PURE round(VECTOR<T> v) {
|
||||
for (size_t i = 0; i < v.size(); i++) {
|
||||
v[i] = std::round(v[i]);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
friend inline VECTOR<T> MATH_PURE inversesqrt(VECTOR<T> v) {
|
||||
for (size_t i = 0; i < v.size(); i++) {
|
||||
v[i] = T(1) / std::sqrt(v[i]);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
friend inline VECTOR<T> MATH_PURE sqrt(VECTOR<T> v) {
|
||||
for (size_t i = 0; i < v.size(); i++) {
|
||||
v[i] = std::sqrt(v[i]);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
friend inline VECTOR<T> MATH_PURE cbrt(VECTOR<T> v) {
|
||||
for (size_t i = 0; i < v.size(); i++) {
|
||||
v[i] = std::cbrt(v[i]);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
friend inline VECTOR<T> MATH_PURE exp(VECTOR<T> v) {
|
||||
for (size_t i = 0; i < v.size(); i++) {
|
||||
v[i] = std::exp(v[i]);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
friend inline VECTOR<T> MATH_PURE pow(VECTOR<T> v, T p) {
|
||||
for (size_t i = 0; i < v.size(); i++) {
|
||||
v[i] = std::pow(v[i], p);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
friend inline VECTOR<T> MATH_PURE pow(T v, VECTOR<T> p) {
|
||||
for (size_t i = 0; i < p.size(); i++) {
|
||||
p[i] = std::pow(v, p[i]);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
friend inline VECTOR<T> MATH_PURE pow(VECTOR<T> v, VECTOR<T> p) {
|
||||
for (size_t i = 0; i < v.size(); i++) {
|
||||
v[i] = std::pow(v[i], p[i]);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
friend inline VECTOR<T> MATH_PURE log(VECTOR<T> v) {
|
||||
for (size_t i = 0; i < v.size(); i++) {
|
||||
v[i] = std::log(v[i]);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
friend inline VECTOR<T> MATH_PURE log10(VECTOR<T> v) {
|
||||
for (size_t i = 0; i < v.size(); i++) {
|
||||
v[i] = std::log10(v[i]);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
friend inline VECTOR<T> MATH_PURE log2(VECTOR<T> v) {
|
||||
for (size_t i = 0; i < v.size(); i++) {
|
||||
v[i] = std::log2(v[i]);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
friend inline constexpr VECTOR<T> MATH_PURE saturate(const VECTOR<T>& lv) {
|
||||
return clamp(lv, T(0), T(1));
|
||||
}
|
||||
|
||||
friend inline constexpr VECTOR<T> MATH_PURE clamp(VECTOR<T> v, T min, T max) {
|
||||
for (size_t i = 0; i < v.size(); i++) {
|
||||
v[i] = details::min(max, details::max(min, v[i]));
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
friend inline constexpr VECTOR<T> MATH_PURE clamp(VECTOR<T> v, VECTOR<T> min, VECTOR<T> max) {
|
||||
for (size_t i = 0; i < v.size(); i++) {
|
||||
v[i] = details::min(max[i], details::max(min[i], v[i]));
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
friend inline constexpr VECTOR<T> MATH_PURE fma(const VECTOR<T>& lv, const VECTOR<T>& rv,
|
||||
VECTOR<T> a) {
|
||||
for (size_t i = 0; i < lv.size(); i++) {
|
||||
a[i] += (lv[i] * rv[i]);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
friend inline constexpr VECTOR<T> MATH_PURE min(const VECTOR<T>& u, VECTOR<T> v) {
|
||||
for (size_t i = 0; i < v.size(); i++) {
|
||||
v[i] = details::min(u[i], v[i]);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
friend inline constexpr VECTOR<T> MATH_PURE max(const VECTOR<T>& u, VECTOR<T> v) {
|
||||
for (size_t i = 0; i < v.size(); i++) {
|
||||
v[i] = details::max(u[i], v[i]);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
friend inline constexpr T MATH_PURE max(const VECTOR<T>& v) {
|
||||
T r(v[0]);
|
||||
for (size_t i = 1; i < v.size(); i++) {
|
||||
r = max(r, v[i]);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
friend inline constexpr T MATH_PURE min(const VECTOR<T>& v) {
|
||||
T r(v[0]);
|
||||
for (size_t i = 1; i < v.size(); i++) {
|
||||
r = min(r, v[i]);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
friend inline constexpr VECTOR<T> MATH_PURE mix(const VECTOR<T>& u, VECTOR<T> v, T a) {
|
||||
for (size_t i = 0; i < v.size(); i++) {
|
||||
v[i] = u[i] * (T(1) - a) + v[i] * a;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
friend inline constexpr VECTOR<T> MATH_PURE smoothstep(T edge0, T edge1, VECTOR<T> v) {
|
||||
VECTOR<T> t = saturate((v - edge0) / (edge1 - edge0));
|
||||
return t * t * (T(3) - T(2) * t);
|
||||
}
|
||||
|
||||
friend inline constexpr VECTOR<T> MATH_PURE step(T edge, VECTOR<T> v) {
|
||||
for (size_t i = 0; i < v.size(); i++) {
|
||||
v[i] = v[i] < edge ? T(0) : T(1);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
friend inline constexpr VECTOR<T> MATH_PURE step(VECTOR<T> edge, VECTOR<T> v) {
|
||||
for (size_t i = 0; i < v.size(); i++) {
|
||||
v[i] = v[i] < edge[i] ? T(0) : T(1);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
friend inline constexpr bool MATH_PURE any(const VECTOR<T>& v) {
|
||||
for (size_t i = 0; i < v.size(); i++) {
|
||||
if (v[i] != T(0)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
friend inline constexpr bool MATH_PURE all(const VECTOR<T>& v) {
|
||||
bool result = true;
|
||||
for (size_t i = 0; i < v.size(); i++) {
|
||||
result &= (v[i] != T(0));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------------
|
||||
} // namespace details
|
||||
} // namespace math
|
||||
} // namespace filament
|
||||
|
||||
#endif // MATH_TVECHELPERS_H_
|
||||
126
ios/include/math/compiler.h
Normal file
126
ios/include/math/compiler.h
Normal file
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* 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 <type_traits>
|
||||
|
||||
#if defined (WIN32)
|
||||
|
||||
#ifdef max
|
||||
#undef max
|
||||
#endif
|
||||
|
||||
#ifdef min
|
||||
#undef min
|
||||
#endif
|
||||
|
||||
#ifdef far
|
||||
#undef far
|
||||
#endif
|
||||
|
||||
#ifdef near
|
||||
#undef near
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// compatibility with non-clang compilers...
|
||||
#ifndef __has_attribute
|
||||
#define __has_attribute(x) 0
|
||||
#endif
|
||||
#ifndef __has_builtin
|
||||
#define __has_builtin(x) 0
|
||||
#endif
|
||||
|
||||
#if __has_builtin(__builtin_expect)
|
||||
# ifdef __cplusplus
|
||||
# define MATH_LIKELY( exp ) (__builtin_expect( !!(exp), true ))
|
||||
# define MATH_UNLIKELY( exp ) (__builtin_expect( !!(exp), false ))
|
||||
# else
|
||||
# define MATH_LIKELY( exp ) (__builtin_expect( !!(exp), 1 ))
|
||||
# define MATH_UNLIKELY( exp ) (__builtin_expect( !!(exp), 0 ))
|
||||
# endif
|
||||
#else
|
||||
# define MATH_LIKELY( exp ) (exp)
|
||||
# define MATH_UNLIKELY( exp ) (exp)
|
||||
#endif
|
||||
|
||||
#if __has_attribute(unused)
|
||||
# define MATH_UNUSED __attribute__((unused))
|
||||
#else
|
||||
# define MATH_UNUSED
|
||||
#endif
|
||||
|
||||
#if __has_attribute(pure)
|
||||
# define MATH_PURE __attribute__((pure))
|
||||
#else
|
||||
# define MATH_PURE
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# define MATH_EMPTY_BASES __declspec(empty_bases)
|
||||
|
||||
// MSVC does not support loop unrolling hints
|
||||
# define MATH_NOUNROLL
|
||||
|
||||
// Sadly, MSVC does not support __builtin_constant_p
|
||||
# ifndef MAKE_CONSTEXPR
|
||||
# define MAKE_CONSTEXPR(e) (e)
|
||||
# endif
|
||||
|
||||
// About value initialization, the C++ standard says:
|
||||
// if T is a class type with a default constructor that is neither user-provided nor deleted
|
||||
// (that is, it may be a class with an implicitly-defined or defaulted default constructor),
|
||||
// the object is zero-initialized and then it is default-initialized
|
||||
// if it has a non-trivial default constructor;
|
||||
// Unfortunately, MSVC always calls the default constructor, even if it is trivial, which
|
||||
// breaks constexpr-ness. To workaround this, we're always zero-initializing TVecN<>
|
||||
# define MATH_CONSTEXPR_INIT {}
|
||||
# define MATH_DEFAULT_CTOR {}
|
||||
# define MATH_DEFAULT_CTOR_CONSTEXPR constexpr
|
||||
# define CONSTEXPR_IF_NOT_MSVC // when declared constexpr, msvc fails with "failure was caused by cast of object of dynamic type"
|
||||
|
||||
#else // _MSC_VER
|
||||
|
||||
# define MATH_EMPTY_BASES
|
||||
// C++11 allows pragmas to be specified as part of defines using the _Pragma syntax.
|
||||
# define MATH_NOUNROLL _Pragma("nounroll")
|
||||
|
||||
# ifndef MAKE_CONSTEXPR
|
||||
# define MAKE_CONSTEXPR(e) __builtin_constant_p(e) ? (e) : (e)
|
||||
# endif
|
||||
|
||||
# define MATH_CONSTEXPR_INIT
|
||||
# define MATH_DEFAULT_CTOR = default;
|
||||
# define MATH_DEFAULT_CTOR_CONSTEXPR
|
||||
# define CONSTEXPR_IF_NOT_MSVC constexpr
|
||||
|
||||
#endif // _MSC_VER
|
||||
|
||||
namespace filament {
|
||||
namespace math {
|
||||
|
||||
// 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
|
||||
// inside of half.h.
|
||||
template<typename T>
|
||||
struct is_arithmetic : std::integral_constant<bool,
|
||||
std::is_integral<T>::value || std::is_floating_point<T>::value> {
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
174
ios/include/math/fast.h
Normal file
174
ios/include/math/fast.h
Normal file
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* 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_MATH_FAST_H
|
||||
#define TNT_MATH_FAST_H
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
|
||||
#include <math/compiler.h>
|
||||
#include <math/scalar.h>
|
||||
|
||||
#ifdef __ARM_NEON
|
||||
#include <arm_neon.h>
|
||||
#endif
|
||||
|
||||
namespace filament {
|
||||
namespace math {
|
||||
namespace fast {
|
||||
|
||||
// fast cos(x), ~8 cycles (vs. 66 cycles on ARM)
|
||||
// can be vectorized
|
||||
// x between -pi and pi
|
||||
template<typename T, typename = std::enable_if_t<std::is_floating_point<T>::value>>
|
||||
constexpr T MATH_PURE cos(T x) noexcept {
|
||||
x *= T(F_1_PI / 2);
|
||||
x -= T(0.25) + std::floor(x + T(0.25));
|
||||
x *= T(16.0) * std::abs(x) - T(8.0);
|
||||
x += T(0.225) * x * (std::abs(x) - T(1.0));
|
||||
return x;
|
||||
}
|
||||
|
||||
// fast sin(x), ~8 cycles (vs. 66 cycles on ARM)
|
||||
// can be vectorized
|
||||
// x between -pi and pi
|
||||
template<typename T, typename = std::enable_if_t<std::is_floating_point<T>::value>>
|
||||
constexpr T MATH_PURE sin(T x) noexcept {
|
||||
return filament::math::fast::cos<T>(x - T(F_PI_2));
|
||||
}
|
||||
|
||||
constexpr inline float MATH_PURE ilog2(float x) noexcept {
|
||||
union {
|
||||
float val;
|
||||
int32_t x;
|
||||
} u = { x };
|
||||
return float(((u.x >> 23) & 0xff) - 127);
|
||||
}
|
||||
|
||||
constexpr inline float MATH_PURE log2(float x) noexcept {
|
||||
union {
|
||||
float val;
|
||||
int32_t x;
|
||||
} u = { x };
|
||||
float ilog2 = float(((u.x >> 23) & 0xff) - 128);
|
||||
u.x = (u.x & 0x007fffff) | 0x3f800000;
|
||||
return ilog2 + (-0.34484843f * u.val + 2.02466578f) * u.val - 0.67487759f;
|
||||
}
|
||||
|
||||
// fast 1/sqrt(), on ARMv8 this is 5 cycles vs. 7 cycles, so maybe not worth it.
|
||||
// we keep this mostly for reference and benchmarking.
|
||||
inline float MATH_PURE isqrt(float x) noexcept {
|
||||
#if defined(__ARM_NEON) && defined(__aarch64__)
|
||||
float y = vrsqrtes_f32(x);
|
||||
return y * vrsqrtss_f32(x, y * y);
|
||||
#else
|
||||
return 1 / std::sqrt(x);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline double MATH_PURE isqrt(double x) noexcept {
|
||||
#if defined(__ARM_NEON) && defined(__aarch64__)
|
||||
double y = vrsqrted_f64(x);
|
||||
return y * vrsqrtsd_f64(x, y * y);
|
||||
#else
|
||||
return 1 / std::sqrt(x);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline int signbit(float x) noexcept {
|
||||
#if __has_builtin(__builtin_signbitf)
|
||||
// Note: on Android NDK, signbit() is a function call -- not what we want.
|
||||
return __builtin_signbitf(x);
|
||||
#else
|
||||
return std::signbit(x);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* constexpr exp(), pow(), factorial()
|
||||
*/
|
||||
|
||||
constexpr double pow(double x, unsigned int y) noexcept {
|
||||
return y == 0 ? 1.0 : x * pow(x, y - 1);
|
||||
}
|
||||
|
||||
constexpr unsigned int factorial(unsigned int x) noexcept {
|
||||
return x == 0 ? 1 : x * factorial(x - 1);
|
||||
}
|
||||
|
||||
constexpr double exp(double x) noexcept {
|
||||
return 1.0 + x + pow(x, 2) / factorial(2) + pow(x, 3) / factorial(3)
|
||||
+ pow(x, 4) / factorial(4) + pow(x, 5) / factorial(5)
|
||||
+ pow(x, 6) / factorial(6) + pow(x, 7) / factorial(7)
|
||||
+ pow(x, 8) / factorial(8) + pow(x, 9) / factorial(9);
|
||||
}
|
||||
|
||||
constexpr float exp(float x) noexcept {
|
||||
return float(exp(double(x)));
|
||||
}
|
||||
|
||||
/*
|
||||
* unsigned saturated arithmetic
|
||||
*/
|
||||
|
||||
#if defined(__ARM_NEON) && defined(__aarch64__)
|
||||
inline uint8_t MATH_PURE qadd(uint8_t a, uint8_t b) noexcept { return vuqaddb_s8(a, b); }
|
||||
inline uint16_t MATH_PURE qadd(uint16_t a, uint16_t b) noexcept { return vuqaddh_s16(a, b); }
|
||||
inline uint32_t MATH_PURE qadd(uint32_t a, uint32_t b) noexcept { return vuqadds_s32(a, b); }
|
||||
|
||||
inline uint8_t MATH_PURE qsub(uint8_t a, uint8_t b) noexcept { return vqsubb_s8(a, b); }
|
||||
inline uint16_t MATH_PURE qsub(uint16_t a, uint16_t b) noexcept { return vqsubh_s16(a, b); }
|
||||
inline uint32_t MATH_PURE qsub(uint32_t a, uint32_t b) noexcept { return vqsubs_s32(a, b); }
|
||||
#else
|
||||
|
||||
template<typename T, typename = std::enable_if_t<
|
||||
std::is_same<uint8_t, T>::value ||
|
||||
std::is_same<uint16_t, T>::value ||
|
||||
std::is_same<uint32_t, T>::value>>
|
||||
inline T MATH_PURE qadd(T a, T b) noexcept {
|
||||
T r = a + b;
|
||||
return r | -T(r < a);
|
||||
}
|
||||
|
||||
template<typename T, typename = std::enable_if_t<
|
||||
std::is_same<uint8_t, T>::value ||
|
||||
std::is_same<uint16_t, T>::value ||
|
||||
std::is_same<uint32_t, T>::value>>
|
||||
inline T MATH_PURE qsub(T a, T b) noexcept {
|
||||
T r = a - b;
|
||||
return r & -T(r <= a);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
inline T MATH_PURE qinc(T a) noexcept {
|
||||
return qadd(a, T(1));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T MATH_PURE qdec(T a) noexcept {
|
||||
return qsub(a, T(1));
|
||||
}
|
||||
|
||||
|
||||
} // namespace fast
|
||||
} // namespace math
|
||||
} // namespace filament
|
||||
|
||||
#endif // TNT_MATH_FAST_H
|
||||
224
ios/include/math/half.h
Normal file
224
ios/include/math/half.h
Normal file
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
* 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_MATH_HALF_H
|
||||
#define TNT_MATH_HALF_H
|
||||
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <math/compiler.h>
|
||||
|
||||
namespace filament {
|
||||
namespace math {
|
||||
|
||||
template<unsigned S, unsigned E, unsigned M>
|
||||
class fp {
|
||||
static_assert(S + E + M <= 16, "we only support 16-bits max custom floats");
|
||||
|
||||
using TYPE = uint16_t; // this should be dynamic
|
||||
|
||||
static constexpr unsigned S_SHIFT = E + M;
|
||||
static constexpr unsigned E_SHIFT = M;
|
||||
static constexpr unsigned M_SHIFT = 0;
|
||||
static constexpr unsigned S_MASK = ((1u << S) - 1u) << S_SHIFT;
|
||||
static constexpr unsigned E_MASK = ((1u << E) - 1u) << E_SHIFT;
|
||||
static constexpr unsigned M_MASK = ((1u << M) - 1u) << M_SHIFT;
|
||||
|
||||
struct fp32 {
|
||||
explicit constexpr fp32(float f) noexcept : fp(f) { } // NOLINT
|
||||
explicit constexpr fp32(uint32_t b) noexcept : bits(b) { } // NOLINT
|
||||
constexpr void setS(unsigned int s) noexcept {
|
||||
bits = uint32_t((bits & 0x7FFFFFFFu) | (s << 31u));
|
||||
}
|
||||
constexpr unsigned int getS() const noexcept { return bits >> 31u; }
|
||||
constexpr unsigned int getE() const noexcept { return (bits >> 23u) & 0xFFu; }
|
||||
constexpr unsigned int getM() const noexcept { return bits & 0x7FFFFFu; }
|
||||
union {
|
||||
uint32_t bits;
|
||||
float fp;
|
||||
};
|
||||
};
|
||||
|
||||
public:
|
||||
static constexpr fp fromf(float f) noexcept {
|
||||
fp out;
|
||||
if (S == 0 && f < 0.0f) {
|
||||
return out;
|
||||
}
|
||||
|
||||
fp32 in(f);
|
||||
unsigned int sign = in.getS();
|
||||
in.setS(0);
|
||||
if (MATH_UNLIKELY(in.getE() == 0xFF)) { // inf or nan
|
||||
out.setE((1u << E) - 1u);
|
||||
out.setM(in.getM() ? (1u << (M - 1u)) : 0);
|
||||
} else {
|
||||
constexpr fp32 infinity(((1u << E) - 1u) << 23u); // fp infinity in fp32 position
|
||||
constexpr fp32 magic(((1u << (E - 1u)) - 1u) << 23u); // exponent offset
|
||||
in.bits &= ~((1u << (22 - M)) - 1u); // erase extra mantissa bits
|
||||
in.bits += 1u << (22 - M); // rounding
|
||||
in.fp *= magic.fp; // add exponent offset
|
||||
in.bits = in.bits < infinity.bits ? in.bits : infinity.bits;
|
||||
out.bits = uint16_t(in.bits >> (23 - M));
|
||||
}
|
||||
out.setS(sign);
|
||||
return out;
|
||||
}
|
||||
|
||||
static constexpr float tof(fp in) noexcept {
|
||||
constexpr fp32 magic ((0xFE - ((1u << (E - 1u)) - 1u)) << 23u);
|
||||
constexpr fp32 infnan((0x80 + ((1u << (E - 1u)) - 1u)) << 23u);
|
||||
fp32 out((in.bits & ((1u << (E + M)) - 1u)) << (23u - M));
|
||||
out.fp *= magic.fp;
|
||||
if (out.fp >= infnan.fp) {
|
||||
out.bits |= 0xFFu << 23u;
|
||||
}
|
||||
out.bits |= (in.bits & S_MASK) << (31u - S_SHIFT);
|
||||
return out.fp;
|
||||
}
|
||||
|
||||
TYPE bits{};
|
||||
static constexpr size_t getBitCount() noexcept { return S + E + M; }
|
||||
constexpr fp() noexcept = default;
|
||||
explicit constexpr fp(TYPE bits) noexcept : bits(bits) { }
|
||||
constexpr void setS(unsigned int s) noexcept { bits = TYPE((bits & ~S_MASK) | (s << S_SHIFT)); }
|
||||
constexpr void setE(unsigned int s) noexcept { bits = TYPE((bits & ~E_MASK) | (s << E_SHIFT)); }
|
||||
constexpr void setM(unsigned int s) noexcept { bits = TYPE((bits & ~M_MASK) | (s << M_SHIFT)); }
|
||||
constexpr unsigned int getS() const noexcept { return (bits & S_MASK) >> S_SHIFT; }
|
||||
constexpr unsigned int getE() const noexcept { return (bits & E_MASK) >> E_SHIFT; }
|
||||
constexpr unsigned int getM() const noexcept { return (bits & M_MASK) >> M_SHIFT; }
|
||||
};
|
||||
|
||||
/*
|
||||
* half-float
|
||||
*
|
||||
* 1 5 10
|
||||
* +-+------+------------+
|
||||
* |s|eee.ee|mm.mmmm.mmmm|
|
||||
* +-+------+------------+
|
||||
*
|
||||
* minimum (denormal) value: 2^-24 = 5.96e-8
|
||||
* minimum (normal) value: 2^-14 = 6.10e-5
|
||||
* maximum value: (2 - 2^-10) * 2^15 = 65504
|
||||
*
|
||||
* Integers between 0 and 2048 can be represented exactly
|
||||
*/
|
||||
|
||||
#ifdef __ARM_NEON
|
||||
|
||||
using half = __fp16;
|
||||
|
||||
inline constexpr uint16_t getBits(half const& h) noexcept {
|
||||
return MAKE_CONSTEXPR(reinterpret_cast<uint16_t const&>(h));
|
||||
}
|
||||
|
||||
inline constexpr half makeHalf(uint16_t bits) noexcept {
|
||||
return MAKE_CONSTEXPR(reinterpret_cast<half const&>(bits));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
class half {
|
||||
using fp16 = fp<1, 5, 10>;
|
||||
|
||||
public:
|
||||
half() = default;
|
||||
constexpr half(float v) noexcept : mBits(fp16::fromf(v)) { } // NOLINT
|
||||
constexpr operator float() const noexcept { return fp16::tof(mBits); } // NOLINT
|
||||
|
||||
private:
|
||||
// these are friends, not members (and they're not "private")
|
||||
friend constexpr uint16_t getBits(half const& h) noexcept { return h.mBits.bits; }
|
||||
friend constexpr inline half makeHalf(uint16_t bits) noexcept;
|
||||
|
||||
enum Binary { binary };
|
||||
explicit constexpr half(Binary, uint16_t bits) noexcept : mBits(bits) { }
|
||||
|
||||
fp16 mBits;
|
||||
};
|
||||
|
||||
constexpr inline half makeHalf(uint16_t bits) noexcept {
|
||||
return half(half::binary, bits);
|
||||
}
|
||||
|
||||
#endif // __ARM_NEON
|
||||
|
||||
inline constexpr half operator "" _h(long double v) {
|
||||
return half( static_cast<float>(v) );
|
||||
}
|
||||
|
||||
template<> struct is_arithmetic<filament::math::half> : public std::true_type {};
|
||||
|
||||
} // namespace math
|
||||
} // namespace filament
|
||||
|
||||
namespace std {
|
||||
|
||||
template<> struct is_floating_point<filament::math::half> : public std::true_type {};
|
||||
|
||||
// note: this shouldn't be needed (is_floating_point<> is enough) but some version of msvc need it
|
||||
// This stopped working with MSVC 2019 16.4, so we specialize our own version of is_arithmetic in
|
||||
// the math::filament namespace (see above).
|
||||
template<> struct is_arithmetic<filament::math::half> : public std::true_type {};
|
||||
|
||||
template<>
|
||||
class numeric_limits<filament::math::half> {
|
||||
public:
|
||||
typedef filament::math::half type;
|
||||
|
||||
static constexpr const bool is_specialized = true;
|
||||
static constexpr const bool is_signed = true;
|
||||
static constexpr const bool is_integer = false;
|
||||
static constexpr const bool is_exact = false;
|
||||
static constexpr const bool has_infinity = true;
|
||||
static constexpr const bool has_quiet_NaN = true;
|
||||
static constexpr const bool has_signaling_NaN = false;
|
||||
static constexpr const float_denorm_style has_denorm = denorm_absent;
|
||||
static constexpr const bool has_denorm_loss = true;
|
||||
static constexpr const bool is_iec559 = false;
|
||||
static constexpr const bool is_bounded = true;
|
||||
static constexpr const bool is_modulo = false;
|
||||
static constexpr const bool traps = false;
|
||||
static constexpr const bool tinyness_before = false;
|
||||
static constexpr const float_round_style round_style = round_indeterminate;
|
||||
|
||||
static constexpr const int digits = 11;
|
||||
static constexpr const int digits10 = 3;
|
||||
static constexpr const int max_digits10 = 5;
|
||||
static constexpr const int radix = 2;
|
||||
static constexpr const int min_exponent = -13;
|
||||
static constexpr const int min_exponent10 = -4;
|
||||
static constexpr const int max_exponent = 16;
|
||||
static constexpr const int max_exponent10 = 4;
|
||||
|
||||
inline static constexpr type round_error() noexcept { return filament::math::makeHalf(0x3800); }
|
||||
inline static constexpr type min() noexcept { return filament::math::makeHalf(0x0400); }
|
||||
inline static constexpr type max() noexcept { return filament::math::makeHalf(0x7bff); }
|
||||
inline static constexpr type lowest() noexcept { return filament::math::makeHalf(0xfbff); }
|
||||
inline static constexpr type epsilon() noexcept { return filament::math::makeHalf(0x1400); }
|
||||
inline static constexpr type infinity() noexcept { return filament::math::makeHalf(0x7c00); }
|
||||
inline static constexpr type quiet_NaN() noexcept { return filament::math::makeHalf(0x7fff); }
|
||||
inline static constexpr type denorm_min() noexcept { return filament::math::makeHalf(0x0001); }
|
||||
inline static constexpr type signaling_NaN() noexcept { return filament::math::makeHalf(0x7dff); }
|
||||
};
|
||||
|
||||
} // namespace std
|
||||
|
||||
#endif // TNT_MATH_HALF_H
|
||||
361
ios/include/math/mat2.h
Normal file
361
ios/include/math/mat2.h
Normal file
@@ -0,0 +1,361 @@
|
||||
/*
|
||||
* Copyright 2013 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 MATH_MAT2_H_
|
||||
#define MATH_MAT2_H_
|
||||
|
||||
#include <math/TMatHelpers.h>
|
||||
#include <math/vec2.h>
|
||||
#include <math/compiler.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
namespace filament {
|
||||
namespace math {
|
||||
// -------------------------------------------------------------------------------------
|
||||
namespace details {
|
||||
|
||||
/**
|
||||
* A 2x2 column-major matrix class.
|
||||
*
|
||||
* Conceptually a 2x2 matrix is a an array of 2 column vec2:
|
||||
*
|
||||
* mat2 m =
|
||||
* \f$
|
||||
* \left(
|
||||
* \begin{array}{cc}
|
||||
* m[0] & m[1] \\
|
||||
* \end{array}
|
||||
* \right)
|
||||
* \f$
|
||||
* =
|
||||
* \f$
|
||||
* \left(
|
||||
* \begin{array}{cc}
|
||||
* m[0][0] & m[1][0] \\
|
||||
* m[0][1] & m[1][1] \\
|
||||
* \end{array}
|
||||
* \right)
|
||||
* \f$
|
||||
* =
|
||||
* \f$
|
||||
* \left(
|
||||
* \begin{array}{cc}
|
||||
* m(0,0) & m(0,1) \\
|
||||
* m(1,0) & m(1,1) \\
|
||||
* \end{array}
|
||||
* \right)
|
||||
* \f$
|
||||
*
|
||||
* m[n] is the \f$ n^{th} \f$ column of the matrix and is a vec2.
|
||||
*
|
||||
*/
|
||||
template<typename T>
|
||||
class MATH_EMPTY_BASES TMat22 :
|
||||
public TVecUnaryOperators<TMat22, T>,
|
||||
public TVecComparisonOperators<TMat22, T>,
|
||||
public TVecAddOperators<TMat22, T>,
|
||||
public TMatProductOperators<TMat22, T, TVec2>,
|
||||
public TMatSquareFunctions<TMat22, T>,
|
||||
public TMatHelpers<TMat22, T> {
|
||||
public:
|
||||
enum no_init {
|
||||
NO_INIT
|
||||
};
|
||||
typedef T value_type;
|
||||
typedef T& reference;
|
||||
typedef T const& const_reference;
|
||||
typedef size_t size_type;
|
||||
typedef TVec2<T> col_type;
|
||||
typedef TVec2<T> row_type;
|
||||
|
||||
static constexpr size_t COL_SIZE = col_type::SIZE; // size of a column (i.e.: number of rows)
|
||||
static constexpr size_t ROW_SIZE = row_type::SIZE; // size of a row (i.e.: number of columns)
|
||||
static constexpr size_t NUM_ROWS = COL_SIZE;
|
||||
static constexpr size_t NUM_COLS = ROW_SIZE;
|
||||
|
||||
private:
|
||||
/*
|
||||
* <-- N columns -->
|
||||
*
|
||||
* a[0][0] a[1][0] a[2][0] ... a[N][0] ^
|
||||
* a[0][1] a[1][1] a[2][1] ... a[N][1] |
|
||||
* a[0][2] a[1][2] a[2][2] ... a[N][2] M rows
|
||||
* ... |
|
||||
* a[0][M] a[1][M] a[2][M] ... a[N][M] v
|
||||
*
|
||||
* COL_SIZE = M
|
||||
* ROW_SIZE = N
|
||||
* m[0] = [ a[0][0] a[0][1] a[0][2] ... a[0][M] ]
|
||||
*/
|
||||
|
||||
col_type m_value[NUM_COLS];
|
||||
|
||||
public:
|
||||
// array access
|
||||
inline constexpr col_type const& operator[](size_t column) const noexcept {
|
||||
assert(column < NUM_COLS);
|
||||
return m_value[column];
|
||||
}
|
||||
|
||||
inline constexpr col_type& operator[](size_t column) noexcept {
|
||||
assert(column < NUM_COLS);
|
||||
return m_value[column];
|
||||
}
|
||||
|
||||
/**
|
||||
* constructors
|
||||
*/
|
||||
|
||||
/**
|
||||
* leaves object uninitialized. use with caution.
|
||||
*/
|
||||
constexpr explicit TMat22(no_init) noexcept {}
|
||||
|
||||
|
||||
/**
|
||||
* initialize to identity.
|
||||
*
|
||||
* \f$
|
||||
* \left(
|
||||
* \begin{array}{cc}
|
||||
* 1 & 0 \\
|
||||
* 0 & 1 \\
|
||||
* \end{array}
|
||||
* \right)
|
||||
* \f$
|
||||
*/
|
||||
constexpr TMat22() noexcept ;
|
||||
|
||||
/**
|
||||
* initialize to Identity*scalar.
|
||||
*
|
||||
* \f$
|
||||
* \left(
|
||||
* \begin{array}{cc}
|
||||
* v & 0 \\
|
||||
* 0 & v \\
|
||||
* \end{array}
|
||||
* \right)
|
||||
* \f$
|
||||
*/
|
||||
template<typename U>
|
||||
constexpr explicit TMat22(U v) noexcept;
|
||||
|
||||
/**
|
||||
* sets the diagonal to a vector.
|
||||
*
|
||||
* \f$
|
||||
* \left(
|
||||
* \begin{array}{cc}
|
||||
* v[0] & 0 \\
|
||||
* 0 & v[1] \\
|
||||
* \end{array}
|
||||
* \right)
|
||||
* \f$
|
||||
*/
|
||||
template<typename U>
|
||||
constexpr explicit TMat22(const TVec2<U>& v) noexcept;
|
||||
|
||||
/**
|
||||
* construct from another matrix of the same size
|
||||
*/
|
||||
template<typename U>
|
||||
constexpr explicit TMat22(const TMat22<U>& rhs) noexcept;
|
||||
|
||||
/**
|
||||
* construct from 2 column vectors.
|
||||
*
|
||||
* \f$
|
||||
* \left(
|
||||
* \begin{array}{cc}
|
||||
* v0 & v1 \\
|
||||
* \end{array}
|
||||
* \right)
|
||||
* \f$
|
||||
*/
|
||||
template<typename A, typename B>
|
||||
constexpr TMat22(const TVec2<A>& v0, const TVec2<B>& v1) noexcept;
|
||||
|
||||
/** construct from 4 elements in column-major form.
|
||||
*
|
||||
* \f$
|
||||
* \left(
|
||||
* \begin{array}{cc}
|
||||
* m[0][0] & m[1][0] \\
|
||||
* m[0][1] & m[1][1] \\
|
||||
* \end{array}
|
||||
* \right)
|
||||
* \f$
|
||||
*/
|
||||
template<
|
||||
typename A, typename B,
|
||||
typename C, typename D>
|
||||
constexpr explicit TMat22(A m00, B m01, C m10, D m11) noexcept ;
|
||||
|
||||
|
||||
struct row_major_init {
|
||||
template<typename A, typename B,
|
||||
typename C, typename D>
|
||||
constexpr explicit row_major_init(A m00, B m01, C m10, D m11) noexcept
|
||||
: m(m00, m10, m01, m11) {}
|
||||
|
||||
private:
|
||||
friend TMat22;
|
||||
TMat22 m;
|
||||
};
|
||||
|
||||
constexpr explicit TMat22(row_major_init c) noexcept : TMat22(std::move(c.m)) {}
|
||||
|
||||
/**
|
||||
* Rotate by radians in the 2D plane
|
||||
*/
|
||||
static TMat22<T> rotate(T radian) noexcept {
|
||||
TMat22<T> r(TMat22<T>::NO_INIT);
|
||||
T c = std::cos(radian);
|
||||
T s = std::sin(radian);
|
||||
r[0][0] = c;
|
||||
r[1][1] = c;
|
||||
r[0][1] = s;
|
||||
r[1][0] = -s;
|
||||
return r;
|
||||
}
|
||||
|
||||
// returns false if the two matrices are different. May return false if they're the
|
||||
// same, with some elements only differing by +0 or -0. Behaviour is undefined with NaNs.
|
||||
static constexpr bool fuzzyEqual(TMat22 l, TMat22 r) noexcept {
|
||||
uint64_t const* const li = reinterpret_cast<uint64_t const*>(&l);
|
||||
uint64_t const* const ri = reinterpret_cast<uint64_t const*>(&r);
|
||||
uint64_t result = 0;
|
||||
// For some reason clang is not able to vectoize this loop when the number of iteration
|
||||
// is known and constant (!?!?!). Still this is better than operator==.
|
||||
#pragma clang loop vectorize_width(2)
|
||||
for (size_t i = 0; i < sizeof(TMat22) / sizeof(uint64_t); i++) {
|
||||
result |= li[i] ^ ri[i];
|
||||
}
|
||||
return result != 0;
|
||||
}
|
||||
|
||||
template<typename A>
|
||||
static constexpr TMat22 translation(const TVec2<A>& t) noexcept {
|
||||
TMat22 r;
|
||||
r[2] = t;
|
||||
return r;
|
||||
}
|
||||
|
||||
template<typename A>
|
||||
static constexpr TMat22 scaling(const TVec2<A>& s) noexcept {
|
||||
return TMat22{ s };
|
||||
}
|
||||
|
||||
template<typename A>
|
||||
static constexpr TMat22 scaling(A s) noexcept {
|
||||
return TMat22{ TVec2<T>{ s, s }};
|
||||
}
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// Constructors
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
// Since the matrix code could become pretty big quickly, we don't inline most
|
||||
// operations.
|
||||
|
||||
template<typename T>
|
||||
constexpr TMat22<T>::TMat22() noexcept
|
||||
: m_value{ col_type(1, 0), col_type(0, 1) } {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
constexpr TMat22<T>::TMat22(U v) noexcept
|
||||
: m_value{ col_type(v, 0), col_type(0, v) } {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
constexpr TMat22<T>::TMat22(const TVec2<U>& v) noexcept
|
||||
: m_value{ col_type(v[0], 0), col_type(0, v[1]) } {
|
||||
}
|
||||
|
||||
// construct from 4 scalars. Note that the arrangement
|
||||
// of values in the constructor is the transpose of the matrix
|
||||
// notation.
|
||||
template<typename T>
|
||||
template<typename A, typename B,
|
||||
typename C, typename D>
|
||||
constexpr TMat22<T>::TMat22(A m00, B m01, C m10, D m11) noexcept
|
||||
: m_value{ col_type(m00, m01), col_type(m10, m11) } {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
constexpr TMat22<T>::TMat22(const TMat22<U>& rhs) noexcept {
|
||||
for (size_t col = 0; col < NUM_COLS; ++col) {
|
||||
m_value[col] = col_type(rhs[col]);
|
||||
}
|
||||
}
|
||||
|
||||
// Construct from 2 column vectors.
|
||||
template<typename T>
|
||||
template<typename A, typename B>
|
||||
constexpr TMat22<T>::TMat22(const TVec2<A>& v0, const TVec2<B>& v1) noexcept
|
||||
: m_value{ v0, v1 } {
|
||||
}
|
||||
|
||||
} // namespace details
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
typedef details::TMat22<double> mat2;
|
||||
typedef details::TMat22<float> mat2f;
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
} // namespace math
|
||||
} // namespace filament
|
||||
|
||||
namespace std {
|
||||
template<typename T>
|
||||
constexpr void swap(filament::math::details::TMat22<T>& lhs,
|
||||
filament::math::details::TMat22<T>& rhs) noexcept {
|
||||
// This generates much better code than the default implementation
|
||||
// It's unclear why, I believe this is due to an optimization bug in the clang.
|
||||
//
|
||||
// filament::math::details::TMat22<T> t(lhs);
|
||||
// lhs = rhs;
|
||||
// rhs = t;
|
||||
//
|
||||
// clang always copy lhs on the stack, even if it's never using it (it's using the
|
||||
// copy it has in registers).
|
||||
|
||||
const T t00 = lhs[0][0];
|
||||
const T t01 = lhs[0][1];
|
||||
const T t10 = lhs[1][0];
|
||||
const T t11 = lhs[1][1];
|
||||
|
||||
lhs[0][0] = rhs[0][0];
|
||||
lhs[0][1] = rhs[0][1];
|
||||
lhs[1][0] = rhs[1][0];
|
||||
lhs[1][1] = rhs[1][1];
|
||||
|
||||
rhs[0][0] = t00;
|
||||
rhs[0][1] = t01;
|
||||
rhs[1][0] = t10;
|
||||
rhs[1][1] = t11;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // MATH_MAT2_H_
|
||||
490
ios/include/math/mat3.h
Normal file
490
ios/include/math/mat3.h
Normal file
@@ -0,0 +1,490 @@
|
||||
/*
|
||||
* Copyright 2013 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 MATH_MAT3_H_
|
||||
#define MATH_MAT3_H_
|
||||
|
||||
#include <math/quat.h>
|
||||
#include <math/TMatHelpers.h>
|
||||
#include <math/vec3.h>
|
||||
#include <math/compiler.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
namespace filament {
|
||||
namespace math {
|
||||
// -------------------------------------------------------------------------------------
|
||||
namespace details {
|
||||
|
||||
/**
|
||||
* A 3x3 column-major matrix class.
|
||||
*
|
||||
* Conceptually a 3x3 matrix is a an array of 3 column vec3:
|
||||
*
|
||||
* mat3 m =
|
||||
* \f$
|
||||
* \left(
|
||||
* \begin{array}{ccc}
|
||||
* m[0] & m[1] & m[2] \\
|
||||
* \end{array}
|
||||
* \right)
|
||||
* \f$
|
||||
* =
|
||||
* \f$
|
||||
* \left(
|
||||
* \begin{array}{ccc}
|
||||
* m[0][0] & m[1][0] & m[2][0] \\
|
||||
* m[0][1] & m[1][1] & m[2][1] \\
|
||||
* m[0][2] & m[1][2] & m[2][2] \\
|
||||
* \end{array}
|
||||
* \right)
|
||||
* \f$
|
||||
* =
|
||||
* \f$
|
||||
* \left(
|
||||
* \begin{array}{ccc}
|
||||
* m(0,0) & m(0,1) & m(0,2) \\
|
||||
* m(1,0) & m(1,1) & m(1,2) \\
|
||||
* m(2,0) & m(2,1) & m(2,2) \\
|
||||
* \end{array}
|
||||
* \right)
|
||||
* \f$
|
||||
*
|
||||
* m[n] is the \f$ n^{th} \f$ column of the matrix and is a vec3.
|
||||
*
|
||||
*/
|
||||
template<typename T>
|
||||
class MATH_EMPTY_BASES TMat33 :
|
||||
public TVecUnaryOperators<TMat33, T>,
|
||||
public TVecComparisonOperators<TMat33, T>,
|
||||
public TVecAddOperators<TMat33, T>,
|
||||
public TMatProductOperators<TMat33, T, TVec3>,
|
||||
public TMatSquareFunctions<TMat33, T>,
|
||||
public TMatTransform<TMat33, T>,
|
||||
public TMatHelpers<TMat33, T> {
|
||||
public:
|
||||
enum no_init {
|
||||
NO_INIT
|
||||
};
|
||||
typedef T value_type;
|
||||
typedef T& reference;
|
||||
typedef T const& const_reference;
|
||||
typedef size_t size_type;
|
||||
typedef TVec3<T> col_type;
|
||||
typedef TVec3<T> row_type;
|
||||
|
||||
static constexpr size_t COL_SIZE = col_type::SIZE; // size of a column (i.e.: number of rows)
|
||||
static constexpr size_t ROW_SIZE = row_type::SIZE; // size of a row (i.e.: number of columns)
|
||||
static constexpr size_t NUM_ROWS = COL_SIZE;
|
||||
static constexpr size_t NUM_COLS = ROW_SIZE;
|
||||
|
||||
private:
|
||||
/*
|
||||
* <-- N columns -->
|
||||
*
|
||||
* a[0][0] a[1][0] a[2][0] ... a[N][0] ^
|
||||
* a[0][1] a[1][1] a[2][1] ... a[N][1] |
|
||||
* a[0][2] a[1][2] a[2][2] ... a[N][2] M rows
|
||||
* ... |
|
||||
* a[0][M] a[1][M] a[2][M] ... a[N][M] v
|
||||
*
|
||||
* COL_SIZE = M
|
||||
* ROW_SIZE = N
|
||||
* m[0] = [ a[0][0] a[0][1] a[0][2] ... a[0][M] ]
|
||||
*/
|
||||
|
||||
col_type m_value[NUM_COLS];
|
||||
|
||||
public:
|
||||
// array access
|
||||
inline constexpr col_type const& operator[](size_t column) const noexcept {
|
||||
assert(column < NUM_COLS);
|
||||
return m_value[column];
|
||||
}
|
||||
|
||||
inline constexpr col_type& operator[](size_t column) noexcept {
|
||||
assert(column < NUM_COLS);
|
||||
return m_value[column];
|
||||
}
|
||||
|
||||
/**
|
||||
* constructors
|
||||
*/
|
||||
|
||||
/**
|
||||
* leaves object uninitialized. use with caution.
|
||||
*/
|
||||
constexpr explicit TMat33(no_init) noexcept {}
|
||||
|
||||
|
||||
/**
|
||||
* initialize to identity.
|
||||
*
|
||||
* \f$
|
||||
* \left(
|
||||
* \begin{array}{ccc}
|
||||
* 1 & 0 & 0 \\
|
||||
* 0 & 1 & 0 \\
|
||||
* 0 & 0 & 1 \\
|
||||
* \end{array}
|
||||
* \right)
|
||||
* \f$
|
||||
*/
|
||||
constexpr TMat33() noexcept;
|
||||
|
||||
/**
|
||||
* initialize to Identity*scalar.
|
||||
*
|
||||
* \f$
|
||||
* \left(
|
||||
* \begin{array}{ccc}
|
||||
* v & 0 & 0 \\
|
||||
* 0 & v & 0 \\
|
||||
* 0 & 0 & v \\
|
||||
* \end{array}
|
||||
* \right)
|
||||
* \f$
|
||||
*/
|
||||
template<typename U>
|
||||
constexpr explicit TMat33(U v) noexcept;
|
||||
|
||||
/**
|
||||
* sets the diagonal to a vector.
|
||||
*
|
||||
* \f$
|
||||
* \left(
|
||||
* \begin{array}{ccc}
|
||||
* v[0] & 0 & 0 \\
|
||||
* 0 & v[1] & 0 \\
|
||||
* 0 & 0 & v[2] \\
|
||||
* \end{array}
|
||||
* \right)
|
||||
* \f$
|
||||
*/
|
||||
template<typename U>
|
||||
constexpr explicit TMat33(const TVec3<U>& v) noexcept;
|
||||
|
||||
/**
|
||||
* construct from another matrix of the same size
|
||||
*/
|
||||
template<typename U>
|
||||
constexpr explicit TMat33(const TMat33<U>& rhs) noexcept;
|
||||
|
||||
/**
|
||||
* construct from 3 column vectors.
|
||||
*
|
||||
* \f$
|
||||
* \left(
|
||||
* \begin{array}{ccc}
|
||||
* v0 & v1 & v2 \\
|
||||
* \end{array}
|
||||
* \right)
|
||||
* \f$
|
||||
*/
|
||||
template<typename A, typename B, typename C>
|
||||
constexpr TMat33(const TVec3<A>& v0, const TVec3<B>& v1, const TVec3<C>& v2) noexcept;
|
||||
|
||||
/** construct from 9 elements in column-major form.
|
||||
*
|
||||
* \f$
|
||||
* \left(
|
||||
* \begin{array}{ccc}
|
||||
* m[0][0] & m[1][0] & m[2][0] \\
|
||||
* m[0][1] & m[1][1] & m[2][1] \\
|
||||
* m[0][2] & m[1][2] & m[2][2] \\
|
||||
* \end{array}
|
||||
* \right)
|
||||
* \f$
|
||||
*/
|
||||
template<
|
||||
typename A, typename B, typename C,
|
||||
typename D, typename E, typename F,
|
||||
typename G, typename H, typename I>
|
||||
constexpr explicit TMat33(A m00, B m01, C m02,
|
||||
D m10, E m11, F m12,
|
||||
G m20, H m21, I m22) noexcept;
|
||||
|
||||
|
||||
struct row_major_init {
|
||||
template<
|
||||
typename A, typename B, typename C,
|
||||
typename D, typename E, typename F,
|
||||
typename G, typename H, typename I>
|
||||
constexpr explicit row_major_init(A m00, B m01, C m02,
|
||||
D m10, E m11, F m12,
|
||||
G m20, H m21, I m22) noexcept
|
||||
: m(m00, m10, m20,
|
||||
m01, m11, m21,
|
||||
m02, m12, m22) {}
|
||||
|
||||
private:
|
||||
friend TMat33;
|
||||
TMat33 m;
|
||||
};
|
||||
|
||||
constexpr explicit TMat33(row_major_init c) noexcept : TMat33(std::move(c.m)) {}
|
||||
|
||||
/**
|
||||
* construct from a quaternion
|
||||
*/
|
||||
template<typename U>
|
||||
constexpr explicit TMat33(const TQuaternion<U>& q) noexcept;
|
||||
|
||||
/**
|
||||
* orthogonalize only works on matrices of size 3x3
|
||||
*/
|
||||
friend inline
|
||||
constexpr TMat33 orthogonalize(const TMat33& m) noexcept {
|
||||
TMat33 ret(TMat33::NO_INIT);
|
||||
ret[0] = normalize(m[0]);
|
||||
ret[2] = normalize(cross(ret[0], m[1]));
|
||||
ret[1] = normalize(cross(ret[2], ret[0]));
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a matrix suitable for transforming normals
|
||||
*
|
||||
* Note that the inverse-transpose of a matrix is equal to its cofactor matrix divided by its
|
||||
* determinant:
|
||||
*
|
||||
* transpose(inverse(M)) = cof(M) / det(M)
|
||||
*
|
||||
* The cofactor matrix is faster to compute than the inverse-transpose, and it can be argued
|
||||
* that it is a more correct way of transforming normals anyway. Some references from Dale
|
||||
* Weiler, Nathan Reed, Inigo Quilez, and Eric Lengyel:
|
||||
*
|
||||
* - https://github.com/graphitemaster/normals_revisited
|
||||
* - http://www.reedbeta.com/blog/normals-inverse-transpose-part-1/
|
||||
* - https://www.shadertoy.com/view/3s33zj
|
||||
* - FGED Volume 1, section 1.7.5 "Inverses of Small Matrices"
|
||||
* - FGED Volume 1, section 3.2.2 "Transforming Normal Vectors"
|
||||
*
|
||||
* In "Transforming Normal Vectors", Lengyel notes that there are two types of transformed
|
||||
* normals: one that uses the transposed adjugate (aka cofactor matrix) and one that uses the
|
||||
* transposed inverse. He goes on to say that this difference is inconsequential, except when
|
||||
* mirroring is involved.
|
||||
*
|
||||
* @param m the transform applied to vertices
|
||||
* @return a matrix to apply to normals
|
||||
*
|
||||
* @warning normals transformed by this matrix must be normalized
|
||||
*/
|
||||
static constexpr TMat33 getTransformForNormals(const TMat33& m) noexcept {
|
||||
return matrix::cof(m);
|
||||
}
|
||||
|
||||
/**
|
||||
* Packs the tangent frame represented by the specified matrix into a quaternion.
|
||||
* Reflection is preserved by encoding it as the sign of the w component in the
|
||||
* resulting quaternion. Since -0 cannot always be represented on the GPU, this
|
||||
* function computes a bias to ensure values are always either positive or negative,
|
||||
* never 0. The bias is computed based on the specified storageSize, which defaults
|
||||
* to 2 bytes, making the resulting quaternion suitable for storage into an SNORM16
|
||||
* vector.
|
||||
*/
|
||||
static constexpr TQuaternion<T> packTangentFrame(
|
||||
const TMat33& m, size_t storageSize = sizeof(int16_t)) noexcept;
|
||||
|
||||
template<typename A>
|
||||
static constexpr TMat33 translation(const TVec3<A>& t) noexcept {
|
||||
TMat33 r;
|
||||
r[2] = t;
|
||||
return r;
|
||||
}
|
||||
|
||||
template<typename A>
|
||||
static constexpr TMat33 scaling(const TVec3<A>& s) noexcept {
|
||||
return TMat33{ s };
|
||||
}
|
||||
|
||||
template<typename A>
|
||||
static constexpr TMat33 scaling(A s) noexcept {
|
||||
return TMat33{ TVec3<T>{ s }};
|
||||
}
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// Constructors
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
// Since the matrix code could become pretty big quickly, we don't inline most
|
||||
// operations.
|
||||
|
||||
template<typename T>
|
||||
constexpr TMat33<T>::TMat33() noexcept
|
||||
: m_value{
|
||||
col_type(1, 0, 0),
|
||||
col_type(0, 1, 0),
|
||||
col_type(0, 0, 1) } {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
constexpr TMat33<T>::TMat33(U v) noexcept
|
||||
: m_value{
|
||||
col_type(v, 0, 0),
|
||||
col_type(0, v, 0),
|
||||
col_type(0, 0, v) } {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
constexpr TMat33<T>::TMat33(const TVec3<U>& v) noexcept
|
||||
: m_value{
|
||||
col_type(v[0], 0, 0),
|
||||
col_type(0, v[1], 0),
|
||||
col_type(0, 0, v[2]) } {
|
||||
}
|
||||
|
||||
// construct from 16 scalars. Note that the arrangement
|
||||
// of values in the constructor is the transpose of the matrix
|
||||
// notation.
|
||||
template<typename T>
|
||||
template<
|
||||
typename A, typename B, typename C,
|
||||
typename D, typename E, typename F,
|
||||
typename G, typename H, typename I>
|
||||
constexpr TMat33<T>::TMat33(A m00, B m01, C m02,
|
||||
D m10, E m11, F m12,
|
||||
G m20, H m21, I m22) noexcept
|
||||
: m_value{
|
||||
col_type(m00, m01, m02),
|
||||
col_type(m10, m11, m12),
|
||||
col_type(m20, m21, m22) } {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
constexpr TMat33<T>::TMat33(const TMat33<U>& rhs) noexcept {
|
||||
for (size_t col = 0; col < NUM_COLS; ++col) {
|
||||
m_value[col] = col_type(rhs[col]);
|
||||
}
|
||||
}
|
||||
|
||||
// Construct from 3 column vectors.
|
||||
template<typename T>
|
||||
template<typename A, typename B, typename C>
|
||||
constexpr TMat33<T>::TMat33(const TVec3<A>& v0, const TVec3<B>& v1, const TVec3<C>& v2) noexcept
|
||||
: m_value{ v0, v1, v2 } {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
constexpr TMat33<T>::TMat33(const TQuaternion<U>& q) noexcept : m_value{} {
|
||||
const U n = q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w;
|
||||
const U s = n > 0 ? 2 / n : 0;
|
||||
const U x = s * q.x;
|
||||
const U y = s * q.y;
|
||||
const U z = s * q.z;
|
||||
const U xx = x * q.x;
|
||||
const U xy = x * q.y;
|
||||
const U xz = x * q.z;
|
||||
const U xw = x * q.w;
|
||||
const U yy = y * q.y;
|
||||
const U yz = y * q.z;
|
||||
const U yw = y * q.w;
|
||||
const U zz = z * q.z;
|
||||
const U zw = z * q.w;
|
||||
m_value[0] = col_type(1 - yy - zz, xy + zw, xz - yw); // NOLINT
|
||||
m_value[1] = col_type(xy - zw, 1 - xx - zz, yz + xw); // NOLINT
|
||||
m_value[2] = col_type(xz + yw, yz - xw, 1 - xx - yy); // NOLINT
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
template<typename T>
|
||||
constexpr TQuaternion<T> TMat33<T>::packTangentFrame(const TMat33<T>& m, size_t storageSize) noexcept {
|
||||
TQuaternion<T> q = TMat33<T>{ m[0], cross(m[2], m[0]), m[2] }.toQuaternion();
|
||||
q = positive(normalize(q));
|
||||
|
||||
// Ensure w is never 0.0
|
||||
// Bias is 2^(nb_bits - 1) - 1
|
||||
const T bias = T(1.0) / T((1 << (storageSize * CHAR_BIT - 1)) - 1);
|
||||
if (q.w < bias) {
|
||||
q.w = bias;
|
||||
|
||||
const T factor = (T)(std::sqrt(1.0 - (double)bias * (double)bias));
|
||||
q.xyz *= factor;
|
||||
}
|
||||
|
||||
// If there's a reflection ((n x t) . b <= 0), make sure w is negative
|
||||
if (dot(cross(m[0], m[2]), m[1]) < T(0)) {
|
||||
q = -q;
|
||||
}
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
} // namespace details
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
typedef details::TMat33<double> mat3;
|
||||
typedef details::TMat33<float> mat3f;
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
} // namespace math
|
||||
} // namespace filament
|
||||
|
||||
namespace std {
|
||||
template<typename T>
|
||||
constexpr void swap(filament::math::details::TMat33<T>& lhs,
|
||||
filament::math::details::TMat33<T>& rhs) noexcept {
|
||||
// This generates much better code than the default implementation
|
||||
// It's unclear why, I believe this is due to an optimization bug in the clang.
|
||||
//
|
||||
// filament::math::details::TMat33<T> t(lhs);
|
||||
// lhs = rhs;
|
||||
// rhs = t;
|
||||
//
|
||||
// clang always copy lhs on the stack, even if it's never using it (it's using the
|
||||
// copy it has in registers).
|
||||
|
||||
const T t00 = lhs[0][0];
|
||||
const T t01 = lhs[0][1];
|
||||
const T t02 = lhs[0][2];
|
||||
const T t10 = lhs[1][0];
|
||||
const T t11 = lhs[1][1];
|
||||
const T t12 = lhs[1][2];
|
||||
const T t20 = lhs[2][0];
|
||||
const T t21 = lhs[2][1];
|
||||
const T t22 = lhs[2][2];
|
||||
|
||||
lhs[0][0] = rhs[0][0];
|
||||
lhs[0][1] = rhs[0][1];
|
||||
lhs[0][2] = rhs[0][2];
|
||||
lhs[1][0] = rhs[1][0];
|
||||
lhs[1][1] = rhs[1][1];
|
||||
lhs[1][2] = rhs[1][2];
|
||||
lhs[2][0] = rhs[2][0];
|
||||
lhs[2][1] = rhs[2][1];
|
||||
lhs[2][2] = rhs[2][2];
|
||||
|
||||
rhs[0][0] = t00;
|
||||
rhs[0][1] = t01;
|
||||
rhs[0][2] = t02;
|
||||
rhs[1][0] = t10;
|
||||
rhs[1][1] = t11;
|
||||
rhs[1][2] = t12;
|
||||
rhs[2][0] = t20;
|
||||
rhs[2][1] = t21;
|
||||
rhs[2][2] = t22;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // MATH_MAT3_H_
|
||||
631
ios/include/math/mat4.h
Normal file
631
ios/include/math/mat4.h
Normal file
@@ -0,0 +1,631 @@
|
||||
/*
|
||||
* Copyright 2013 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 MATH_MAT4_H_
|
||||
#define MATH_MAT4_H_
|
||||
|
||||
#include <math/compiler.h>
|
||||
#include <math/mat3.h>
|
||||
#include <math/quat.h>
|
||||
#include <math/scalar.h>
|
||||
#include <math/TMatHelpers.h>
|
||||
#include <math/vec3.h>
|
||||
#include <math/vec4.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <limits>
|
||||
|
||||
namespace filament {
|
||||
namespace math {
|
||||
// -------------------------------------------------------------------------------------
|
||||
namespace details {
|
||||
|
||||
template<typename T>
|
||||
class TQuaternion;
|
||||
|
||||
/**
|
||||
* A 4x4 column-major matrix class.
|
||||
*
|
||||
* Conceptually a 4x4 matrix is a an array of 4 column double4:
|
||||
*
|
||||
* mat4 m =
|
||||
* \f$
|
||||
* \left(
|
||||
* \begin{array}{cccc}
|
||||
* m[0] & m[1] & m[2] & m[3] \\
|
||||
* \end{array}
|
||||
* \right)
|
||||
* \f$
|
||||
* =
|
||||
* \f$
|
||||
* \left(
|
||||
* \begin{array}{cccc}
|
||||
* m[0][0] & m[1][0] & m[2][0] & m[3][0] \\
|
||||
* m[0][1] & m[1][1] & m[2][1] & m[3][1] \\
|
||||
* m[0][2] & m[1][2] & m[2][2] & m[3][2] \\
|
||||
* m[0][3] & m[1][3] & m[2][3] & m[3][3] \\
|
||||
* \end{array}
|
||||
* \right)
|
||||
* \f$
|
||||
* =
|
||||
* \f$
|
||||
* \left(
|
||||
* \begin{array}{cccc}
|
||||
* m(0,0) & m(0,1) & m(0,2) & m(0,3) \\
|
||||
* m(1,0) & m(1,1) & m(1,2) & m(1,3) \\
|
||||
* m(2,0) & m(2,1) & m(2,2) & m(2,3) \\
|
||||
* m(3,0) & m(3,1) & m(3,2) & m(3,3) \\
|
||||
* \end{array}
|
||||
* \right)
|
||||
* \f$
|
||||
*
|
||||
* m[n] is the \f$ n^{th} \f$ column of the matrix and is a double4.
|
||||
*
|
||||
*/
|
||||
template<typename T>
|
||||
class MATH_EMPTY_BASES TMat44 :
|
||||
public TVecUnaryOperators<TMat44, T>,
|
||||
public TVecComparisonOperators<TMat44, T>,
|
||||
public TVecAddOperators<TMat44, T>,
|
||||
public TMatProductOperators<TMat44, T, TVec4>,
|
||||
public TMatSquareFunctions<TMat44, T>,
|
||||
public TMatTransform<TMat44, T>,
|
||||
public TMatHelpers<TMat44, T> {
|
||||
public:
|
||||
enum no_init {
|
||||
NO_INIT
|
||||
};
|
||||
typedef T value_type;
|
||||
typedef T& reference;
|
||||
typedef T const& const_reference;
|
||||
typedef size_t size_type;
|
||||
typedef TVec4<T> col_type;
|
||||
typedef TVec4<T> row_type;
|
||||
|
||||
static constexpr size_t COL_SIZE = col_type::SIZE; // size of a column (i.e.: number of rows)
|
||||
static constexpr size_t ROW_SIZE = row_type::SIZE; // size of a row (i.e.: number of columns)
|
||||
static constexpr size_t NUM_ROWS = COL_SIZE;
|
||||
static constexpr size_t NUM_COLS = ROW_SIZE;
|
||||
|
||||
private:
|
||||
/*
|
||||
* <-- N columns -->
|
||||
*
|
||||
* a[0][0] a[1][0] a[2][0] ... a[N][0] ^
|
||||
* a[0][1] a[1][1] a[2][1] ... a[N][1] |
|
||||
* a[0][2] a[1][2] a[2][2] ... a[N][2] M rows
|
||||
* ... |
|
||||
* a[0][M] a[1][M] a[2][M] ... a[N][M] v
|
||||
*
|
||||
* COL_SIZE = M
|
||||
* ROW_SIZE = N
|
||||
* m[0] = [ a[0][0] a[0][1] a[0][2] ... a[0][M] ]
|
||||
*/
|
||||
|
||||
col_type m_value[NUM_COLS];
|
||||
|
||||
public:
|
||||
// array access
|
||||
inline constexpr col_type const& operator[](size_t column) const noexcept {
|
||||
assert(column < NUM_COLS);
|
||||
return m_value[column];
|
||||
}
|
||||
|
||||
inline constexpr col_type& operator[](size_t column) noexcept {
|
||||
assert(column < NUM_COLS);
|
||||
return m_value[column];
|
||||
}
|
||||
|
||||
/*
|
||||
* constructors
|
||||
*/
|
||||
|
||||
// leaves object uninitialized. use with caution.
|
||||
constexpr explicit TMat44(no_init) noexcept {}
|
||||
|
||||
/** initialize to identity.
|
||||
*
|
||||
* \f$
|
||||
* \left(
|
||||
* \begin{array}{cccc}
|
||||
* 1 & 0 & 0 & 0 \\
|
||||
* 0 & 1 & 0 & 0 \\
|
||||
* 0 & 0 & 1 & 0 \\
|
||||
* 0 & 0 & 0 & 1 \\
|
||||
* \end{array}
|
||||
* \right)
|
||||
* \f$
|
||||
*/
|
||||
constexpr TMat44() noexcept;
|
||||
|
||||
/** initialize to Identity*scalar.
|
||||
*
|
||||
* \f$
|
||||
* \left(
|
||||
* \begin{array}{cccc}
|
||||
* v & 0 & 0 & 0 \\
|
||||
* 0 & v & 0 & 0 \\
|
||||
* 0 & 0 & v & 0 \\
|
||||
* 0 & 0 & 0 & v \\
|
||||
* \end{array}
|
||||
* \right)
|
||||
* \f$
|
||||
*/
|
||||
template<typename U>
|
||||
constexpr explicit TMat44(U v) noexcept;
|
||||
|
||||
/** sets the diagonal to a vector.
|
||||
*
|
||||
* \f$
|
||||
* \left(
|
||||
* \begin{array}{cccc}
|
||||
* v[0] & 0 & 0 & 0 \\
|
||||
* 0 & v[1] & 0 & 0 \\
|
||||
* 0 & 0 & v[2] & 0 \\
|
||||
* 0 & 0 & 0 & v[3] \\
|
||||
* \end{array}
|
||||
* \right)
|
||||
* \f$
|
||||
*/
|
||||
template<typename U>
|
||||
constexpr explicit TMat44(const TVec4<U>& v) noexcept;
|
||||
|
||||
// construct from another matrix of the same size
|
||||
template<typename U>
|
||||
constexpr explicit TMat44(const TMat44<U>& rhs) noexcept;
|
||||
|
||||
/** construct from 4 column vectors.
|
||||
*
|
||||
* \f$
|
||||
* \left(
|
||||
* \begin{array}{cccc}
|
||||
* v0 & v1 & v2 & v3 \\
|
||||
* \end{array}
|
||||
* \right)
|
||||
* \f$
|
||||
*/
|
||||
template<typename A, typename B, typename C, typename D>
|
||||
constexpr TMat44(const TVec4<A>& v0, const TVec4<B>& v1, const TVec4<C>& v2,
|
||||
const TVec4<D>& v3) noexcept;
|
||||
|
||||
/** construct from 16 elements in column-major form.
|
||||
*
|
||||
* \f$
|
||||
* \left(
|
||||
* \begin{array}{cccc}
|
||||
* m[0][0] & m[1][0] & m[2][0] & m[3][0] \\
|
||||
* m[0][1] & m[1][1] & m[2][1] & m[3][1] \\
|
||||
* m[0][2] & m[1][2] & m[2][2] & m[3][2] \\
|
||||
* m[0][3] & m[1][3] & m[2][3] & m[3][3] \\
|
||||
* \end{array}
|
||||
* \right)
|
||||
* \f$
|
||||
*/
|
||||
template<
|
||||
typename A, typename B, typename C, typename D,
|
||||
typename E, typename F, typename G, typename H,
|
||||
typename I, typename J, typename K, typename L,
|
||||
typename M, typename N, typename O, typename P>
|
||||
constexpr explicit TMat44(A m00, B m01, C m02, D m03,
|
||||
E m10, F m11, G m12, H m13,
|
||||
I m20, J m21, K m22, L m23,
|
||||
M m30, N m31, O m32, P m33) noexcept;
|
||||
|
||||
|
||||
struct row_major_init {
|
||||
template<
|
||||
typename A, typename B, typename C, typename D,
|
||||
typename E, typename F, typename G, typename H,
|
||||
typename I, typename J, typename K, typename L,
|
||||
typename M, typename N, typename O, typename P>
|
||||
constexpr explicit row_major_init(A m00, B m01, C m02, D m03,
|
||||
E m10, F m11, G m12, H m13,
|
||||
I m20, J m21, K m22, L m23,
|
||||
M m30, N m31, O m32, P m33) noexcept
|
||||
: m(m00, m10, m20, m30,
|
||||
m01, m11, m21, m31,
|
||||
m02, m12, m22, m32,
|
||||
m03, m13, m23, m33) {}
|
||||
|
||||
private:
|
||||
friend TMat44;
|
||||
TMat44 m;
|
||||
};
|
||||
|
||||
constexpr explicit TMat44(row_major_init c) noexcept : TMat44(std::move(c.m)) {}
|
||||
|
||||
/**
|
||||
* construct from a quaternion
|
||||
*/
|
||||
template<typename U>
|
||||
constexpr explicit TMat44(const TQuaternion<U>& q) noexcept;
|
||||
|
||||
/**
|
||||
* construct from a 3x3 matrix
|
||||
*/
|
||||
template<typename U>
|
||||
constexpr explicit TMat44(const TMat33<U>& matrix) noexcept;
|
||||
|
||||
/**
|
||||
* construct from a 3x3 matrix and 3d translation
|
||||
*/
|
||||
template<typename U, typename V>
|
||||
constexpr TMat44(const TMat33<U>& matrix, const TVec3<V>& translation) noexcept;
|
||||
|
||||
/**
|
||||
* construct from a 3x3 matrix and 4d last column.
|
||||
*/
|
||||
template<typename U, typename V>
|
||||
constexpr TMat44(const TMat33<U>& matrix, const TVec4<V>& column3) noexcept;
|
||||
|
||||
/*
|
||||
* helpers
|
||||
*/
|
||||
|
||||
// returns false if the two matrices are different. May return false if they're the
|
||||
// same, with some elements only differing by +0 or -0. Behaviour is undefined with NaNs.
|
||||
static constexpr bool fuzzyEqual(TMat44 const& l, TMat44 const& r) noexcept {
|
||||
uint64_t const* const li = reinterpret_cast<uint64_t const*>(&l);
|
||||
uint64_t const* const ri = reinterpret_cast<uint64_t const*>(&r);
|
||||
uint64_t result = 0;
|
||||
// For some reason clang is not able to vectorize this loop when the number of iteration
|
||||
// is known and constant (!?!?!). Still this is better than operator==.
|
||||
for (size_t i = 0; i < sizeof(TMat44) / sizeof(uint64_t); i++) {
|
||||
result |= li[i] ^ ri[i];
|
||||
}
|
||||
return result != 0;
|
||||
}
|
||||
|
||||
static constexpr TMat44 ortho(T left, T right, T bottom, T top, T near, T far) noexcept;
|
||||
|
||||
static constexpr TMat44 frustum(T left, T right, T bottom, T top, T near, T far) noexcept;
|
||||
|
||||
enum class Fov {
|
||||
HORIZONTAL,
|
||||
VERTICAL
|
||||
};
|
||||
static TMat44 perspective(T fov, T aspect, T near, T far, Fov direction = Fov::VERTICAL) noexcept;
|
||||
|
||||
template<typename A, typename B, typename C>
|
||||
static TMat44 lookAt(const TVec3<A>& eye, const TVec3<B>& center, const TVec3<C>& up) noexcept;
|
||||
|
||||
template<typename A>
|
||||
static constexpr TVec3<A> project(const TMat44& projectionMatrix, TVec3<A> vertice) noexcept{
|
||||
TVec4<A> r = projectionMatrix * TVec4<A>{ vertice, 1 };
|
||||
return TVec3<A>{ r[0], r[1], r[2] } * (1 / r[3]);
|
||||
}
|
||||
|
||||
template<typename A>
|
||||
static constexpr TVec4<A> project(const TMat44& projectionMatrix, TVec4<A> vertice) noexcept{
|
||||
vertice = projectionMatrix * vertice;
|
||||
return { TVec3<A>{ vertice[0], vertice[1], vertice[2] } * (1 / vertice[3]), 1 };
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a 3x3 matrix from the upper-left corner of this 4x4 matrix
|
||||
*/
|
||||
inline constexpr TMat33<T> upperLeft() const noexcept {
|
||||
const TVec3<T> v0 = { m_value[0][0], m_value[0][1], m_value[0][2] };
|
||||
const TVec3<T> v1 = { m_value[1][0], m_value[1][1], m_value[1][2] };
|
||||
const TVec3<T> v2 = { m_value[2][0], m_value[2][1], m_value[2][2] };
|
||||
return TMat33<T>(v0, v1, v2);
|
||||
}
|
||||
|
||||
template<typename A>
|
||||
static constexpr TMat44 translation(const TVec3<A>& t) noexcept {
|
||||
TMat44 r;
|
||||
r[3] = TVec4<T>{ t, 1 };
|
||||
return r;
|
||||
}
|
||||
|
||||
template<typename A>
|
||||
static constexpr TMat44 scaling(const TVec3<A>& s) noexcept {
|
||||
return TMat44{ TVec4<T>{ s, 1 }};
|
||||
}
|
||||
|
||||
template<typename A>
|
||||
static constexpr TMat44 scaling(A s) noexcept {
|
||||
return TMat44{ TVec4<T>{ s, s, s, 1 }};
|
||||
}
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// Constructors
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
// Since the matrix code could become pretty big quickly, we don't inline most
|
||||
// operations.
|
||||
|
||||
template<typename T>
|
||||
constexpr TMat44<T>::TMat44() noexcept
|
||||
: m_value{
|
||||
col_type(1, 0, 0, 0),
|
||||
col_type(0, 1, 0, 0),
|
||||
col_type(0, 0, 1, 0),
|
||||
col_type(0, 0, 0, 1) } {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
constexpr TMat44<T>::TMat44(U v) noexcept
|
||||
: m_value{
|
||||
col_type(v, 0, 0, 0),
|
||||
col_type(0, v, 0, 0),
|
||||
col_type(0, 0, v, 0),
|
||||
col_type(0, 0, 0, v) } {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
constexpr TMat44<T>::TMat44(const TVec4<U>& v) noexcept
|
||||
: m_value{
|
||||
col_type(v[0], 0, 0, 0),
|
||||
col_type(0, v[1], 0, 0),
|
||||
col_type(0, 0, v[2], 0),
|
||||
col_type(0, 0, 0, v[3]) } {
|
||||
}
|
||||
|
||||
|
||||
// construct from 16 scalars
|
||||
template<typename T>
|
||||
template<
|
||||
typename A, typename B, typename C, typename D,
|
||||
typename E, typename F, typename G, typename H,
|
||||
typename I, typename J, typename K, typename L,
|
||||
typename M, typename N, typename O, typename P>
|
||||
constexpr TMat44<T>::TMat44(A m00, B m01, C m02, D m03,
|
||||
E m10, F m11, G m12, H m13,
|
||||
I m20, J m21, K m22, L m23,
|
||||
M m30, N m31, O m32, P m33) noexcept
|
||||
: m_value{
|
||||
col_type(m00, m01, m02, m03),
|
||||
col_type(m10, m11, m12, m13),
|
||||
col_type(m20, m21, m22, m23),
|
||||
col_type(m30, m31, m32, m33) } {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
constexpr TMat44<T>::TMat44(const TMat44<U>& rhs) noexcept {
|
||||
for (size_t col = 0; col < NUM_COLS; ++col) {
|
||||
m_value[col] = col_type(rhs[col]);
|
||||
}
|
||||
}
|
||||
|
||||
// Construct from 4 column vectors.
|
||||
template<typename T>
|
||||
template<typename A, typename B, typename C, typename D>
|
||||
constexpr TMat44<T>::TMat44(const TVec4<A>& v0, const TVec4<B>& v1,
|
||||
const TVec4<C>& v2, const TVec4<D>& v3) noexcept
|
||||
: m_value{ v0, v1, v2, v3 } {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
constexpr TMat44<T>::TMat44(const TQuaternion<U>& q) noexcept : m_value{} {
|
||||
const U n = q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w;
|
||||
const U s = n > 0 ? 2 / n : 0;
|
||||
const U x = s * q.x;
|
||||
const U y = s * q.y;
|
||||
const U z = s * q.z;
|
||||
const U xx = x * q.x;
|
||||
const U xy = x * q.y;
|
||||
const U xz = x * q.z;
|
||||
const U xw = x * q.w;
|
||||
const U yy = y * q.y;
|
||||
const U yz = y * q.z;
|
||||
const U yw = y * q.w;
|
||||
const U zz = z * q.z;
|
||||
const U zw = z * q.w;
|
||||
m_value[0] = col_type(1 - yy - zz, xy + zw, xz - yw, 0);
|
||||
m_value[1] = col_type(xy - zw, 1 - xx - zz, yz + xw, 0); // NOLINT
|
||||
m_value[2] = col_type(xz + yw, yz - xw, 1 - xx - yy, 0); // NOLINT
|
||||
m_value[3] = col_type(0, 0, 0, 1); // NOLINT
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
constexpr TMat44<T>::TMat44(const TMat33<U>& m) noexcept
|
||||
: m_value{
|
||||
col_type(m[0][0], m[0][1], m[0][2], 0),
|
||||
col_type(m[1][0], m[1][1], m[1][2], 0),
|
||||
col_type(m[2][0], m[2][1], m[2][2], 0),
|
||||
col_type(0, 0, 0, 1) } // NOLINT
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U, typename V>
|
||||
constexpr TMat44<T>::TMat44(const TMat33<U>& m, const TVec3<V>& v) noexcept
|
||||
: m_value{
|
||||
col_type(m[0][0], m[0][1], m[0][2], 0),
|
||||
col_type(m[1][0], m[1][1], m[1][2], 0),
|
||||
col_type(m[2][0], m[2][1], m[2][2], 0),
|
||||
col_type(v[0], v[1], v[2], 1) } // NOLINT
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U, typename V>
|
||||
constexpr TMat44<T>::TMat44(const TMat33<U>& m, const TVec4<V>& v) noexcept
|
||||
: m_value{
|
||||
col_type(m[0][0], m[0][1], m[0][2], 0),
|
||||
col_type(m[1][0], m[1][1], m[1][2], 0),
|
||||
col_type(m[2][0], m[2][1], m[2][2], 0),
|
||||
col_type(v[0], v[1], v[2], v[3]) } // NOLINT
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template<typename T>
|
||||
constexpr TMat44<T> TMat44<T>::ortho(T left, T right, T bottom, T top, T near, T far) noexcept {
|
||||
TMat44<T> m;
|
||||
m[0][0] = 2 / (right - left);
|
||||
m[1][1] = 2 / (top - bottom);
|
||||
m[2][2] = -2 / (far - near);
|
||||
m[3][0] = -(right + left) / (right - left);
|
||||
m[3][1] = -(top + bottom) / (top - bottom);
|
||||
m[3][2] = -(far + near) / (far - near);
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr TMat44<T> TMat44<T>::frustum(T left, T right, T bottom, T top, T near, T far) noexcept {
|
||||
TMat44<T> m;
|
||||
m[0][0] = (2 * near) / (right - left);
|
||||
m[1][1] = (2 * near) / (top - bottom);
|
||||
m[2][0] = (right + left) / (right - left);
|
||||
m[2][1] = (top + bottom) / (top - bottom);
|
||||
m[2][2] = -(far + near) / (far - near);
|
||||
m[2][3] = -1;
|
||||
m[3][2] = -(2 * far * near) / (far - near);
|
||||
m[3][3] = 0;
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
TMat44<T> TMat44<T>::perspective(T fov, T aspect, T near, T far, TMat44::Fov direction) noexcept {
|
||||
T h, w;
|
||||
|
||||
if (direction == TMat44::Fov::VERTICAL) {
|
||||
h = std::tan(fov * F_PI / 360.0f) * near;
|
||||
w = h * aspect;
|
||||
} else {
|
||||
w = std::tan(fov * F_PI / 360.0f) * near;
|
||||
h = w / aspect;
|
||||
}
|
||||
return frustum(-w, w, -h, h, near, far);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a matrix representing the pose of a virtual camera looking towards -Z in its
|
||||
* local Y-up coordinate system. "eye" is where the camera is located, "center" is the point it's
|
||||
* looking at and "up" defines where the Y axis of the camera's local coordinate system is.
|
||||
*/
|
||||
template<typename T>
|
||||
template<typename A, typename B, typename C>
|
||||
TMat44<T> TMat44<T>::lookAt(const TVec3<A>& eye, const TVec3<B>& center,
|
||||
const TVec3<C>& up) noexcept {
|
||||
TVec3<T> z_axis(normalize(center - eye));
|
||||
TVec3<T> norm_up(normalize(up));
|
||||
if (std::abs(dot(z_axis, norm_up)) > T(0.999)) {
|
||||
// Fix up vector if we're degenerate (looking straight up, basically)
|
||||
norm_up = { norm_up.z, norm_up.x, norm_up.y };
|
||||
}
|
||||
TVec3<T> x_axis(normalize(cross(z_axis, norm_up)));
|
||||
TVec3<T> y_axis(cross(x_axis, z_axis));
|
||||
return TMat44<T>(
|
||||
TVec4<T>(x_axis, 0),
|
||||
TVec4<T>(y_axis, 0),
|
||||
TVec4<T>(-z_axis, 0),
|
||||
TVec4<T>(eye, 1));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// Arithmetic operators outside of class
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
// mat44 * vec3, result is vec3( mat44 * {vec3, 1} )
|
||||
template<typename T, typename U>
|
||||
constexpr typename TMat44<T>::col_type MATH_PURE operator*(const TMat44<T>& lhs,
|
||||
const TVec3<U>& rhs) noexcept {
|
||||
return lhs * TVec4<U>{ rhs, 1 };
|
||||
}
|
||||
|
||||
} // namespace details
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
typedef details::TMat44<double> mat4;
|
||||
typedef details::TMat44<float> mat4f;
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
} // namespace math
|
||||
} // namespace filament
|
||||
|
||||
namespace std {
|
||||
template<typename T>
|
||||
constexpr void swap(filament::math::details::TMat44<T>& lhs,
|
||||
filament::math::details::TMat44<T>& rhs) noexcept {
|
||||
// This generates much better code than the default implementation
|
||||
// It's unclear why, I believe this is due to an optimization bug in the clang.
|
||||
//
|
||||
// filament::math::details::TMat44<T> t(lhs);
|
||||
// lhs = rhs;
|
||||
// rhs = t;
|
||||
//
|
||||
// clang always copy lhs on the stack, even if it's never using it (it's using the
|
||||
// copy it has in registers).
|
||||
|
||||
const T t00 = lhs[0][0];
|
||||
const T t01 = lhs[0][1];
|
||||
const T t02 = lhs[0][2];
|
||||
const T t03 = lhs[0][3];
|
||||
const T t10 = lhs[1][0];
|
||||
const T t11 = lhs[1][1];
|
||||
const T t12 = lhs[1][2];
|
||||
const T t13 = lhs[1][3];
|
||||
const T t20 = lhs[2][0];
|
||||
const T t21 = lhs[2][1];
|
||||
const T t22 = lhs[2][2];
|
||||
const T t23 = lhs[2][3];
|
||||
const T t30 = lhs[3][0];
|
||||
const T t31 = lhs[3][1];
|
||||
const T t32 = lhs[3][2];
|
||||
const T t33 = lhs[3][3];
|
||||
|
||||
lhs[0][0] = rhs[0][0];
|
||||
lhs[0][1] = rhs[0][1];
|
||||
lhs[0][2] = rhs[0][2];
|
||||
lhs[0][3] = rhs[0][3];
|
||||
lhs[1][0] = rhs[1][0];
|
||||
lhs[1][1] = rhs[1][1];
|
||||
lhs[1][2] = rhs[1][2];
|
||||
lhs[1][3] = rhs[1][3];
|
||||
lhs[2][0] = rhs[2][0];
|
||||
lhs[2][1] = rhs[2][1];
|
||||
lhs[2][2] = rhs[2][2];
|
||||
lhs[2][3] = rhs[2][3];
|
||||
lhs[3][0] = rhs[3][0];
|
||||
lhs[3][1] = rhs[3][1];
|
||||
lhs[3][2] = rhs[3][2];
|
||||
lhs[3][3] = rhs[3][3];
|
||||
|
||||
rhs[0][0] = t00;
|
||||
rhs[0][1] = t01;
|
||||
rhs[0][2] = t02;
|
||||
rhs[0][3] = t03;
|
||||
rhs[1][0] = t10;
|
||||
rhs[1][1] = t11;
|
||||
rhs[1][2] = t12;
|
||||
rhs[1][3] = t13;
|
||||
rhs[2][0] = t20;
|
||||
rhs[2][1] = t21;
|
||||
rhs[2][2] = t22;
|
||||
rhs[2][3] = t23;
|
||||
rhs[3][0] = t30;
|
||||
rhs[3][1] = t31;
|
||||
rhs[3][2] = t32;
|
||||
rhs[3][3] = t33;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // MATH_MAT4_H_
|
||||
94
ios/include/math/mathfwd.h
Normal file
94
ios/include/math/mathfwd.h
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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 MATH_MATHFWD_H_
|
||||
#define MATH_MATHFWD_H_
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
// MSVC cannot compute the size of math types correctly when this file is included before the
|
||||
// actual implementations.
|
||||
// See github.com/google/filament/issues/2190.
|
||||
#include <math/vec2.h>
|
||||
#include <math/vec3.h>
|
||||
#include <math/vec4.h>
|
||||
#include <math/mat2.h>
|
||||
#include <math/mat3.h>
|
||||
#include <math/mat4.h>
|
||||
|
||||
#else
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace filament {
|
||||
namespace math {
|
||||
namespace details {
|
||||
|
||||
template<typename T> class TVec2;
|
||||
template<typename T> class TVec3;
|
||||
template<typename T> class TVec4;
|
||||
|
||||
template<typename T> class TMat22;
|
||||
template<typename T> class TMat33;
|
||||
template<typename T> class TMat44;
|
||||
|
||||
} // namespace details
|
||||
|
||||
using double2 = details::TVec2<double>;
|
||||
using float2 = details::TVec2<float>;
|
||||
using int2 = details::TVec2<int32_t>;
|
||||
using uint2 = details::TVec2<uint32_t>;
|
||||
using short2 = details::TVec2<int16_t>;
|
||||
using ushort2 = details::TVec2<uint16_t>;
|
||||
using byte2 = details::TVec2<int8_t>;
|
||||
using ubyte2 = details::TVec2<uint8_t>;
|
||||
using bool2 = details::TVec2<bool>;
|
||||
|
||||
using double3 = details::TVec3<double>;
|
||||
using float3 = details::TVec3<float>;
|
||||
using int3 = details::TVec3<int32_t>;
|
||||
using uint3 = details::TVec3<uint32_t>;
|
||||
using short3 = details::TVec3<int16_t>;
|
||||
using ushort3 = details::TVec3<uint16_t>;
|
||||
using byte3 = details::TVec3<int8_t>;
|
||||
using ubyte3 = details::TVec3<uint8_t>;
|
||||
using bool3 = details::TVec3<bool>;
|
||||
|
||||
using double4 = details::TVec4<double>;
|
||||
using float4 = details::TVec4<float>;
|
||||
using int4 = details::TVec4<int32_t>;
|
||||
using uint4 = details::TVec4<uint32_t>;
|
||||
using short4 = details::TVec4<int16_t>;
|
||||
using ushort4 = details::TVec4<uint16_t>;
|
||||
using byte4 = details::TVec4<int8_t>;
|
||||
using ubyte4 = details::TVec4<uint8_t>;
|
||||
using bool4 = details::TVec4<bool>;
|
||||
|
||||
using mat2 = details::TMat22<double>;
|
||||
using mat2f = details::TMat22<float>;
|
||||
|
||||
using mat3 = details::TMat33<double>;
|
||||
using mat3f = details::TMat33<float>;
|
||||
|
||||
using mat4 = details::TMat44<double>;
|
||||
using mat4f = details::TMat44<float>;
|
||||
|
||||
} // namespace math
|
||||
} // namespace filament
|
||||
|
||||
#endif // _MSC_VER
|
||||
|
||||
#endif // MATH_MATHFWD_H_
|
||||
100
ios/include/math/norm.h
Normal file
100
ios/include/math/norm.h
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* 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_MATH_NORM_H
|
||||
#define TNT_MATH_NORM_H
|
||||
|
||||
#include <math/scalar.h>
|
||||
#include <math/vec4.h>
|
||||
|
||||
#include <cmath>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace filament {
|
||||
namespace math {
|
||||
|
||||
inline uint16_t packUnorm16(float v) noexcept {
|
||||
return static_cast<uint16_t>(std::round(clamp(v, 0.0f, 1.0f) * 65535.0f));
|
||||
}
|
||||
|
||||
inline ushort4 packUnorm16(float4 v) noexcept {
|
||||
return ushort4{ packUnorm16(v.x), packUnorm16(v.y), packUnorm16(v.z), packUnorm16(v.w) };
|
||||
}
|
||||
|
||||
inline int16_t packSnorm16(float v) noexcept {
|
||||
return static_cast<int16_t>(std::round(clamp(v, -1.0f, 1.0f) * 32767.0f));
|
||||
}
|
||||
|
||||
inline short2 packSnorm16(float2 v) noexcept {
|
||||
return short2{ packSnorm16(v.x), packSnorm16(v.y) };
|
||||
}
|
||||
|
||||
inline short4 packSnorm16(float4 v) noexcept {
|
||||
return short4{ packSnorm16(v.x), packSnorm16(v.y), packSnorm16(v.z), packSnorm16(v.w) };
|
||||
}
|
||||
|
||||
inline float unpackUnorm16(uint16_t v) noexcept {
|
||||
return v / 65535.0f;
|
||||
}
|
||||
|
||||
inline float4 unpackUnorm16(ushort4 v) noexcept {
|
||||
return float4{ unpackUnorm16(v.x), unpackUnorm16(v.y), unpackUnorm16(v.z), unpackUnorm16(v.w) };
|
||||
}
|
||||
|
||||
inline float unpackSnorm16(int16_t v) noexcept {
|
||||
return clamp(v / 32767.0f, -1.0f, 1.0f);
|
||||
}
|
||||
|
||||
inline float4 unpackSnorm16(short4 v) noexcept {
|
||||
return float4{ unpackSnorm16(v.x), unpackSnorm16(v.y), unpackSnorm16(v.z), unpackSnorm16(v.w) };
|
||||
}
|
||||
|
||||
inline uint8_t packUnorm8(float v) noexcept {
|
||||
return static_cast<uint8_t>(std::round(clamp(v, 0.0f, 1.0f) * 255.0));
|
||||
}
|
||||
|
||||
inline ubyte4 packUnorm8(float4 v) noexcept {
|
||||
return ubyte4{ packUnorm8(v.x), packUnorm8(v.y), packUnorm8(v.z), packUnorm8(v.w) };
|
||||
}
|
||||
|
||||
inline int8_t packSnorm8(float v) noexcept {
|
||||
return static_cast<int8_t>(std::round(clamp(v, -1.0f, 1.0f) * 127.0));
|
||||
}
|
||||
|
||||
inline byte4 packSnorm8(float4 v) noexcept {
|
||||
return byte4{ packSnorm8(v.x), packSnorm8(v.y), packSnorm8(v.z), packSnorm8(v.w) };
|
||||
}
|
||||
|
||||
inline float unpackUnorm8(uint8_t v) noexcept {
|
||||
return v / 255.0f;
|
||||
}
|
||||
|
||||
inline float4 unpackUnorm8(ubyte4 v) noexcept {
|
||||
return float4{ unpackUnorm8(v.x), unpackUnorm8(v.y), unpackUnorm8(v.z), unpackUnorm8(v.w) };
|
||||
}
|
||||
|
||||
inline float unpackSnorm8(int8_t v) noexcept {
|
||||
return clamp(v / 127.0f, -1.0f, 1.0f);
|
||||
}
|
||||
|
||||
inline float4 unpackSnorm8(byte4 v) noexcept {
|
||||
return float4{ unpackSnorm8(v.x), unpackSnorm8(v.y), unpackSnorm8(v.z), unpackSnorm8(v.w) };
|
||||
}
|
||||
|
||||
} // namespace math
|
||||
} // namespace filament
|
||||
|
||||
#endif // TNT_MATH_NORM_H
|
||||
167
ios/include/math/quat.h
Normal file
167
ios/include/math/quat.h
Normal file
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* Copyright (C) 2013 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 MATH_QUAT_H_
|
||||
#define MATH_QUAT_H_
|
||||
|
||||
#include <math/half.h>
|
||||
#include <math/TQuatHelpers.h>
|
||||
#include <math/vec3.h>
|
||||
#include <math/vec4.h>
|
||||
#include <math/compiler.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
namespace filament {
|
||||
namespace math {
|
||||
// -------------------------------------------------------------------------------------
|
||||
|
||||
namespace details {
|
||||
|
||||
template<typename T>
|
||||
class MATH_EMPTY_BASES TQuaternion :
|
||||
public TVecAddOperators<TQuaternion, T>,
|
||||
public TVecUnaryOperators<TQuaternion, T>,
|
||||
public TVecComparisonOperators<TQuaternion, T>,
|
||||
public TQuatProductOperators<TQuaternion, T>,
|
||||
public TQuatFunctions<TQuaternion, T> {
|
||||
public:
|
||||
enum no_init {
|
||||
NO_INIT
|
||||
};
|
||||
typedef T value_type;
|
||||
typedef T& reference;
|
||||
typedef T const& const_reference;
|
||||
typedef size_t size_type;
|
||||
|
||||
/*
|
||||
* quaternion internals stored as:
|
||||
*
|
||||
* q = w + xi + yj + zk
|
||||
*
|
||||
* q[0] = x;
|
||||
* q[1] = y;
|
||||
* q[2] = z;
|
||||
* q[3] = w;
|
||||
*
|
||||
*/
|
||||
union {
|
||||
struct { T x, y, z, w; };
|
||||
TVec4<T> xyzw;
|
||||
TVec3<T> xyz;
|
||||
TVec2<T> xy;
|
||||
};
|
||||
|
||||
enum { SIZE = 4 };
|
||||
inline constexpr static size_type size() { return SIZE; }
|
||||
|
||||
// array access
|
||||
inline constexpr T const& operator[](size_t i) const {
|
||||
// only possible in C++0x14 with constexpr
|
||||
assert(i < SIZE);
|
||||
return (&x)[i];
|
||||
}
|
||||
|
||||
inline constexpr T& operator[](size_t i) {
|
||||
assert(i < SIZE);
|
||||
return (&x)[i];
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// we want the compiler generated versions for these...
|
||||
TQuaternion(const TQuaternion&) = default;
|
||||
~TQuaternion() = default;
|
||||
TQuaternion& operator=(const TQuaternion&) = default;
|
||||
|
||||
// constructors
|
||||
|
||||
// leaves object uninitialized. use with caution.
|
||||
explicit constexpr TQuaternion(no_init) {}
|
||||
|
||||
// default constructor. sets all values to zero.
|
||||
constexpr TQuaternion() : x(0), y(0), z(0), w(0) {}
|
||||
|
||||
// handles implicit conversion to a quat. must not be explicit.
|
||||
template<typename A, typename = enable_if_arithmetic_t<A>>
|
||||
constexpr TQuaternion(A w) : x(0), y(0), z(0), w(w) {}
|
||||
|
||||
// initialize from 4 values to w + xi + yj + zk
|
||||
template<typename A, typename B, typename C, typename D,
|
||||
typename = enable_if_arithmetic_t<A, B, C, D>>
|
||||
constexpr TQuaternion(A w, B x, C y, D z) : x(x), y(y), z(z), w(w) {}
|
||||
|
||||
// initialize from a vec3 + a value to : v.xi + v.yj + v.zk + w
|
||||
template<typename A, typename B, typename = enable_if_arithmetic_t<A, B>>
|
||||
constexpr TQuaternion(const TVec3<A>& v, B w) : x(v.x), y(v.y), z(v.z), w(w) {}
|
||||
|
||||
// initialize from a vec4
|
||||
template<typename A, typename = enable_if_arithmetic_t<A>>
|
||||
constexpr explicit TQuaternion(const TVec4<A>& v) : x(v.x), y(v.y), z(v.z), w(v.w) {}
|
||||
|
||||
// initialize from a quaternion of a different type
|
||||
template<typename A, typename = enable_if_arithmetic_t<A>>
|
||||
constexpr explicit TQuaternion(const TQuaternion<A>& v) : x(v.x), y(v.y), z(v.z), w(v.w) {}
|
||||
|
||||
// conjugate operator
|
||||
constexpr TQuaternion operator~() const {
|
||||
return conj(*this);
|
||||
}
|
||||
|
||||
// constructs a quaternion from an axis and angle
|
||||
template<typename A, typename B, typename = enable_if_arithmetic_t<A, B>>
|
||||
constexpr static TQuaternion MATH_PURE fromAxisAngle(const TVec3<A>& axis, B angle) {
|
||||
return TQuaternion(std::sin(angle * 0.5) * normalize(axis), std::cos(angle * 0.5));
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace details
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
typedef details::TQuaternion<double> quat;
|
||||
typedef details::TQuaternion<float> quatf;
|
||||
typedef details::TQuaternion<half> quath;
|
||||
|
||||
constexpr inline quat operator "" _i(long double v) {
|
||||
return quat(0.0, double(v), 0.0, 0.0);
|
||||
}
|
||||
|
||||
constexpr inline quat operator "" _j(long double v) {
|
||||
return quat(0.0, 0.0, double(v), 0.0);
|
||||
}
|
||||
|
||||
constexpr inline quat operator "" _k(long double v) {
|
||||
return quat(0.0, 0.0, 0.0, double(v));
|
||||
}
|
||||
|
||||
constexpr inline quat operator "" _i(unsigned long long v) {
|
||||
return quat(0.0, double(v), 0.0, 0.0);
|
||||
}
|
||||
|
||||
constexpr inline quat operator "" _j(unsigned long long v) {
|
||||
return quat(0.0, 0.0, double(v), 0.0);
|
||||
}
|
||||
|
||||
constexpr inline quat operator "" _k(unsigned long long v) {
|
||||
return quat(0.0, 0.0, 0.0, double(v));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
} // namespace math
|
||||
} // namespace filament
|
||||
|
||||
#endif // MATH_QUAT_H_
|
||||
124
ios/include/math/scalar.h
Normal file
124
ios/include/math/scalar.h
Normal file
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* 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_MATH_SCALAR_H
|
||||
#define TNT_MATH_SCALAR_H
|
||||
|
||||
#include <math/compiler.h>
|
||||
#include <assert.h>
|
||||
|
||||
namespace filament {
|
||||
namespace math {
|
||||
|
||||
constexpr const double F_E = 2.71828182845904523536028747135266250;
|
||||
constexpr const double F_LOG2E = 1.44269504088896340735992468100189214;
|
||||
constexpr const double F_LOG10E = 0.434294481903251827651128918916605082;
|
||||
constexpr const double F_LN2 = 0.693147180559945309417232121458176568;
|
||||
constexpr const double F_LN10 = 2.30258509299404568401799145468436421;
|
||||
constexpr const double F_PI = 3.14159265358979323846264338327950288;
|
||||
constexpr const double F_PI_2 = 1.57079632679489661923132169163975144;
|
||||
constexpr const double F_PI_4 = 0.785398163397448309615660845819875721;
|
||||
constexpr const double F_1_PI = 0.318309886183790671537767526745028724;
|
||||
constexpr const double F_2_PI = 0.636619772367581343075535053490057448;
|
||||
constexpr const double F_2_SQRTPI = 1.12837916709551257389615890312154517;
|
||||
constexpr const double F_SQRT2 = 1.41421356237309504880168872420969808;
|
||||
constexpr const double F_SQRT1_2 = 0.707106781186547524400844362104849039;
|
||||
constexpr const double F_TAU = 2.0 * F_PI;
|
||||
|
||||
namespace d {
|
||||
constexpr const double E = F_E;
|
||||
constexpr const double LOG2E = F_LOG2E;
|
||||
constexpr const double LOG10E = F_LOG10E;
|
||||
constexpr const double LN2 = F_LN2;
|
||||
constexpr const double LN10 = F_LN10;
|
||||
constexpr const double PI = F_PI;
|
||||
constexpr const double PI_2 = F_PI_2;
|
||||
constexpr const double PI_4 = F_PI_4;
|
||||
constexpr const double ONE_OVER_PI = F_1_PI;
|
||||
constexpr const double TWO_OVER_PI = F_2_PI;
|
||||
constexpr const double TWO_OVER_SQRTPI = F_2_SQRTPI;
|
||||
constexpr const double SQRT2 = F_SQRT2;
|
||||
constexpr const double SQRT1_2 = F_SQRT1_2;
|
||||
constexpr const double TAU = F_TAU;
|
||||
constexpr const double DEG_TO_RAD = F_PI / 180.0;
|
||||
constexpr const double RAD_TO_DEG = 180.0 / F_PI;
|
||||
} // namespace d
|
||||
|
||||
namespace f {
|
||||
constexpr const float E = (float)d::E;
|
||||
constexpr const float LOG2E = (float)d::LOG2E;
|
||||
constexpr const float LOG10E = (float)d::LOG10E;
|
||||
constexpr const float LN2 = (float)d::LN2;
|
||||
constexpr const float LN10 = (float)d::LN10;
|
||||
constexpr const float PI = (float)d::PI;
|
||||
constexpr const float PI_2 = (float)d::PI_2;
|
||||
constexpr const float PI_4 = (float)d::PI_4;
|
||||
constexpr const float ONE_OVER_PI = (float)d::ONE_OVER_PI;
|
||||
constexpr const float TWO_OVER_PI = (float)d::TWO_OVER_PI;
|
||||
constexpr const float TWO_OVER_SQRTPI = (float)d::TWO_OVER_SQRTPI;
|
||||
constexpr const float SQRT2 = (float)d::SQRT2;
|
||||
constexpr const float SQRT1_2 = (float)d::SQRT1_2;
|
||||
constexpr const float TAU = (float)d::TAU;
|
||||
constexpr const float DEG_TO_RAD = (float)d::DEG_TO_RAD;
|
||||
constexpr const float RAD_TO_DEG = (float)d::RAD_TO_DEG;
|
||||
} // namespace f
|
||||
|
||||
template<typename T>
|
||||
inline constexpr T MATH_PURE min(T a, T b) noexcept {
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline constexpr T MATH_PURE max(T a, T b) noexcept {
|
||||
return a > b ? a : b;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline constexpr T MATH_PURE clamp(T v, T min, T max) noexcept {
|
||||
assert(min <= max);
|
||||
return T(math::min(max, math::max(min, v)));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline constexpr T MATH_PURE saturate(T v) noexcept {
|
||||
return clamp(v, T(0), T(1));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline constexpr T MATH_PURE mix(T x, T y, T a) noexcept {
|
||||
return x * (T(1) - a) + y * a;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline constexpr T MATH_PURE lerp(T x, T y, T a) noexcept {
|
||||
return mix(x, y, a);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline constexpr T MATH_PURE smoothstep(T e0, T e1, T x) noexcept {
|
||||
T t = clamp((x - e0) / (e1 - e0), T(0), T(1));
|
||||
return t * t * (T(3) - T(2) * t);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline constexpr T sign(T x) noexcept {
|
||||
return x < T(0) ? T(-1) : T(1);
|
||||
}
|
||||
|
||||
} // namespace math
|
||||
} // namespace filament
|
||||
|
||||
#endif // TNT_MATH_SCALAR_H
|
||||
113
ios/include/math/vec2.h
Normal file
113
ios/include/math/vec2.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright 2013 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 MATH_VEC2_H_
|
||||
#define MATH_VEC2_H_
|
||||
|
||||
#include <math/TVecHelpers.h>
|
||||
#include <math/half.h>
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <type_traits>
|
||||
|
||||
|
||||
namespace filament {
|
||||
namespace math {
|
||||
// -------------------------------------------------------------------------------------
|
||||
|
||||
namespace details {
|
||||
|
||||
template<typename T>
|
||||
class MATH_EMPTY_BASES TVec2 :
|
||||
public TVecProductOperators<TVec2, T>,
|
||||
public TVecAddOperators<TVec2, T>,
|
||||
public TVecUnaryOperators<TVec2, T>,
|
||||
public TVecComparisonOperators<TVec2, T>,
|
||||
public TVecFunctions<TVec2, T> {
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef T& reference;
|
||||
typedef T const& const_reference;
|
||||
typedef size_t size_type;
|
||||
static constexpr size_t SIZE = 2;
|
||||
|
||||
union {
|
||||
T v[SIZE] MATH_CONSTEXPR_INIT;
|
||||
struct { T x, y; };
|
||||
struct { T s, t; };
|
||||
struct { T r, g; };
|
||||
};
|
||||
|
||||
inline constexpr size_type size() const { return SIZE; }
|
||||
|
||||
// array access
|
||||
inline constexpr T const& operator[](size_t i) const noexcept {
|
||||
assert(i < SIZE);
|
||||
return v[i];
|
||||
}
|
||||
|
||||
inline constexpr T& operator[](size_t i) noexcept {
|
||||
assert(i < SIZE);
|
||||
return v[i];
|
||||
}
|
||||
|
||||
// constructors
|
||||
|
||||
// default constructor
|
||||
MATH_DEFAULT_CTOR_CONSTEXPR TVec2() MATH_DEFAULT_CTOR
|
||||
|
||||
// handles implicit conversion to a tvec4. must not be explicit.
|
||||
template<typename A, typename = enable_if_arithmetic_t<A>>
|
||||
constexpr TVec2(A v) noexcept : v{ T(v), T(v) } {}
|
||||
|
||||
template<typename A, typename B, typename = enable_if_arithmetic_t<A, B>>
|
||||
constexpr TVec2(A x, B y) noexcept : v{ T(x), T(y) } {}
|
||||
|
||||
template<typename A, typename = enable_if_arithmetic_t<A>>
|
||||
constexpr TVec2(const TVec2<A>& v) noexcept : v{ T(v[0]), T(v[1]) } {}
|
||||
|
||||
// cross product works only on vectors of size 2 or 3
|
||||
template<typename U>
|
||||
friend inline constexpr
|
||||
arithmetic_result_t<T, U> cross(const TVec2& u, const TVec2<U>& v) noexcept {
|
||||
return u[0] * v[1] - u[1] * v[0];
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace details
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template<typename T, typename = details::enable_if_arithmetic_t<T>>
|
||||
using vec2 = details::TVec2<T>;
|
||||
|
||||
using double2 = vec2<double>;
|
||||
using float2 = vec2<float>;
|
||||
using half2 = vec2<half>;
|
||||
using int2 = vec2<int32_t>;
|
||||
using uint2 = vec2<uint32_t>;
|
||||
using short2 = vec2<int16_t>;
|
||||
using ushort2 = vec2<uint16_t>;
|
||||
using byte2 = vec2<int8_t>;
|
||||
using ubyte2 = vec2<uint8_t>;
|
||||
using bool2 = vec2<bool>;
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
} // namespace math
|
||||
} // namespace filament
|
||||
|
||||
#endif // MATH_VEC2_H_
|
||||
133
ios/include/math/vec3.h
Normal file
133
ios/include/math/vec3.h
Normal file
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright 2013 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 MATH_VEC3_H_
|
||||
#define MATH_VEC3_H_
|
||||
|
||||
#include <math/vec2.h>
|
||||
#include <math/half.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
|
||||
namespace filament {
|
||||
namespace math {
|
||||
// -------------------------------------------------------------------------------------
|
||||
|
||||
namespace details {
|
||||
|
||||
template<typename T>
|
||||
class MATH_EMPTY_BASES TVec3 :
|
||||
public TVecProductOperators<TVec3, T>,
|
||||
public TVecAddOperators<TVec3, T>,
|
||||
public TVecUnaryOperators<TVec3, T>,
|
||||
public TVecComparisonOperators<TVec3, T>,
|
||||
public TVecFunctions<TVec3, T> {
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef T& reference;
|
||||
typedef T const& const_reference;
|
||||
typedef size_t size_type;
|
||||
static constexpr size_t SIZE = 3;
|
||||
|
||||
union {
|
||||
T v[SIZE] MATH_CONSTEXPR_INIT;
|
||||
TVec2<T> xy;
|
||||
TVec2<T> st;
|
||||
TVec2<T> rg;
|
||||
struct {
|
||||
union {
|
||||
T x;
|
||||
T s;
|
||||
T r;
|
||||
};
|
||||
union {
|
||||
struct { T y, z; };
|
||||
struct { T t, p; };
|
||||
struct { T g, b; };
|
||||
TVec2<T> yz;
|
||||
TVec2<T> tp;
|
||||
TVec2<T> gb;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
inline constexpr size_type size() const { return SIZE; }
|
||||
|
||||
// array access
|
||||
inline constexpr T const& operator[](size_t i) const noexcept {
|
||||
assert(i < SIZE);
|
||||
return v[i];
|
||||
}
|
||||
|
||||
inline constexpr T& operator[](size_t i) noexcept {
|
||||
assert(i < SIZE);
|
||||
return v[i];
|
||||
}
|
||||
|
||||
// constructors
|
||||
|
||||
// default constructor
|
||||
MATH_DEFAULT_CTOR_CONSTEXPR TVec3() noexcept MATH_DEFAULT_CTOR
|
||||
|
||||
// handles implicit conversion to a tvec3. must not be explicit.
|
||||
template<typename A, typename = enable_if_arithmetic_t<A>>
|
||||
constexpr TVec3(A v) noexcept : v{ T(v), T(v), T(v) } {}
|
||||
|
||||
template<typename A, typename B, typename C,
|
||||
typename = enable_if_arithmetic_t<A, B, C>>
|
||||
constexpr TVec3(A x, B y, C z) noexcept : v{ T(x), T(y), T(z) } {}
|
||||
|
||||
template<typename A, typename B, typename = enable_if_arithmetic_t<A, B>>
|
||||
constexpr TVec3(const TVec2<A>& v, B z) noexcept : v{ T(v[0]), T(v[1]), T(z) } {}
|
||||
|
||||
template<typename A, typename = enable_if_arithmetic_t<A>>
|
||||
constexpr TVec3(const TVec3<A>& v) noexcept : v{ T(v[0]), T(v[1]), T(v[2]) } {}
|
||||
|
||||
// cross product works only on vectors of size 3
|
||||
template<typename U>
|
||||
friend inline constexpr
|
||||
TVec3<arithmetic_result_t<T, U>> cross(const TVec3& u, const TVec3<U>& v) noexcept {
|
||||
return {
|
||||
u[1] * v[2] - u[2] * v[1],
|
||||
u[2] * v[0] - u[0] * v[2],
|
||||
u[0] * v[1] - u[1] * v[0] };
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace details
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template<typename T, typename = details::enable_if_arithmetic_t<T>>
|
||||
using vec3 = details::TVec3<T>;
|
||||
|
||||
using double3 = vec3<double>;
|
||||
using float3 = vec3<float>;
|
||||
using half3 = vec3<half>;
|
||||
using int3 = vec3<int32_t>;
|
||||
using uint3 = vec3<uint32_t>;
|
||||
using short3 = vec3<int16_t>;
|
||||
using ushort3 = vec3<uint16_t>;
|
||||
using byte3 = vec3<int8_t>;
|
||||
using ubyte3 = vec3<uint8_t>;
|
||||
using bool3 = vec3<bool>;
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
} // namespace math
|
||||
} // namespace filament
|
||||
|
||||
#endif // MATH_VEC3_H_
|
||||
132
ios/include/math/vec4.h
Normal file
132
ios/include/math/vec4.h
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright 2013 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 MATH_VEC4_H_
|
||||
#define MATH_VEC4_H_
|
||||
|
||||
#include <math/vec3.h>
|
||||
#include <math/half.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
|
||||
namespace filament {
|
||||
namespace math {
|
||||
// -------------------------------------------------------------------------------------
|
||||
|
||||
namespace details {
|
||||
|
||||
template<typename T>
|
||||
class MATH_EMPTY_BASES TVec4 :
|
||||
public TVecProductOperators<TVec4, T>,
|
||||
public TVecAddOperators<TVec4, T>,
|
||||
public TVecUnaryOperators<TVec4, T>,
|
||||
public TVecComparisonOperators<TVec4, T>,
|
||||
public TVecFunctions<TVec4, T> {
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef T& reference;
|
||||
typedef T const& const_reference;
|
||||
typedef size_t size_type;
|
||||
static constexpr size_t SIZE = 4;
|
||||
|
||||
union {
|
||||
T v[SIZE] MATH_CONSTEXPR_INIT;
|
||||
TVec2<T> xy, st, rg;
|
||||
TVec3<T> xyz, stp, rgb;
|
||||
struct {
|
||||
union { T x, s, r; };
|
||||
union {
|
||||
TVec2<T> yz, tp, gb;
|
||||
TVec3<T> yzw, tpq, gba;
|
||||
struct {
|
||||
union { T y, t, g; };
|
||||
union {
|
||||
TVec2<T> zw, pq, ba;
|
||||
struct { T z, w; };
|
||||
struct { T p, q; };
|
||||
struct { T b, a; };
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
inline constexpr size_type size() const { return SIZE; }
|
||||
|
||||
// array access
|
||||
inline constexpr T const& operator[](size_t i) const noexcept {
|
||||
assert(i < SIZE);
|
||||
return v[i];
|
||||
}
|
||||
|
||||
inline constexpr T& operator[](size_t i) noexcept {
|
||||
assert(i < SIZE);
|
||||
return v[i];
|
||||
}
|
||||
|
||||
// constructors
|
||||
|
||||
// default constructor
|
||||
MATH_DEFAULT_CTOR_CONSTEXPR TVec4() noexcept MATH_DEFAULT_CTOR
|
||||
|
||||
// handles implicit conversion to a tvec4. must not be explicit.
|
||||
template<typename A, typename = enable_if_arithmetic_t<A>>
|
||||
constexpr TVec4(A v) noexcept : v{ T(v), T(v), T(v), T(v) } {}
|
||||
|
||||
template<typename A, typename B, typename C, typename D,
|
||||
typename = enable_if_arithmetic_t<A, B, C, D>>
|
||||
constexpr TVec4(A x, B y, C z, D w) noexcept : v{ T(x), T(y), T(z), T(w) } {}
|
||||
|
||||
template<typename A, typename B, typename C,
|
||||
typename = enable_if_arithmetic_t<A, B, C>>
|
||||
constexpr TVec4(const TVec2<A>& v, B z, C w) noexcept : v{ T(v[0]), T(v[1]), T(z), T(w) } {}
|
||||
|
||||
template<typename A, typename B, typename = enable_if_arithmetic_t<A, B>>
|
||||
constexpr TVec4(const TVec2<A>& v, const TVec2<B>& w) noexcept : v{
|
||||
T(v[0]), T(v[1]), T(w[0]), T(w[1]) } {}
|
||||
|
||||
template<typename A, typename B, typename = enable_if_arithmetic_t<A, B>>
|
||||
constexpr TVec4(const TVec3<A>& v, B w) noexcept : v{ T(v[0]), T(v[1]), T(v[2]), T(w) } {}
|
||||
|
||||
template<typename A, typename = enable_if_arithmetic_t<A>>
|
||||
constexpr TVec4(const TVec4<A>& v) noexcept : v{ T(v[0]), T(v[1]), T(v[2]), T(v[3]) } {}
|
||||
};
|
||||
|
||||
} // namespace details
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template<typename T, typename = details::enable_if_arithmetic_t<T>>
|
||||
using vec4 = details::TVec4<T>;
|
||||
|
||||
using double4 = vec4<double>;
|
||||
using float4 = vec4<float>;
|
||||
using half4 = vec4<half>;
|
||||
using int4 = vec4<int32_t>;
|
||||
using uint4 = vec4<uint32_t>;
|
||||
using short4 = vec4<int16_t>;
|
||||
using ushort4 = vec4<uint16_t>;
|
||||
using byte4 = vec4<int8_t>;
|
||||
using ubyte4 = vec4<uint8_t>;
|
||||
using bool4 = vec4<bool>;
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
} // namespace math
|
||||
} // namespace filament
|
||||
|
||||
#endif // MATH_VEC4_H_
|
||||
60
ios/include/mathio/ostream.h
Normal file
60
ios/include/mathio/ostream.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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
|
||||
2090
ios/include/trie/htrie_hash.h
Normal file
2090
ios/include/trie/htrie_hash.h
Normal file
File diff suppressed because it is too large
Load Diff
647
ios/include/trie/htrie_map.h
Normal file
647
ios/include/trie/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/trie/htrie_set.h
Normal file
586
ios/include/trie/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
|
||||
290
ios/include/tsl/robin_growth_policy.h
Normal file
290
ios/include/tsl/robin_growth_policy.h
Normal file
@@ -0,0 +1,290 @@
|
||||
/**
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2017 Tessil
|
||||
*
|
||||
* 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_ROBIN_GROWTH_POLICY_H
|
||||
#define TSL_ROBIN_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
|
||||
|
||||
#ifndef __has_builtin
|
||||
#define __has_builtin(x) 0
|
||||
#endif
|
||||
|
||||
#if __has_builtin(__builtin_expect)
|
||||
# define TSL_LIKELY( exp ) (__builtin_expect( !!(exp), true ))
|
||||
#else
|
||||
# define TSL_LIKELY( exp ) (exp)
|
||||
#endif
|
||||
|
||||
namespace tsl {
|
||||
namespace rh {
|
||||
|
||||
/**
|
||||
* 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).
|
||||
*/
|
||||
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 maxmimum size.");
|
||||
}
|
||||
|
||||
static_assert(MIN_BUCKETS_SIZE > 0, "MIN_BUCKETS_SIZE must be > 0.");
|
||||
const std::size_t min_bucket_count = MIN_BUCKETS_SIZE;
|
||||
|
||||
min_bucket_count_in_out = std::max(min_bucket_count, min_bucket_count_in_out);
|
||||
min_bucket_count_in_out = round_up_to_power_of_two(min_bucket_count_in_out);
|
||||
m_mask = min_bucket_count_in_out - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the bucket [0, bucket_count()) to which the hash belongs.
|
||||
*/
|
||||
std::size_t bucket_for_hash(std::size_t hash) const noexcept {
|
||||
return hash & m_mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the bucket count to use when the bucket array grows on rehash.
|
||||
*/
|
||||
std::size_t next_bucket_count() const {
|
||||
if((m_mask + 1) > max_bucket_count() / GrowthFactor) {
|
||||
THROW(std::length_error, "The hash table exceeds its maxmimum 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;
|
||||
}
|
||||
|
||||
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 const std::size_t MIN_BUCKETS_SIZE = 2;
|
||||
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 usefull if you want a slower growth.
|
||||
*/
|
||||
template<class GrowthFactor = std::ratio<3, 2>>
|
||||
class mod_growth_policy {
|
||||
public:
|
||||
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 maxmimum size.");
|
||||
}
|
||||
|
||||
static_assert(MIN_BUCKETS_SIZE > 0, "MIN_BUCKETS_SIZE must be > 0.");
|
||||
const std::size_t min_bucket_count = MIN_BUCKETS_SIZE;
|
||||
|
||||
min_bucket_count_in_out = std::max(min_bucket_count, min_bucket_count_in_out);
|
||||
m_bucket_count = min_bucket_count_in_out;
|
||||
}
|
||||
|
||||
std::size_t bucket_for_hash(std::size_t hash) const noexcept {
|
||||
return hash % m_bucket_count;
|
||||
}
|
||||
|
||||
std::size_t next_bucket_count() const {
|
||||
if(m_bucket_count == max_bucket_count()) {
|
||||
THROW(std::length_error, "The hash table exceeds its maxmimum size.");
|
||||
}
|
||||
|
||||
const double next_bucket_count = std::ceil(double(m_bucket_count) * REHASH_SIZE_MULTIPLICATION_FACTOR);
|
||||
if(!std::isnormal(next_bucket_count)) {
|
||||
THROW(std::length_error, "The hash table exceeds its maxmimum 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;
|
||||
}
|
||||
|
||||
private:
|
||||
static const std::size_t MIN_BUCKETS_SIZE = 2;
|
||||
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_bucket_count;
|
||||
};
|
||||
|
||||
|
||||
|
||||
namespace detail {
|
||||
|
||||
static constexpr const std::array<std::size_t, 39> PRIMES = {{
|
||||
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), 39> 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>
|
||||
}};
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Grow the hash table by using prime numbers as bucket count. Slower than tsl::rh::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 environement.
|
||||
*/
|
||||
class prime_growth_policy {
|
||||
public:
|
||||
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 maxmimum size.");
|
||||
}
|
||||
|
||||
m_iprime = static_cast<unsigned int>(std::distance(detail::PRIMES.begin(), it_prime));
|
||||
min_bucket_count_in_out = *it_prime;
|
||||
}
|
||||
|
||||
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 maxmimum size.");
|
||||
}
|
||||
|
||||
return detail::PRIMES[m_iprime + 1];
|
||||
}
|
||||
|
||||
std::size_t max_bucket_count() const {
|
||||
return detail::PRIMES.back();
|
||||
}
|
||||
|
||||
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
|
||||
1252
ios/include/tsl/robin_hash.h
Normal file
1252
ios/include/tsl/robin_hash.h
Normal file
File diff suppressed because it is too large
Load Diff
668
ios/include/tsl/robin_map.h
Normal file
668
ios/include/tsl/robin_map.h
Normal file
@@ -0,0 +1,668 @@
|
||||
/**
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2017 Tessil
|
||||
*
|
||||
* 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_ROBIN_MAP_H
|
||||
#define TSL_ROBIN_MAP_H
|
||||
|
||||
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include "robin_hash.h"
|
||||
|
||||
|
||||
namespace tsl {
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of a hash map using open-adressing and the robin hood hashing algorithm with backward shift deletion.
|
||||
*
|
||||
* For operations modifying the hash map (insert, erase, rehash, ...), the strong exception guarantee
|
||||
* is only guaranteed when the expression `std::is_nothrow_swappable<std::pair<Key, T>>::value &&
|
||||
* std::is_nothrow_move_constructible<std::pair<Key, T>>::value` is true, otherwise if an exception
|
||||
* is thrown during the swap or the move, the hash map may end up in a undefined state. Per the standard
|
||||
* a `Key` or `T` with a noexcept copy constructor and no move constructor also satisfies the
|
||||
* `std::is_nothrow_move_constructible<std::pair<Key, T>>::value` criterion (and will thus guarantee the
|
||||
* strong exception for the map).
|
||||
*
|
||||
* When `StoreHash` is true, 32 bits of the hash are stored alongside the values. It can improve
|
||||
* the performance during lookups if the `KeyEqual` function takes time (if it engenders a cache-miss for example)
|
||||
* as we then compare the stored hashes before comparing the keys. When `tsl::rh::power_of_two_growth_policy` is used
|
||||
* as `GrowthPolicy`, it may also speed-up the rehash process as we can avoid to recalculate the hash.
|
||||
* When it is detected that storing the hash will not incur any memory penality due to alignement (i.e.
|
||||
* `sizeof(tsl::detail_robin_hash::bucket_entry<ValueType, true>) ==
|
||||
* sizeof(tsl::detail_robin_hash::bucket_entry<ValueType, false>)`) and `tsl::rh::power_of_two_growth_policy` is
|
||||
* used, the hash will be stored even if `StoreHash` is false so that we can speed-up the rehash (but it will
|
||||
* not be used on lookups unless `StoreHash` is true).
|
||||
*
|
||||
* `GrowthPolicy` defines how the map grows and consequently how a hash value is mapped to a bucket.
|
||||
* By default the map uses `tsl::rh::power_of_two_growth_policy`. This policy keeps the number of buckets
|
||||
* to a power of two and uses a mask to map the hash to a bucket instead of the slow modulo.
|
||||
* Other growth policies are available and you may define your own growth policy,
|
||||
* check `tsl::rh::power_of_two_growth_policy` for the interface.
|
||||
*
|
||||
* If the destructor of `Key` or `T` throws an exception, the behaviour of the class is undefined.
|
||||
*
|
||||
* Iterators invalidation:
|
||||
* - clear, operator=, reserve, rehash: always invalidate the iterators.
|
||||
* - insert, emplace, emplace_hint, operator[]: if there is an effective insert, invalidate the iterators.
|
||||
* - erase: always invalidate the iterators.
|
||||
*/
|
||||
template<class Key,
|
||||
class T,
|
||||
class Hash = std::hash<Key>,
|
||||
class KeyEqual = std::equal_to<Key>,
|
||||
class Allocator = std::allocator<std::pair<Key, T>>,
|
||||
bool StoreHash = false,
|
||||
class GrowthPolicy = tsl::rh::power_of_two_growth_policy<2>>
|
||||
class robin_map {
|
||||
private:
|
||||
template<typename U>
|
||||
using has_is_transparent = tsl::detail_robin_hash::has_is_transparent<U>;
|
||||
|
||||
class KeySelect {
|
||||
public:
|
||||
using key_type = Key;
|
||||
|
||||
const key_type& operator()(const std::pair<Key, T>& key_value) const noexcept {
|
||||
return key_value.first;
|
||||
}
|
||||
|
||||
key_type& operator()(std::pair<Key, T>& key_value) noexcept {
|
||||
return key_value.first;
|
||||
}
|
||||
};
|
||||
|
||||
class ValueSelect {
|
||||
public:
|
||||
using value_type = T;
|
||||
|
||||
const value_type& operator()(const std::pair<Key, T>& key_value) const noexcept {
|
||||
return key_value.second;
|
||||
}
|
||||
|
||||
value_type& operator()(std::pair<Key, T>& key_value) noexcept {
|
||||
return key_value.second;
|
||||
}
|
||||
};
|
||||
|
||||
using ht = detail_robin_hash::robin_hash<std::pair<Key, T>, KeySelect, ValueSelect,
|
||||
Hash, KeyEqual, Allocator, StoreHash, GrowthPolicy>;
|
||||
|
||||
public:
|
||||
using key_type = typename ht::key_type;
|
||||
using mapped_type = T;
|
||||
using value_type = typename ht::value_type;
|
||||
using size_type = typename ht::size_type;
|
||||
using difference_type = typename ht::difference_type;
|
||||
using hasher = typename ht::hasher;
|
||||
using key_equal = typename ht::key_equal;
|
||||
using allocator_type = typename ht::allocator_type;
|
||||
using reference = typename ht::reference;
|
||||
using const_reference = typename ht::const_reference;
|
||||
using pointer = typename ht::pointer;
|
||||
using const_pointer = typename ht::const_pointer;
|
||||
using iterator = typename ht::iterator;
|
||||
using const_iterator = typename ht::const_iterator;
|
||||
|
||||
|
||||
public:
|
||||
/*
|
||||
* Constructors
|
||||
*/
|
||||
robin_map(): robin_map(ht::DEFAULT_INIT_BUCKETS_SIZE) {
|
||||
}
|
||||
|
||||
explicit robin_map(size_type bucket_count,
|
||||
const Hash& hash = Hash(),
|
||||
const KeyEqual& equal = KeyEqual(),
|
||||
const Allocator& alloc = Allocator()):
|
||||
m_ht(bucket_count, hash, equal, alloc, ht::DEFAULT_MAX_LOAD_FACTOR)
|
||||
{
|
||||
}
|
||||
|
||||
robin_map(size_type bucket_count,
|
||||
const Allocator& alloc): robin_map(bucket_count, Hash(), KeyEqual(), alloc)
|
||||
{
|
||||
}
|
||||
|
||||
robin_map(size_type bucket_count,
|
||||
const Hash& hash,
|
||||
const Allocator& alloc): robin_map(bucket_count, hash, KeyEqual(), alloc)
|
||||
{
|
||||
}
|
||||
|
||||
explicit robin_map(const Allocator& alloc): robin_map(ht::DEFAULT_INIT_BUCKETS_SIZE, alloc) {
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
robin_map(InputIt first, InputIt last,
|
||||
size_type bucket_count = ht::DEFAULT_INIT_BUCKETS_SIZE,
|
||||
const Hash& hash = Hash(),
|
||||
const KeyEqual& equal = KeyEqual(),
|
||||
const Allocator& alloc = Allocator()): robin_map(bucket_count, hash, equal, alloc)
|
||||
{
|
||||
insert(first, last);
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
robin_map(InputIt first, InputIt last,
|
||||
size_type bucket_count,
|
||||
const Allocator& alloc): robin_map(first, last, bucket_count, Hash(), KeyEqual(), alloc)
|
||||
{
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
robin_map(InputIt first, InputIt last,
|
||||
size_type bucket_count,
|
||||
const Hash& hash,
|
||||
const Allocator& alloc): robin_map(first, last, bucket_count, hash, KeyEqual(), alloc)
|
||||
{
|
||||
}
|
||||
|
||||
robin_map(std::initializer_list<value_type> init,
|
||||
size_type bucket_count = ht::DEFAULT_INIT_BUCKETS_SIZE,
|
||||
const Hash& hash = Hash(),
|
||||
const KeyEqual& equal = KeyEqual(),
|
||||
const Allocator& alloc = Allocator()):
|
||||
robin_map(init.begin(), init.end(), bucket_count, hash, equal, alloc)
|
||||
{
|
||||
}
|
||||
|
||||
robin_map(std::initializer_list<value_type> init,
|
||||
size_type bucket_count,
|
||||
const Allocator& alloc):
|
||||
robin_map(init.begin(), init.end(), bucket_count, Hash(), KeyEqual(), alloc)
|
||||
{
|
||||
}
|
||||
|
||||
robin_map(std::initializer_list<value_type> init,
|
||||
size_type bucket_count,
|
||||
const Hash& hash,
|
||||
const Allocator& alloc):
|
||||
robin_map(init.begin(), init.end(), bucket_count, hash, KeyEqual(), alloc)
|
||||
{
|
||||
}
|
||||
|
||||
robin_map& operator=(std::initializer_list<value_type> ilist) {
|
||||
m_ht.clear();
|
||||
|
||||
m_ht.reserve(ilist.size());
|
||||
m_ht.insert(ilist.begin(), ilist.end());
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
allocator_type get_allocator() const { return m_ht.get_allocator(); }
|
||||
|
||||
|
||||
/*
|
||||
* 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(); }
|
||||
|
||||
/*
|
||||
* Modifiers
|
||||
*/
|
||||
void clear() noexcept { m_ht.clear(); }
|
||||
|
||||
|
||||
|
||||
std::pair<iterator, bool> insert(const value_type& value) {
|
||||
return m_ht.insert(value);
|
||||
}
|
||||
|
||||
template<class P, typename std::enable_if<std::is_constructible<value_type, P&&>::value>::type* = nullptr>
|
||||
std::pair<iterator, bool> insert(P&& value) {
|
||||
return m_ht.emplace(std::forward<P>(value));
|
||||
}
|
||||
|
||||
std::pair<iterator, bool> insert(value_type&& value) {
|
||||
return m_ht.insert(std::move(value));
|
||||
}
|
||||
|
||||
|
||||
iterator insert(const_iterator hint, const value_type& value) {
|
||||
return m_ht.insert(hint, value);
|
||||
}
|
||||
|
||||
template<class P, typename std::enable_if<std::is_constructible<value_type, P&&>::value>::type* = nullptr>
|
||||
iterator insert(const_iterator hint, P&& value) {
|
||||
return m_ht.emplace_hint(hint, std::forward<P>(value));
|
||||
}
|
||||
|
||||
iterator insert(const_iterator hint, value_type&& value) {
|
||||
return m_ht.insert(hint, std::move(value));
|
||||
}
|
||||
|
||||
|
||||
template<class InputIt>
|
||||
void insert(InputIt first, InputIt last) {
|
||||
m_ht.insert(first, last);
|
||||
}
|
||||
|
||||
void insert(std::initializer_list<value_type> ilist) {
|
||||
m_ht.insert(ilist.begin(), ilist.end());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template<class M>
|
||||
std::pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj) {
|
||||
return m_ht.insert_or_assign(k, std::forward<M>(obj));
|
||||
}
|
||||
|
||||
template<class M>
|
||||
std::pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj) {
|
||||
return m_ht.insert_or_assign(std::move(k), std::forward<M>(obj));
|
||||
}
|
||||
|
||||
template<class M>
|
||||
iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj) {
|
||||
return m_ht.insert_or_assign(hint, k, std::forward<M>(obj));
|
||||
}
|
||||
|
||||
template<class M>
|
||||
iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj) {
|
||||
return m_ht.insert_or_assign(hint, std::move(k), std::forward<M>(obj));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Due to the way elements are stored, emplace will need to move or copy the key-value once.
|
||||
* The method is equivalent to insert(value_type(std::forward<Args>(args)...));
|
||||
*
|
||||
* Mainly here for compatibility with the std::unordered_map interface.
|
||||
*/
|
||||
template<class... Args>
|
||||
std::pair<iterator, bool> emplace(Args&&... args) {
|
||||
return m_ht.emplace(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Due to the way elements are stored, emplace_hint will need to move or copy the key-value once.
|
||||
* The method is equivalent to insert(hint, value_type(std::forward<Args>(args)...));
|
||||
*
|
||||
* Mainly here for compatibility with the std::unordered_map interface.
|
||||
*/
|
||||
template<class... Args>
|
||||
iterator emplace_hint(const_iterator hint, Args&&... args) {
|
||||
return m_ht.emplace_hint(hint, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template<class... Args>
|
||||
std::pair<iterator, bool> try_emplace(const key_type& k, Args&&... args) {
|
||||
return m_ht.try_emplace(k, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<class... Args>
|
||||
std::pair<iterator, bool> try_emplace(key_type&& k, Args&&... args) {
|
||||
return m_ht.try_emplace(std::move(k), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<class... Args>
|
||||
iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args) {
|
||||
return m_ht.try_emplace(hint, k, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<class... Args>
|
||||
iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args) {
|
||||
return m_ht.try_emplace(hint, std::move(k), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
iterator erase(iterator pos) { return m_ht.erase(pos); }
|
||||
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(const key_type& key) { return m_ht.erase(key); }
|
||||
|
||||
/**
|
||||
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||
* as hash_function()(key). Usefull to speed-up the lookup to the value if you already have the hash.
|
||||
*/
|
||||
size_type erase(const key_type& key, std::size_t precalculated_hash) {
|
||||
return m_ht.erase(key, precalculated_hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists.
|
||||
* If so, K must be hashable and comparable to Key.
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
size_type erase(const K& key) { return m_ht.erase(key); }
|
||||
|
||||
/**
|
||||
* @copydoc erase(const K& key)
|
||||
*
|
||||
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||
* as hash_function()(key). Usefull to speed-up the lookup to the value if you already have the hash.
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
size_type erase(const K& key, std::size_t precalculated_hash) {
|
||||
return m_ht.erase(key, precalculated_hash);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void swap(robin_map& other) { other.m_ht.swap(m_ht); }
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Lookup
|
||||
*/
|
||||
T& at(const Key& key) { return m_ht.at(key); }
|
||||
|
||||
/**
|
||||
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
|
||||
*/
|
||||
T& at(const Key& key, std::size_t precalculated_hash) { return m_ht.at(key, precalculated_hash); }
|
||||
|
||||
|
||||
const T& at(const Key& key) const { return m_ht.at(key); }
|
||||
|
||||
/**
|
||||
* @copydoc at(const Key& key, std::size_t precalculated_hash)
|
||||
*/
|
||||
const T& at(const Key& key, std::size_t precalculated_hash) const { return m_ht.at(key, precalculated_hash); }
|
||||
|
||||
|
||||
/**
|
||||
* This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists.
|
||||
* If so, K must be hashable and comparable to Key.
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
T& at(const K& key) { return m_ht.at(key); }
|
||||
|
||||
/**
|
||||
* @copydoc at(const K& key)
|
||||
*
|
||||
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
T& at(const K& key, std::size_t precalculated_hash) { return m_ht.at(key, precalculated_hash); }
|
||||
|
||||
|
||||
/**
|
||||
* @copydoc at(const K& key)
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
const T& at(const K& key) const { return m_ht.at(key); }
|
||||
|
||||
/**
|
||||
* @copydoc at(const K& key, std::size_t precalculated_hash)
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
const T& at(const K& key, std::size_t precalculated_hash) const { return m_ht.at(key, precalculated_hash); }
|
||||
|
||||
|
||||
|
||||
|
||||
T& operator[](const Key& key) { return m_ht[key]; }
|
||||
T& operator[](Key&& key) { return m_ht[std::move(key)]; }
|
||||
|
||||
|
||||
|
||||
|
||||
size_type count(const Key& key) const { return m_ht.count(key); }
|
||||
|
||||
/**
|
||||
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
|
||||
*/
|
||||
size_type count(const Key& key, std::size_t precalculated_hash) const {
|
||||
return m_ht.count(key, precalculated_hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists.
|
||||
* If so, K must be hashable and comparable to Key.
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
size_type count(const K& key) const { return m_ht.count(key); }
|
||||
|
||||
/**
|
||||
* @copydoc count(const K& key) const
|
||||
*
|
||||
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
size_type count(const K& key, std::size_t precalculated_hash) const { return m_ht.count(key, precalculated_hash); }
|
||||
|
||||
|
||||
|
||||
|
||||
iterator find(const Key& key) { return m_ht.find(key); }
|
||||
|
||||
/**
|
||||
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
|
||||
*/
|
||||
iterator find(const Key& key, std::size_t precalculated_hash) { return m_ht.find(key, precalculated_hash); }
|
||||
|
||||
const_iterator find(const Key& key) const { return m_ht.find(key); }
|
||||
|
||||
/**
|
||||
* @copydoc find(const Key& key, std::size_t precalculated_hash)
|
||||
*/
|
||||
const_iterator find(const Key& key, std::size_t precalculated_hash) const {
|
||||
return m_ht.find(key, precalculated_hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists.
|
||||
* If so, K must be hashable and comparable to Key.
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
iterator find(const K& key) { return m_ht.find(key); }
|
||||
|
||||
/**
|
||||
* @copydoc find(const K& key)
|
||||
*
|
||||
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
iterator find(const K& key, std::size_t precalculated_hash) { return m_ht.find(key, precalculated_hash); }
|
||||
|
||||
/**
|
||||
* @copydoc find(const K& key)
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
const_iterator find(const K& key) const { return m_ht.find(key); }
|
||||
|
||||
/**
|
||||
* @copydoc find(const K& key)
|
||||
*
|
||||
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
const_iterator find(const K& key, std::size_t precalculated_hash) const {
|
||||
return m_ht.find(key, precalculated_hash);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
std::pair<iterator, iterator> equal_range(const Key& key) { return m_ht.equal_range(key); }
|
||||
|
||||
/**
|
||||
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
|
||||
*/
|
||||
std::pair<iterator, iterator> equal_range(const Key& key, std::size_t precalculated_hash) {
|
||||
return m_ht.equal_range(key, precalculated_hash);
|
||||
}
|
||||
|
||||
std::pair<const_iterator, const_iterator> equal_range(const Key& key) const { return m_ht.equal_range(key); }
|
||||
|
||||
/**
|
||||
* @copydoc equal_range(const Key& key, std::size_t precalculated_hash)
|
||||
*/
|
||||
std::pair<const_iterator, const_iterator> equal_range(const Key& key, std::size_t precalculated_hash) const {
|
||||
return m_ht.equal_range(key, precalculated_hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists.
|
||||
* If so, K must be hashable and comparable to Key.
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
std::pair<iterator, iterator> equal_range(const K& key) { return m_ht.equal_range(key); }
|
||||
|
||||
|
||||
/**
|
||||
* @copydoc equal_range(const K& key)
|
||||
*
|
||||
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
std::pair<iterator, iterator> equal_range(const K& key, std::size_t precalculated_hash) {
|
||||
return m_ht.equal_range(key, precalculated_hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc equal_range(const K& key)
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
std::pair<const_iterator, const_iterator> equal_range(const K& key) const { return m_ht.equal_range(key); }
|
||||
|
||||
/**
|
||||
* @copydoc equal_range(const K& key, std::size_t precalculated_hash)
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
std::pair<const_iterator, const_iterator> equal_range(const K& key, std::size_t precalculated_hash) const {
|
||||
return m_ht.equal_range(key, 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
|
||||
*/
|
||||
|
||||
/**
|
||||
* Convert a const_iterator to an iterator.
|
||||
*/
|
||||
iterator mutable_iterator(const_iterator pos) {
|
||||
return m_ht.mutable_iterator(pos);
|
||||
}
|
||||
|
||||
friend bool operator==(const robin_map& lhs, const robin_map& rhs) {
|
||||
if(lhs.size() != rhs.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for(const auto& element_lhs: lhs) {
|
||||
const auto it_element_rhs = rhs.find(element_lhs.first);
|
||||
if(it_element_rhs == rhs.cend() || element_lhs.second != it_element_rhs->second) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
friend bool operator!=(const robin_map& lhs, const robin_map& rhs) {
|
||||
return !operator==(lhs, rhs);
|
||||
}
|
||||
|
||||
friend void swap(robin_map& lhs, robin_map& rhs) {
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
|
||||
private:
|
||||
ht m_ht;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Same as `tsl::robin_map<Key, T, Hash, KeyEqual, Allocator, StoreHash, tsl::rh::prime_growth_policy>`.
|
||||
*/
|
||||
template<class Key,
|
||||
class T,
|
||||
class Hash = std::hash<Key>,
|
||||
class KeyEqual = std::equal_to<Key>,
|
||||
class Allocator = std::allocator<std::pair<Key, T>>,
|
||||
bool StoreHash = false>
|
||||
using robin_pg_map = robin_map<Key, T, Hash, KeyEqual, Allocator, StoreHash, tsl::rh::prime_growth_policy>;
|
||||
|
||||
} // end namespace tsl
|
||||
|
||||
#endif
|
||||
535
ios/include/tsl/robin_set.h
Normal file
535
ios/include/tsl/robin_set.h
Normal file
@@ -0,0 +1,535 @@
|
||||
/**
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2017 Tessil
|
||||
*
|
||||
* 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_ROBIN_SET_H
|
||||
#define TSL_ROBIN_SET_H
|
||||
|
||||
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include "robin_hash.h"
|
||||
|
||||
|
||||
namespace tsl {
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of a hash set using open-adressing and the robin hood hashing algorithm with backward shift deletion.
|
||||
*
|
||||
* For operations modifying the hash set (insert, erase, rehash, ...), the strong exception guarantee
|
||||
* is only guaranteed when the expression `std::is_nothrow_swappable<Key>::value &&
|
||||
* std::is_nothrow_move_constructible<Key>::value` is true, otherwise if an exception
|
||||
* is thrown during the swap or the move, the hash set may end up in a undefined state. Per the standard
|
||||
* a `Key` with a noexcept copy constructor and no move constructor also satisfies the
|
||||
* `std::is_nothrow_move_constructible<Key>::value` criterion (and will thus guarantee the
|
||||
* strong exception for the set).
|
||||
*
|
||||
* When `StoreHash` is true, 32 bits of the hash are stored alongside the values. It can improve
|
||||
* the performance during lookups if the `KeyEqual` function takes time (or engenders a cache-miss for example)
|
||||
* as we then compare the stored hashes before comparing the keys. When `tsl::rh::power_of_two_growth_policy` is used
|
||||
* as `GrowthPolicy`, it may also speed-up the rehash process as we can avoid to recalculate the hash.
|
||||
* When it is detected that storing the hash will not incur any memory penality due to alignement (i.e.
|
||||
* `sizeof(tsl::detail_robin_hash::bucket_entry<ValueType, true>) ==
|
||||
* sizeof(tsl::detail_robin_hash::bucket_entry<ValueType, false>)`) and `tsl::rh::power_of_two_growth_policy` is
|
||||
* used, the hash will be stored even if `StoreHash` is false so that we can speed-up the rehash (but it will
|
||||
* not be used on lookups unless `StoreHash` is true).
|
||||
*
|
||||
* `GrowthPolicy` defines how the set grows and consequently how a hash value is mapped to a bucket.
|
||||
* By default the set uses `tsl::rh::power_of_two_growth_policy`. This policy keeps the number of buckets
|
||||
* to a power of two and uses a mask to set the hash to a bucket instead of the slow modulo.
|
||||
* Other growth policies are available and you may define your own growth policy,
|
||||
* check `tsl::rh::power_of_two_growth_policy` for the interface.
|
||||
*
|
||||
* If the destructor of `Key` throws an exception, the behaviour of the class is undefined.
|
||||
*
|
||||
* Iterators invalidation:
|
||||
* - clear, operator=, reserve, rehash: always invalidate the iterators.
|
||||
* - insert, emplace, emplace_hint, operator[]: if there is an effective insert, invalidate the iterators.
|
||||
* - erase: always invalidate the iterators.
|
||||
*/
|
||||
template<class Key,
|
||||
class Hash = std::hash<Key>,
|
||||
class KeyEqual = std::equal_to<Key>,
|
||||
class Allocator = std::allocator<Key>,
|
||||
bool StoreHash = false,
|
||||
class GrowthPolicy = tsl::rh::power_of_two_growth_policy<2>>
|
||||
class robin_set {
|
||||
private:
|
||||
template<typename U>
|
||||
using has_is_transparent = tsl::detail_robin_hash::has_is_transparent<U>;
|
||||
|
||||
class KeySelect {
|
||||
public:
|
||||
using key_type = Key;
|
||||
|
||||
const key_type& operator()(const Key& key) const noexcept {
|
||||
return key;
|
||||
}
|
||||
|
||||
key_type& operator()(Key& key) noexcept {
|
||||
return key;
|
||||
}
|
||||
};
|
||||
|
||||
using ht = detail_robin_hash::robin_hash<Key, KeySelect, void,
|
||||
Hash, KeyEqual, Allocator, StoreHash, GrowthPolicy>;
|
||||
|
||||
public:
|
||||
using key_type = typename ht::key_type;
|
||||
using value_type = typename ht::value_type;
|
||||
using size_type = typename ht::size_type;
|
||||
using difference_type = typename ht::difference_type;
|
||||
using hasher = typename ht::hasher;
|
||||
using key_equal = typename ht::key_equal;
|
||||
using allocator_type = typename ht::allocator_type;
|
||||
using reference = typename ht::reference;
|
||||
using const_reference = typename ht::const_reference;
|
||||
using pointer = typename ht::pointer;
|
||||
using const_pointer = typename ht::const_pointer;
|
||||
using iterator = typename ht::iterator;
|
||||
using const_iterator = typename ht::const_iterator;
|
||||
|
||||
|
||||
/*
|
||||
* Constructors
|
||||
*/
|
||||
robin_set(): robin_set(ht::DEFAULT_INIT_BUCKETS_SIZE) {
|
||||
}
|
||||
|
||||
explicit robin_set(size_type bucket_count,
|
||||
const Hash& hash = Hash(),
|
||||
const KeyEqual& equal = KeyEqual(),
|
||||
const Allocator& alloc = Allocator()):
|
||||
m_ht(bucket_count, hash, equal, alloc, ht::DEFAULT_MAX_LOAD_FACTOR)
|
||||
{
|
||||
}
|
||||
|
||||
robin_set(size_type bucket_count,
|
||||
const Allocator& alloc): robin_set(bucket_count, Hash(), KeyEqual(), alloc)
|
||||
{
|
||||
}
|
||||
|
||||
robin_set(size_type bucket_count,
|
||||
const Hash& hash,
|
||||
const Allocator& alloc): robin_set(bucket_count, hash, KeyEqual(), alloc)
|
||||
{
|
||||
}
|
||||
|
||||
explicit robin_set(const Allocator& alloc): robin_set(ht::DEFAULT_INIT_BUCKETS_SIZE, alloc) {
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
robin_set(InputIt first, InputIt last,
|
||||
size_type bucket_count = ht::DEFAULT_INIT_BUCKETS_SIZE,
|
||||
const Hash& hash = Hash(),
|
||||
const KeyEqual& equal = KeyEqual(),
|
||||
const Allocator& alloc = Allocator()): robin_set(bucket_count, hash, equal, alloc)
|
||||
{
|
||||
insert(first, last);
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
robin_set(InputIt first, InputIt last,
|
||||
size_type bucket_count,
|
||||
const Allocator& alloc): robin_set(first, last, bucket_count, Hash(), KeyEqual(), alloc)
|
||||
{
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
robin_set(InputIt first, InputIt last,
|
||||
size_type bucket_count,
|
||||
const Hash& hash,
|
||||
const Allocator& alloc): robin_set(first, last, bucket_count, hash, KeyEqual(), alloc)
|
||||
{
|
||||
}
|
||||
|
||||
robin_set(std::initializer_list<value_type> init,
|
||||
size_type bucket_count = ht::DEFAULT_INIT_BUCKETS_SIZE,
|
||||
const Hash& hash = Hash(),
|
||||
const KeyEqual& equal = KeyEqual(),
|
||||
const Allocator& alloc = Allocator()):
|
||||
robin_set(init.begin(), init.end(), bucket_count, hash, equal, alloc)
|
||||
{
|
||||
}
|
||||
|
||||
robin_set(std::initializer_list<value_type> init,
|
||||
size_type bucket_count,
|
||||
const Allocator& alloc):
|
||||
robin_set(init.begin(), init.end(), bucket_count, Hash(), KeyEqual(), alloc)
|
||||
{
|
||||
}
|
||||
|
||||
robin_set(std::initializer_list<value_type> init,
|
||||
size_type bucket_count,
|
||||
const Hash& hash,
|
||||
const Allocator& alloc):
|
||||
robin_set(init.begin(), init.end(), bucket_count, hash, KeyEqual(), alloc)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
robin_set& operator=(std::initializer_list<value_type> ilist) {
|
||||
m_ht.clear();
|
||||
|
||||
m_ht.reserve(ilist.size());
|
||||
m_ht.insert(ilist.begin(), ilist.end());
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
allocator_type get_allocator() const { return m_ht.get_allocator(); }
|
||||
|
||||
|
||||
/*
|
||||
* 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(); }
|
||||
|
||||
/*
|
||||
* Modifiers
|
||||
*/
|
||||
void clear() noexcept { m_ht.clear(); }
|
||||
|
||||
|
||||
|
||||
|
||||
std::pair<iterator, bool> insert(const value_type& value) {
|
||||
return m_ht.insert(value);
|
||||
}
|
||||
|
||||
std::pair<iterator, bool> insert(value_type&& value) {
|
||||
return m_ht.insert(std::move(value));
|
||||
}
|
||||
|
||||
iterator insert(const_iterator hint, const value_type& value) {
|
||||
return m_ht.insert(hint, value);
|
||||
}
|
||||
|
||||
iterator insert(const_iterator hint, value_type&& value) {
|
||||
return m_ht.insert(hint, std::move(value));
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
void insert(InputIt first, InputIt last) {
|
||||
m_ht.insert(first, last);
|
||||
}
|
||||
|
||||
void insert(std::initializer_list<value_type> ilist) {
|
||||
m_ht.insert(ilist.begin(), ilist.end());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Due to the way elements are stored, emplace will need to move or copy the key-value once.
|
||||
* The method is equivalent to insert(value_type(std::forward<Args>(args)...));
|
||||
*
|
||||
* Mainly here for compatibility with the std::unordered_map interface.
|
||||
*/
|
||||
template<class... Args>
|
||||
std::pair<iterator, bool> emplace(Args&&... args) {
|
||||
return m_ht.emplace(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Due to the way elements are stored, emplace_hint will need to move or copy the key-value once.
|
||||
* The method is equivalent to insert(hint, value_type(std::forward<Args>(args)...));
|
||||
*
|
||||
* Mainly here for compatibility with the std::unordered_map interface.
|
||||
*/
|
||||
template<class... Args>
|
||||
iterator emplace_hint(const_iterator hint, Args&&... args) {
|
||||
return m_ht.emplace_hint(hint, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
|
||||
|
||||
iterator erase(iterator pos) { return m_ht.erase(pos); }
|
||||
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(const key_type& key) { return m_ht.erase(key); }
|
||||
|
||||
/**
|
||||
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||
* as hash_function()(key). Usefull to speed-up the lookup to the value if you already have the hash.
|
||||
*/
|
||||
size_type erase(const key_type& key, std::size_t precalculated_hash) {
|
||||
return m_ht.erase(key, precalculated_hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists.
|
||||
* If so, K must be hashable and comparable to Key.
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
size_type erase(const K& key) { return m_ht.erase(key); }
|
||||
|
||||
/**
|
||||
* @copydoc erase(const K& key)
|
||||
*
|
||||
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||
* as hash_function()(key). Usefull to speed-up the lookup to the value if you already have the hash.
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
size_type erase(const K& key, std::size_t precalculated_hash) {
|
||||
return m_ht.erase(key, precalculated_hash);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void swap(robin_set& other) { other.m_ht.swap(m_ht); }
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Lookup
|
||||
*/
|
||||
size_type count(const Key& key) const { return m_ht.count(key); }
|
||||
|
||||
/**
|
||||
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
|
||||
*/
|
||||
size_type count(const Key& key, std::size_t precalculated_hash) const { return m_ht.count(key, precalculated_hash); }
|
||||
|
||||
/**
|
||||
* This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists.
|
||||
* If so, K must be hashable and comparable to Key.
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
size_type count(const K& key) const { return m_ht.count(key); }
|
||||
|
||||
/**
|
||||
* @copydoc count(const K& key) const
|
||||
*
|
||||
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
size_type count(const K& key, std::size_t precalculated_hash) const { return m_ht.count(key, precalculated_hash); }
|
||||
|
||||
|
||||
|
||||
|
||||
iterator find(const Key& key) { return m_ht.find(key); }
|
||||
|
||||
/**
|
||||
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
|
||||
*/
|
||||
iterator find(const Key& key, std::size_t precalculated_hash) { return m_ht.find(key, precalculated_hash); }
|
||||
|
||||
const_iterator find(const Key& key) const { return m_ht.find(key); }
|
||||
|
||||
/**
|
||||
* @copydoc find(const Key& key, std::size_t precalculated_hash)
|
||||
*/
|
||||
const_iterator find(const Key& key, std::size_t precalculated_hash) const { return m_ht.find(key, precalculated_hash); }
|
||||
|
||||
/**
|
||||
* This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists.
|
||||
* If so, K must be hashable and comparable to Key.
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
iterator find(const K& key) { return m_ht.find(key); }
|
||||
|
||||
/**
|
||||
* @copydoc find(const K& key)
|
||||
*
|
||||
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
iterator find(const K& key, std::size_t precalculated_hash) { return m_ht.find(key, precalculated_hash); }
|
||||
|
||||
/**
|
||||
* @copydoc find(const K& key)
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
const_iterator find(const K& key) const { return m_ht.find(key); }
|
||||
|
||||
/**
|
||||
* @copydoc find(const K& key)
|
||||
*
|
||||
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
const_iterator find(const K& key, std::size_t precalculated_hash) const { return m_ht.find(key, precalculated_hash); }
|
||||
|
||||
|
||||
|
||||
|
||||
std::pair<iterator, iterator> equal_range(const Key& key) { return m_ht.equal_range(key); }
|
||||
|
||||
/**
|
||||
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
|
||||
*/
|
||||
std::pair<iterator, iterator> equal_range(const Key& key, std::size_t precalculated_hash) {
|
||||
return m_ht.equal_range(key, precalculated_hash);
|
||||
}
|
||||
|
||||
std::pair<const_iterator, const_iterator> equal_range(const Key& key) const { return m_ht.equal_range(key); }
|
||||
|
||||
/**
|
||||
* @copydoc equal_range(const Key& key, std::size_t precalculated_hash)
|
||||
*/
|
||||
std::pair<const_iterator, const_iterator> equal_range(const Key& key, std::size_t precalculated_hash) const {
|
||||
return m_ht.equal_range(key, precalculated_hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists.
|
||||
* If so, K must be hashable and comparable to Key.
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
std::pair<iterator, iterator> equal_range(const K& key) { return m_ht.equal_range(key); }
|
||||
|
||||
/**
|
||||
* @copydoc equal_range(const K& key)
|
||||
*
|
||||
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
std::pair<iterator, iterator> equal_range(const K& key, std::size_t precalculated_hash) {
|
||||
return m_ht.equal_range(key, precalculated_hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc equal_range(const K& key)
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
std::pair<const_iterator, const_iterator> equal_range(const K& key) const { return m_ht.equal_range(key); }
|
||||
|
||||
/**
|
||||
* @copydoc equal_range(const K& key, std::size_t precalculated_hash)
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
std::pair<const_iterator, const_iterator> equal_range(const K& key, std::size_t precalculated_hash) const {
|
||||
return m_ht.equal_range(key, 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
|
||||
*/
|
||||
|
||||
/**
|
||||
* Convert a const_iterator to an iterator.
|
||||
*/
|
||||
iterator mutable_iterator(const_iterator pos) {
|
||||
return m_ht.mutable_iterator(pos);
|
||||
}
|
||||
|
||||
friend bool operator==(const robin_set& lhs, const robin_set& rhs) {
|
||||
if(lhs.size() != rhs.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for(const auto& element_lhs: lhs) {
|
||||
const auto it_element_rhs = rhs.find(element_lhs);
|
||||
if(it_element_rhs == rhs.cend()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
friend bool operator!=(const robin_set& lhs, const robin_set& rhs) {
|
||||
return !operator==(lhs, rhs);
|
||||
}
|
||||
|
||||
friend void swap(robin_set& lhs, robin_set& rhs) {
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
|
||||
private:
|
||||
ht m_ht;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Same as `tsl::robin_set<Key, Hash, KeyEqual, Allocator, StoreHash, tsl::rh::prime_growth_policy>`.
|
||||
*/
|
||||
template<class Key,
|
||||
class Hash = std::hash<Key>,
|
||||
class KeyEqual = std::equal_to<Key>,
|
||||
class Allocator = std::allocator<Key>,
|
||||
bool StoreHash = false>
|
||||
using robin_pg_set = robin_set<Key, Hash, KeyEqual, Allocator, StoreHash, tsl::rh::prime_growth_policy>;
|
||||
|
||||
} // end namespace tsl
|
||||
|
||||
#endif
|
||||
|
||||
824
ios/include/utils/Allocator.h
Normal file
824
ios/include/utils/Allocator.h
Normal file
@@ -0,0 +1,824 @@
|
||||
/*
|
||||
* 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 TNT_UTILS_ALLOCATOR_H
|
||||
#define TNT_UTILS_ALLOCATOR_H
|
||||
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/memalign.h>
|
||||
#include <utils/Mutex.h>
|
||||
#include <utils/SpinLock.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <cstddef>
|
||||
#include <mutex>
|
||||
#include <type_traits>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
namespace utils {
|
||||
|
||||
namespace pointermath {
|
||||
|
||||
template <typename P, typename T>
|
||||
static inline P* add(P* a, T b) noexcept {
|
||||
return (P*)(uintptr_t(a) + uintptr_t(b));
|
||||
}
|
||||
|
||||
template <typename P>
|
||||
static inline P* align(P* p, size_t alignment) noexcept {
|
||||
// alignment must be a power-of-two
|
||||
assert(alignment && !(alignment & alignment-1));
|
||||
return (P*)((uintptr_t(p) + alignment - 1) & ~(alignment - 1));
|
||||
}
|
||||
|
||||
template <typename P>
|
||||
static inline P* align(P* p, size_t alignment, size_t offset) noexcept {
|
||||
P* const r = align(add(p, offset), alignment);
|
||||
assert(pointermath::add(r, -offset) >= p);
|
||||
return r;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* LinearAllocator
|
||||
*
|
||||
* + Allocates blocks linearly
|
||||
* + Cannot free individual blocks
|
||||
* + Can free top of memory back up to a specified point
|
||||
* + Doesn't call destructors
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class LinearAllocator {
|
||||
public:
|
||||
// use memory area provided
|
||||
LinearAllocator(void* begin, void* end) noexcept;
|
||||
|
||||
template <typename AREA>
|
||||
explicit LinearAllocator(const AREA& area) : LinearAllocator(area.begin(), area.end()) { }
|
||||
|
||||
// Allocators can't be copied
|
||||
LinearAllocator(const LinearAllocator& rhs) = delete;
|
||||
LinearAllocator& operator=(const LinearAllocator& rhs) = delete;
|
||||
|
||||
// Allocators can be moved
|
||||
LinearAllocator(LinearAllocator&& rhs) noexcept;
|
||||
LinearAllocator& operator=(LinearAllocator&& rhs) noexcept;
|
||||
|
||||
~LinearAllocator() noexcept = default;
|
||||
|
||||
// our allocator concept
|
||||
void* alloc(size_t size, size_t alignment = alignof(std::max_align_t), size_t extra = 0) UTILS_RESTRICT {
|
||||
// branch-less allocation
|
||||
void* const p = pointermath::align(current(), alignment, extra);
|
||||
void* const c = pointermath::add(p, size);
|
||||
bool success = c <= end();
|
||||
set_current(success ? c : current());
|
||||
return success ? p : nullptr;
|
||||
}
|
||||
|
||||
// API specific to this allocator
|
||||
|
||||
void *getCurrent() UTILS_RESTRICT noexcept {
|
||||
return current();
|
||||
}
|
||||
|
||||
// free memory back to the specified point
|
||||
void rewind(void* p) UTILS_RESTRICT noexcept {
|
||||
assert(p>=mBegin && p<end());
|
||||
set_current(p);
|
||||
}
|
||||
|
||||
// frees all allocated blocks
|
||||
void reset() UTILS_RESTRICT noexcept {
|
||||
rewind(mBegin);
|
||||
}
|
||||
|
||||
size_t allocated() const UTILS_RESTRICT noexcept {
|
||||
return mSize;
|
||||
}
|
||||
|
||||
size_t available() const UTILS_RESTRICT noexcept {
|
||||
return mSize - mCur;
|
||||
}
|
||||
|
||||
void swap(LinearAllocator& rhs) noexcept;
|
||||
|
||||
void *base() noexcept { return mBegin; }
|
||||
|
||||
void free(void*, size_t) UTILS_RESTRICT noexcept { }
|
||||
|
||||
private:
|
||||
void* end() UTILS_RESTRICT noexcept { return pointermath::add(mBegin, mSize); }
|
||||
void* current() UTILS_RESTRICT noexcept { return pointermath::add(mBegin, mCur); }
|
||||
void set_current(void* p) UTILS_RESTRICT noexcept { mCur = uintptr_t(p) - uintptr_t(mBegin); }
|
||||
|
||||
void* mBegin = nullptr;
|
||||
uint32_t mSize = 0;
|
||||
uint32_t mCur = 0;
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* HeapAllocator
|
||||
*
|
||||
* + uses malloc() for all allocations
|
||||
* + frees blocks with free()
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
class HeapAllocator {
|
||||
public:
|
||||
HeapAllocator() noexcept = default;
|
||||
|
||||
template <typename AREA>
|
||||
explicit HeapAllocator(const AREA&) { }
|
||||
|
||||
// our allocator concept
|
||||
void* alloc(size_t size, size_t alignment = alignof(std::max_align_t), size_t extra = 0) {
|
||||
// this allocator doesn't support 'extra'
|
||||
assert(extra == 0);
|
||||
return aligned_alloc(size, alignment);
|
||||
}
|
||||
|
||||
void free(void* p) noexcept {
|
||||
aligned_free(p);
|
||||
}
|
||||
|
||||
void free(void* p, size_t) noexcept {
|
||||
free(p);
|
||||
}
|
||||
|
||||
~HeapAllocator() noexcept = default;
|
||||
|
||||
void swap(HeapAllocator& rhs) noexcept { }
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
class FreeList {
|
||||
public:
|
||||
FreeList() noexcept = default;
|
||||
FreeList(void* begin, void* end, size_t elementSize, size_t alignment, size_t extra) noexcept;
|
||||
FreeList(const FreeList& rhs) = delete;
|
||||
FreeList& operator=(const FreeList& rhs) = delete;
|
||||
FreeList(FreeList&& rhs) noexcept = default;
|
||||
FreeList& operator=(FreeList&& rhs) noexcept = default;
|
||||
|
||||
void* pop() noexcept {
|
||||
Node* const head = mHead;
|
||||
mHead = head ? head->next : nullptr;
|
||||
// this could indicate a use after free
|
||||
assert(!mHead || mHead >= mBegin && mHead < mEnd);
|
||||
return head;
|
||||
}
|
||||
|
||||
void push(void* p) noexcept {
|
||||
assert(p);
|
||||
assert(p >= mBegin && p < mEnd);
|
||||
// TODO: assert this is one of our pointer (i.e.: it's address match one of ours)
|
||||
Node* const head = static_cast<Node*>(p);
|
||||
head->next = mHead;
|
||||
mHead = head;
|
||||
}
|
||||
|
||||
void *getFirst() noexcept {
|
||||
return mHead;
|
||||
}
|
||||
|
||||
private:
|
||||
struct Node {
|
||||
Node* next;
|
||||
};
|
||||
|
||||
static Node* init(void* begin, void* end,
|
||||
size_t elementSize, size_t alignment, size_t extra) noexcept;
|
||||
|
||||
Node* mHead = nullptr;
|
||||
|
||||
#ifndef NDEBUG
|
||||
// These are needed only for debugging...
|
||||
void* mBegin = nullptr;
|
||||
void* mEnd = nullptr;
|
||||
#endif
|
||||
};
|
||||
|
||||
class AtomicFreeList {
|
||||
public:
|
||||
AtomicFreeList() noexcept = default;
|
||||
AtomicFreeList(void* begin, void* end,
|
||||
size_t elementSize, size_t alignment, size_t extra) noexcept;
|
||||
AtomicFreeList(const FreeList& rhs) = delete;
|
||||
AtomicFreeList& operator=(const FreeList& rhs) = delete;
|
||||
|
||||
void* pop() noexcept {
|
||||
Node* const storage = mStorage;
|
||||
|
||||
HeadPtr currentHead = mHead.load();
|
||||
while (currentHead.offset >= 0) {
|
||||
// The value of "next" we load here might already contain application data if another
|
||||
// thread raced ahead of us. But in that case, the computed "newHead" will be discarded
|
||||
// since compare_exchange_weak fails. Then this thread will loop with the updated
|
||||
// value of currentHead, and try again.
|
||||
Node* const next = storage[currentHead.offset].next.load(std::memory_order_relaxed);
|
||||
const HeadPtr newHead{ next ? int32_t(next - storage) : -1, currentHead.tag + 1 };
|
||||
// In the rare case that the other thread that raced ahead of us already returned the
|
||||
// same mHead we just loaded, but it now has a different "next" value, the tag field will not
|
||||
// match, and compare_exchange_weak will fail and prevent that particular race condition.
|
||||
if (mHead.compare_exchange_weak(currentHead, newHead)) {
|
||||
// This assert needs to occur after we have validated that there was no race condition
|
||||
// Otherwise, next might already contain application data, if another thread
|
||||
// raced ahead of us after we loaded mHead, but before we loaded mHead->next.
|
||||
assert(!next || next >= storage);
|
||||
break;
|
||||
}
|
||||
}
|
||||
void* p = (currentHead.offset >= 0) ? (storage + currentHead.offset) : nullptr;
|
||||
assert(!p || p >= storage);
|
||||
return p;
|
||||
}
|
||||
|
||||
void push(void* p) noexcept {
|
||||
Node* const storage = mStorage;
|
||||
assert(p && p >= storage);
|
||||
Node* const node = static_cast<Node*>(p);
|
||||
HeadPtr currentHead = mHead.load();
|
||||
HeadPtr newHead = { int32_t(node - storage), currentHead.tag + 1 };
|
||||
do {
|
||||
newHead.tag = currentHead.tag + 1;
|
||||
Node* const n = (currentHead.offset >= 0) ? (storage + currentHead.offset) : nullptr;
|
||||
node->next.store(n, std::memory_order_relaxed);
|
||||
} while(!mHead.compare_exchange_weak(currentHead, newHead));
|
||||
}
|
||||
|
||||
void* getFirst() noexcept {
|
||||
return mStorage + mHead.load(std::memory_order_relaxed).offset;
|
||||
}
|
||||
|
||||
private:
|
||||
struct Node {
|
||||
// This should be a regular (non-atomic) pointer, but this causes TSAN to complain
|
||||
// about a data-race that exists but is benin. We always use this atomic<> in
|
||||
// relaxed mode.
|
||||
// The data race TSAN complains about is when a pop() is interrupted by a
|
||||
// pop() + push() just after mHead->next is read -- it appears as though it is written
|
||||
// without synchronization (by the push), however in that case, the pop's CAS will fail
|
||||
// and things will auto-correct.
|
||||
//
|
||||
// Pop() |
|
||||
// | |
|
||||
// read head->next |
|
||||
// | pop()
|
||||
// | |
|
||||
// | read head->next
|
||||
// | CAS, tag++
|
||||
// | |
|
||||
// | push()
|
||||
// | |
|
||||
// [TSAN: data-race here] write head->next
|
||||
// | CAS, tag++
|
||||
// CAS fails
|
||||
// |
|
||||
// read head->next
|
||||
// |
|
||||
// CAS, tag++
|
||||
//
|
||||
std::atomic<Node*> next;
|
||||
};
|
||||
|
||||
// This struct is using a 32-bit offset into the arena rather than
|
||||
// a direct pointer, because together with the 32-bit tag, it needs to
|
||||
// fit into 8 bytes. If it was any larger, it would not be possible to
|
||||
// access it atomically.
|
||||
struct alignas(8) HeadPtr {
|
||||
int32_t offset;
|
||||
uint32_t tag;
|
||||
};
|
||||
|
||||
std::atomic<HeadPtr> mHead{};
|
||||
|
||||
Node* mStorage = nullptr;
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
template <
|
||||
size_t ELEMENT_SIZE,
|
||||
size_t ALIGNMENT = alignof(std::max_align_t),
|
||||
size_t OFFSET = 0,
|
||||
typename FREELIST = FreeList>
|
||||
class PoolAllocator {
|
||||
static_assert(ELEMENT_SIZE >= sizeof(void*), "ELEMENT_SIZE must accommodate at least a pointer");
|
||||
public:
|
||||
// our allocator concept
|
||||
void* alloc(size_t size = ELEMENT_SIZE,
|
||||
size_t alignment = ALIGNMENT, size_t offset = OFFSET) noexcept {
|
||||
assert(size <= ELEMENT_SIZE);
|
||||
assert(alignment <= ALIGNMENT);
|
||||
assert(offset == OFFSET);
|
||||
return mFreeList.pop();
|
||||
}
|
||||
|
||||
void free(void* p, size_t = ELEMENT_SIZE) noexcept {
|
||||
mFreeList.push(p);
|
||||
}
|
||||
|
||||
constexpr size_t getSize() const noexcept { return ELEMENT_SIZE; }
|
||||
|
||||
PoolAllocator(void* begin, void* end) noexcept
|
||||
: mFreeList(begin, end, ELEMENT_SIZE, ALIGNMENT, OFFSET) {
|
||||
}
|
||||
|
||||
template <typename AREA>
|
||||
explicit PoolAllocator(const AREA& area) noexcept
|
||||
: PoolAllocator(area.begin(), area.end()) {
|
||||
}
|
||||
|
||||
// Allocators can't be copied
|
||||
PoolAllocator(const PoolAllocator& rhs) = delete;
|
||||
PoolAllocator& operator=(const PoolAllocator& rhs) = delete;
|
||||
|
||||
// Allocators can be moved
|
||||
PoolAllocator(PoolAllocator&& rhs) = default;
|
||||
PoolAllocator& operator=(PoolAllocator&& rhs) = default;
|
||||
|
||||
PoolAllocator() noexcept = default;
|
||||
~PoolAllocator() noexcept = default;
|
||||
|
||||
// API specific to this allocator
|
||||
|
||||
void *getCurrent() noexcept {
|
||||
return mFreeList.getFirst();
|
||||
}
|
||||
|
||||
private:
|
||||
FREELIST mFreeList;
|
||||
};
|
||||
|
||||
#define UTILS_MAX(a,b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
template <typename T, size_t OFFSET = 0>
|
||||
using ObjectPoolAllocator = PoolAllocator<sizeof(T),
|
||||
UTILS_MAX(alignof(FreeList), alignof(T)), OFFSET>;
|
||||
|
||||
template <typename T, size_t OFFSET = 0>
|
||||
using ThreadSafeObjectPoolAllocator = PoolAllocator<sizeof(T),
|
||||
UTILS_MAX(alignof(FreeList), alignof(T)), OFFSET, AtomicFreeList>;
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Areas
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace AreaPolicy {
|
||||
|
||||
class StaticArea {
|
||||
public:
|
||||
StaticArea() noexcept = default;
|
||||
|
||||
StaticArea(void* b, void* e) noexcept
|
||||
: mBegin(b), mEnd(e) {
|
||||
}
|
||||
|
||||
~StaticArea() noexcept = default;
|
||||
|
||||
StaticArea(const StaticArea& rhs) = default;
|
||||
StaticArea& operator=(const StaticArea& rhs) = default;
|
||||
StaticArea(StaticArea&& rhs) noexcept = default;
|
||||
StaticArea& operator=(StaticArea&& rhs) noexcept = default;
|
||||
|
||||
void* data() const noexcept { return mBegin; }
|
||||
void* begin() const noexcept { return mBegin; }
|
||||
void* end() const noexcept { return mEnd; }
|
||||
size_t size() const noexcept { return uintptr_t(mEnd) - uintptr_t(mBegin); }
|
||||
|
||||
friend void swap(StaticArea& lhs, StaticArea& rhs) noexcept {
|
||||
using std::swap;
|
||||
swap(lhs.mBegin, rhs.mBegin);
|
||||
swap(lhs.mEnd, rhs.mEnd);
|
||||
}
|
||||
|
||||
private:
|
||||
void* mBegin = nullptr;
|
||||
void* mEnd = nullptr;
|
||||
};
|
||||
|
||||
class HeapArea {
|
||||
public:
|
||||
HeapArea() noexcept = default;
|
||||
|
||||
explicit HeapArea(size_t size) {
|
||||
if (size) {
|
||||
// TODO: policy committing memory
|
||||
mBegin = malloc(size);
|
||||
mEnd = pointermath::add(mBegin, size);
|
||||
}
|
||||
}
|
||||
|
||||
~HeapArea() noexcept {
|
||||
// TODO: policy for returning memory to system
|
||||
free(mBegin);
|
||||
}
|
||||
|
||||
HeapArea(const HeapArea& rhs) = delete;
|
||||
HeapArea& operator=(const HeapArea& rhs) = delete;
|
||||
HeapArea(HeapArea&& rhs) noexcept = delete;
|
||||
HeapArea& operator=(HeapArea&& rhs) noexcept = delete;
|
||||
|
||||
void* data() const noexcept { return mBegin; }
|
||||
void* begin() const noexcept { return mBegin; }
|
||||
void* end() const noexcept { return mEnd; }
|
||||
size_t size() const noexcept { return uintptr_t(mEnd) - uintptr_t(mBegin); }
|
||||
|
||||
friend void swap(HeapArea& lhs, HeapArea& rhs) noexcept {
|
||||
using std::swap;
|
||||
swap(lhs.mBegin, rhs.mBegin);
|
||||
swap(lhs.mEnd, rhs.mEnd);
|
||||
}
|
||||
|
||||
private:
|
||||
void* mBegin = nullptr;
|
||||
void* mEnd = nullptr;
|
||||
};
|
||||
|
||||
} // namespace AreaPolicy
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Policies
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace LockingPolicy {
|
||||
|
||||
struct NoLock {
|
||||
void lock() noexcept { }
|
||||
void unlock() noexcept { }
|
||||
};
|
||||
|
||||
using SpinLock = utils::SpinLock;
|
||||
using Mutex = utils::Mutex;
|
||||
|
||||
} // namespace LockingPolicy
|
||||
|
||||
|
||||
namespace TrackingPolicy {
|
||||
|
||||
// default no-op tracker
|
||||
struct Untracked {
|
||||
Untracked() noexcept = default;
|
||||
Untracked(const char* name, void* base, size_t size) noexcept { }
|
||||
void onAlloc(void* p, size_t size, size_t alignment, size_t extra) noexcept { }
|
||||
void onFree(void* p, size_t = 0) noexcept { }
|
||||
void onReset() noexcept { }
|
||||
void onRewind(void* addr) noexcept { }
|
||||
};
|
||||
|
||||
// This just track the max memory usage and logs it in the destructor
|
||||
struct HighWatermark {
|
||||
HighWatermark() noexcept = default;
|
||||
HighWatermark(const char* name, void* base, size_t size) noexcept
|
||||
: mName(name), mBase(base), mSize(uint32_t(size)) { }
|
||||
~HighWatermark() noexcept;
|
||||
void onAlloc(void* p, size_t size, size_t alignment, size_t extra) noexcept;
|
||||
void onFree(void* p, size_t size) noexcept;
|
||||
void onReset() noexcept;
|
||||
void onRewind(void const* addr) noexcept;
|
||||
protected:
|
||||
const char* mName = nullptr;
|
||||
void* mBase = nullptr;
|
||||
uint32_t mSize = 0;
|
||||
uint32_t mCurrent = 0;
|
||||
uint32_t mHighWaterMark = 0;
|
||||
};
|
||||
|
||||
// This just fills buffers with known values to help catch uninitialized access and use after free.
|
||||
struct Debug {
|
||||
Debug() noexcept = default;
|
||||
Debug(const char* name, void* base, size_t size) noexcept
|
||||
: mName(name), mBase(base), mSize(uint32_t(size)) { }
|
||||
void onAlloc(void* p, size_t size, size_t alignment, size_t extra) noexcept;
|
||||
void onFree(void* p, size_t size) noexcept;
|
||||
void onReset() noexcept;
|
||||
void onRewind(void* addr) noexcept;
|
||||
protected:
|
||||
const char* mName = nullptr;
|
||||
void* mBase = nullptr;
|
||||
uint32_t mSize = 0;
|
||||
};
|
||||
|
||||
struct DebugAndHighWatermark : protected HighWatermark, protected Debug {
|
||||
DebugAndHighWatermark() noexcept = default;
|
||||
DebugAndHighWatermark(const char* name, void* base, size_t size) noexcept
|
||||
: HighWatermark(name, base, size), Debug(name, base, size) { }
|
||||
void onAlloc(void* p, size_t size, size_t alignment, size_t extra) noexcept {
|
||||
HighWatermark::onAlloc(p, size, alignment, extra);
|
||||
Debug::onAlloc(p, size, alignment, extra);
|
||||
}
|
||||
void onFree(void* p, size_t size) noexcept {
|
||||
HighWatermark::onFree(p, size);
|
||||
Debug::onFree(p, size);
|
||||
}
|
||||
void onReset() noexcept {
|
||||
HighWatermark::onReset();
|
||||
Debug::onReset();
|
||||
}
|
||||
void onRewind(void* addr) noexcept {
|
||||
HighWatermark::onRewind(addr);
|
||||
Debug::onRewind(addr);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace TrackingPolicy
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Arenas
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
template<typename AllocatorPolicy, typename LockingPolicy,
|
||||
typename TrackingPolicy = TrackingPolicy::Untracked,
|
||||
typename AreaPolicy = AreaPolicy::HeapArea>
|
||||
class Arena {
|
||||
public:
|
||||
|
||||
Arena() = default;
|
||||
|
||||
// construct an arena with a name and forward argument to its allocator
|
||||
template<typename ... ARGS>
|
||||
Arena(const char* name, size_t size, ARGS&& ... args)
|
||||
: mArenaName(name),
|
||||
mArea(size),
|
||||
mAllocator(mArea, std::forward<ARGS>(args) ... ),
|
||||
mListener(name, mArea.data(), mArea.size()) {
|
||||
}
|
||||
|
||||
template<typename ... ARGS>
|
||||
Arena(const char* name, AreaPolicy&& area, ARGS&& ... args)
|
||||
: mArenaName(name),
|
||||
mArea(std::forward<AreaPolicy>(area)),
|
||||
mAllocator(mArea, std::forward<ARGS>(args) ... ),
|
||||
mListener(name, mArea.data(), mArea.size()) {
|
||||
}
|
||||
|
||||
// allocate memory from arena with given size and alignment
|
||||
// (acceptable size/alignment may depend on the allocator provided)
|
||||
void* alloc(size_t size, size_t alignment = alignof(std::max_align_t), size_t extra = 0) noexcept {
|
||||
std::lock_guard<LockingPolicy> guard(mLock);
|
||||
void* p = mAllocator.alloc(size, alignment, extra);
|
||||
mListener.onAlloc(p, size, alignment, extra);
|
||||
return p;
|
||||
}
|
||||
|
||||
// Allocate an array of trivially destructible objects
|
||||
// for safety, we disable the object-based alloc method if the object type is not
|
||||
// trivially destructible, since free() won't call the destructor and this is allocating
|
||||
// an array.
|
||||
template <typename T,
|
||||
typename = typename std::enable_if<std::is_trivially_destructible<T>::value>::type>
|
||||
T* alloc(size_t count, size_t alignment = alignof(T), size_t extra = 0) noexcept {
|
||||
return (T*)alloc(count * sizeof(T), alignment, extra);
|
||||
}
|
||||
|
||||
// return memory pointed by p to the arena
|
||||
// (actual behaviour may depend on allocator provided)
|
||||
void free(void* p) noexcept {
|
||||
if (p) {
|
||||
std::lock_guard<LockingPolicy> guard(mLock);
|
||||
mListener.onFree(p);
|
||||
mAllocator.free(p);
|
||||
}
|
||||
}
|
||||
|
||||
// some allocators require the size of the allocation for free
|
||||
void free(void* p, size_t size) noexcept {
|
||||
if (p) {
|
||||
std::lock_guard<LockingPolicy> guard(mLock);
|
||||
mListener.onFree(p, size);
|
||||
mAllocator.free(p, size);
|
||||
}
|
||||
}
|
||||
|
||||
// some allocators don't have a free() call, but a single reset() or rewind() instead
|
||||
void reset() noexcept {
|
||||
std::lock_guard<LockingPolicy> guard(mLock);
|
||||
mListener.onReset();
|
||||
mAllocator.reset();
|
||||
}
|
||||
|
||||
void* getCurrent() noexcept { return mAllocator.getCurrent(); }
|
||||
|
||||
void rewind(void *addr) noexcept {
|
||||
std::lock_guard<LockingPolicy> guard(mLock);
|
||||
mListener.onRewind(addr);
|
||||
mAllocator.rewind(addr);
|
||||
}
|
||||
|
||||
// Allocate and construct an object
|
||||
template<typename T, size_t ALIGN = alignof(T), typename... ARGS>
|
||||
T* make(ARGS&& ... args) noexcept {
|
||||
void* const p = this->alloc(sizeof(T), ALIGN);
|
||||
return p ? new(p) T(std::forward<ARGS>(args)...) : nullptr;
|
||||
}
|
||||
|
||||
// destroys an object created with make<T>() above, and frees associated memory
|
||||
template<typename T>
|
||||
void destroy(T* p) noexcept {
|
||||
if (p) {
|
||||
p->~T();
|
||||
this->free((void*)p, sizeof(T));
|
||||
}
|
||||
}
|
||||
|
||||
char const* getName() const noexcept { return mArenaName; }
|
||||
|
||||
AllocatorPolicy& getAllocator() noexcept { return mAllocator; }
|
||||
AllocatorPolicy const& getAllocator() const noexcept { return mAllocator; }
|
||||
|
||||
TrackingPolicy& getListener() noexcept { return mListener; }
|
||||
TrackingPolicy const& getListener() const noexcept { return mListener; }
|
||||
|
||||
AreaPolicy& getArea() noexcept { return mArea; }
|
||||
AreaPolicy const& getArea() const noexcept { return mArea; }
|
||||
|
||||
void setListener(TrackingPolicy listener) noexcept {
|
||||
std::swap(mListener, listener);
|
||||
}
|
||||
|
||||
template <typename ... ARGS>
|
||||
void emplaceListener(ARGS&& ... args) noexcept {
|
||||
mListener.~TrackingPolicy();
|
||||
new (&mListener) TrackingPolicy(std::forward<ARGS>(args)...);
|
||||
}
|
||||
|
||||
// An arena can't be copied
|
||||
Arena(Arena const& rhs) noexcept = delete;
|
||||
Arena& operator=(Arena const& rhs) noexcept = delete;
|
||||
|
||||
friend void swap(Arena& lhs, Arena& rhs) noexcept {
|
||||
using std::swap;
|
||||
swap(lhs.mArea, rhs.mArea);
|
||||
swap(lhs.mAllocator, rhs.mAllocator);
|
||||
swap(lhs.mLock, rhs.mLock);
|
||||
swap(lhs.mListener, rhs.mListener);
|
||||
swap(lhs.mArenaName, rhs.mArenaName);
|
||||
}
|
||||
|
||||
private:
|
||||
char const* mArenaName = nullptr;
|
||||
AreaPolicy mArea;
|
||||
// note: we should use something like compressed_pair for the members below
|
||||
AllocatorPolicy mAllocator;
|
||||
LockingPolicy mLock;
|
||||
TrackingPolicy mListener;
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
template<typename TrackingPolicy = TrackingPolicy::Untracked>
|
||||
using HeapArena = Arena<HeapAllocator, LockingPolicy::NoLock, TrackingPolicy>;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
// This doesn't implement our allocator concept, because it's too risky to use this as an allocator
|
||||
// in particular, doing ArenaScope<ArenaScope>.
|
||||
template<typename ARENA>
|
||||
class ArenaScope {
|
||||
|
||||
struct Finalizer {
|
||||
void (*finalizer)(void* p) = nullptr;
|
||||
Finalizer* next = nullptr;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
static void destruct(void* p) noexcept {
|
||||
static_cast<T*>(p)->~T();
|
||||
}
|
||||
|
||||
public:
|
||||
explicit ArenaScope(ARENA& allocator)
|
||||
: mArena(allocator), mRewind(allocator.getCurrent()) {
|
||||
}
|
||||
|
||||
ArenaScope& operator=(const ArenaScope& rhs) = delete;
|
||||
ArenaScope(ArenaScope&& rhs) noexcept = delete;
|
||||
ArenaScope& operator=(ArenaScope&& rhs) noexcept = delete;
|
||||
|
||||
~ArenaScope() {
|
||||
// run the finalizer chain
|
||||
Finalizer* head = mFinalizerHead;
|
||||
while (head) {
|
||||
void* p = pointermath::add(head, sizeof(Finalizer));
|
||||
head->finalizer(p);
|
||||
head = head->next;
|
||||
}
|
||||
// ArenaScope works only with Arena that implements rewind()
|
||||
mArena.rewind(mRewind);
|
||||
}
|
||||
|
||||
template<typename T, size_t ALIGN = alignof(T), typename... ARGS>
|
||||
T* make(ARGS&& ... args) noexcept {
|
||||
T* o = nullptr;
|
||||
if (std::is_trivially_destructible<T>::value) {
|
||||
o = mArena.template make<T, ALIGN>(std::forward<ARGS>(args)...);
|
||||
} else {
|
||||
void* const p = (Finalizer*)mArena.alloc(sizeof(T), ALIGN, sizeof(Finalizer));
|
||||
if (p != nullptr) {
|
||||
Finalizer* const f = static_cast<Finalizer*>(p) - 1;
|
||||
// constructor must be called before adding the dtor to the list
|
||||
// so that the ctor can allocate objects in a nested scope and have the
|
||||
// finalizers called in reverse order.
|
||||
o = new(p) T(std::forward<ARGS>(args)...);
|
||||
f->finalizer = &destruct<T>;
|
||||
f->next = mFinalizerHead;
|
||||
mFinalizerHead = f;
|
||||
}
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
void* allocate(size_t size, size_t alignment = 1) noexcept {
|
||||
return mArena.template alloc<uint8_t>(size, alignment, 0);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T* allocate(size_t size, size_t alignment = alignof(T), size_t extra = 0) noexcept {
|
||||
return mArena.template alloc<T>(size, alignment, extra);
|
||||
}
|
||||
|
||||
// use with caution
|
||||
ARENA& getAllocator() noexcept { return mArena; }
|
||||
|
||||
private:
|
||||
ARENA& mArena;
|
||||
void* mRewind = nullptr;
|
||||
Finalizer* mFinalizerHead = nullptr;
|
||||
};
|
||||
|
||||
|
||||
template <typename TYPE, typename ARENA>
|
||||
class STLAllocator {
|
||||
public:
|
||||
using value_type = TYPE;
|
||||
using pointer = TYPE*;
|
||||
using const_pointer = const TYPE*;
|
||||
using reference = TYPE&;
|
||||
using const_reference = const TYPE&;
|
||||
using size_type = std::size_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using propagate_on_container_move_assignment = std::true_type;
|
||||
using is_always_equal = std::true_type;
|
||||
|
||||
template<typename OTHER>
|
||||
struct rebind { using other = STLAllocator<OTHER, ARENA>; };
|
||||
|
||||
public:
|
||||
// we don't make this explicit, so that we can initialize a vector using a STLAllocator
|
||||
// from an Arena, avoiding to have to repeat the vector type.
|
||||
STLAllocator(ARENA& arena) : mArena(arena) { } // NOLINT(google-explicit-constructor)
|
||||
|
||||
template<typename U>
|
||||
explicit STLAllocator(STLAllocator<U, ARENA> const& rhs) : mArena(rhs.mArena) { }
|
||||
|
||||
TYPE* allocate(std::size_t n) {
|
||||
return static_cast<TYPE *>(mArena.alloc(n * sizeof(TYPE), alignof(TYPE)));
|
||||
}
|
||||
|
||||
void deallocate(TYPE* p, std::size_t n) {
|
||||
mArena.free(p, n * sizeof(TYPE));
|
||||
}
|
||||
|
||||
// these should be out-of-class friends, but this doesn't seem to work with some compilers
|
||||
// which complain about multiple definition each time a STLAllocator<> is instantiated.
|
||||
template <typename U, typename A>
|
||||
bool operator==(const STLAllocator<U, A>& rhs) const noexcept {
|
||||
return std::addressof(mArena) == std::addressof(rhs.mArena);
|
||||
}
|
||||
|
||||
template <typename U, typename A>
|
||||
bool operator!=(const STLAllocator<U, A>& rhs) const noexcept {
|
||||
return !operator==(rhs);
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename U, typename A>
|
||||
friend class STLAllocator;
|
||||
|
||||
ARENA& mArena;
|
||||
};
|
||||
|
||||
} // namespace utils
|
||||
|
||||
#endif // TNT_UTILS_ALLOCATOR_H
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user