From 9ccee73baca0fd7ecb95c90cb983133b737c6c55 Mon Sep 17 00:00:00 2001 From: Egor Yusov Date: Tue, 20 Oct 2015 20:46:28 -0700 Subject: Release v1.0.0 --- Common/interface/AdvancedMath.h | 127 ++++ Common/interface/BasicMath.h | 1344 ++++++++++++++++++++++++++++++++++ Common/interface/ComPtr.h | 43 ++ Common/interface/DataBlob.h | 53 ++ Common/interface/FileStream.h | 58 ++ Common/interface/Object.h | 79 ++ Common/interface/ReferenceCounters.h | 115 +++ 7 files changed, 1819 insertions(+) create mode 100644 Common/interface/AdvancedMath.h create mode 100644 Common/interface/BasicMath.h create mode 100644 Common/interface/ComPtr.h create mode 100644 Common/interface/DataBlob.h create mode 100644 Common/interface/FileStream.h create mode 100644 Common/interface/Object.h create mode 100644 Common/interface/ReferenceCounters.h (limited to 'Common/interface') diff --git a/Common/interface/AdvancedMath.h b/Common/interface/AdvancedMath.h new file mode 100644 index 00000000..c4af54ad --- /dev/null +++ b/Common/interface/AdvancedMath.h @@ -0,0 +1,127 @@ +/* Copyright 2015 Egor Yusov + * + * 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 + * + * 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 OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#pragma once + +#include "BasicMath.h" + +// Structure describing a plane +struct Plane3D +{ + float3 Normal; + float Distance; //Distance from the coordinate system origin to the plane along the normal direction +}; + +struct ViewFrustum +{ + Plane3D LeftPlane, RightPlane, BottomPlane, TopPlane, NearPlane, FarPlane; +}; + +// For OpenGL, matrix is still considered row-major. The only difference is that +// near clip plane is at -1, not 0. +inline void ExtractViewFrustumPlanesFromMatrix(const float4x4 &Matrix, ViewFrustum &ViewFrustum, bool bIsDirectX) +{ + // For more details, see Gribb G., Hartmann K., "Fast Extraction of Viewing Frustum Planes from the + // World-View-Projection Matrix" (the paper is available at + // http://gamedevs.org/uploads/fast-extraction-viewing-frustum-planes-from-world-view-projection-matrix.pdf) + + // Left clipping plane + ViewFrustum.LeftPlane.Normal.x = Matrix._14 + Matrix._11; + ViewFrustum.LeftPlane.Normal.y = Matrix._24 + Matrix._21; + ViewFrustum.LeftPlane.Normal.z = Matrix._34 + Matrix._31; + ViewFrustum.LeftPlane.Distance = Matrix._44 + Matrix._41; + + // Right clipping plane + ViewFrustum.RightPlane.Normal.x = Matrix._14 - Matrix._11; + ViewFrustum.RightPlane.Normal.y = Matrix._24 - Matrix._21; + ViewFrustum.RightPlane.Normal.z = Matrix._34 - Matrix._31; + ViewFrustum.RightPlane.Distance = Matrix._44 - Matrix._41; + + // Top clipping plane + ViewFrustum.TopPlane.Normal.x = Matrix._14 - Matrix._12; + ViewFrustum.TopPlane.Normal.y = Matrix._24 - Matrix._22; + ViewFrustum.TopPlane.Normal.z = Matrix._34 - Matrix._32; + ViewFrustum.TopPlane.Distance = Matrix._44 - Matrix._42; + + // Bottom clipping plane + ViewFrustum.BottomPlane.Normal.x = Matrix._14 + Matrix._12; + ViewFrustum.BottomPlane.Normal.y = Matrix._24 + Matrix._22; + ViewFrustum.BottomPlane.Normal.z = Matrix._34 + Matrix._32; + ViewFrustum.BottomPlane.Distance = Matrix._44 + Matrix._42; + + // Near clipping plane + if( bIsDirectX ) + { + // 0 <= z <= w + ViewFrustum.NearPlane.Normal.x = Matrix._13; + ViewFrustum.NearPlane.Normal.y = Matrix._23; + ViewFrustum.NearPlane.Normal.z = Matrix._33; + ViewFrustum.NearPlane.Distance = Matrix._43; + } + else + { + // -w <= z <= w + ViewFrustum.NearPlane.Normal.x = Matrix._14 + Matrix._13; + ViewFrustum.NearPlane.Normal.y = Matrix._24 + Matrix._23; + ViewFrustum.NearPlane.Normal.z = Matrix._34 + Matrix._33; + ViewFrustum.NearPlane.Distance = Matrix._44 + Matrix._43; + } + + // Far clipping plane + ViewFrustum.FarPlane.Normal.x = Matrix._14 - Matrix._13; + ViewFrustum.FarPlane.Normal.y = Matrix._24 - Matrix._23; + ViewFrustum.FarPlane.Normal.z = Matrix._34 - Matrix._33; + ViewFrustum.FarPlane.Distance = Matrix._44 - Matrix._43; +} + + + +struct BoundBox +{ + float fMinX, fMaxX, fMinY, fMaxY, fMinZ, fMaxZ; +}; + +// Tests if bounding box is visible by the camera +inline bool IBoxVisible(const ViewFrustum &ViewFrustum, const BoundBox &Box) +{ + Plane3D *pPlanes = (Plane3D *)&ViewFrustum; + // If bounding box is "behind" some plane, then it is invisible + // Otherwise it is treated as visible + for(int iViewFrustumPlane = 0; iViewFrustumPlane < 6; iViewFrustumPlane++) + { + Plane3D *pCurrPlane = pPlanes + iViewFrustumPlane; + float3 *pCurrNormal = &pCurrPlane->Normal; + float3 MaxPoint; + + MaxPoint.x = (pCurrNormal->x > 0) ? Box.fMaxX : Box.fMinX; + MaxPoint.y = (pCurrNormal->y > 0) ? Box.fMaxY : Box.fMinY; + MaxPoint.z = (pCurrNormal->z > 0) ? Box.fMaxZ : Box.fMinZ; + + float DMax = dot( MaxPoint, *pCurrNormal ) + pCurrPlane->Distance; + + if( DMax < 0 ) + return false; + } + + return true; +} diff --git a/Common/interface/BasicMath.h b/Common/interface/BasicMath.h new file mode 100644 index 00000000..95b35974 --- /dev/null +++ b/Common/interface/BasicMath.h @@ -0,0 +1,1344 @@ +/* Copyright 2015 Egor Yusov + * + * 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 + * + * 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 OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +//// PARTICULAR PURPOSE. +//// +//// Copyright (c) Microsoft Corporation. All rights reserved + +#pragma once + +#include "DebugUtilities.h" + +#define _USE_MATH_DEFINES +#include + +// This header defines math and matrix helper functions and structures used +// by DirectX SDK samples. + +// Common Constants + +#define PI_F 3.1415927f + +// Template Vector & Matrix Classes +template struct Matrix4x4; +template struct Vector4; + +template struct Vector2 +{ + union + { + struct + { + T x; + T y; + }; + struct + { + T r; + T g; + }; + struct + { + T u; + T v; + }; + }; + + + Vector2 operator-(const Vector2 &right)const + { + return Vector2(x - right.x, y - right.y); + } + + Vector2& operator-=(const Vector2 &right) + { + x -= right.x; + y -= right.y; + return *this; + } + + Vector2 operator-()const + { + return Vector2(-x, -y); + } + + Vector2 operator+(const Vector2 &right)const + { + return Vector2(x + right.x, y + right.y); + } + + Vector2& operator+=(const Vector2 &right) + { + x += right.x; + y += right.y; + return *this; + } + + Vector2 operator*(T s)const + { + return Vector2(x * s, y * s); + } + + Vector2 operator*(const Vector2 &right)const + { + return Vector2(x * right.x, y * right.y); + } + + Vector2& operator*=( const Vector2 &right) + { + x *= right.x; + y *= right.y; + return *this; + } + + Vector2& operator*=( T s) + { + x *= s; + y *= s; + return *this; + } + + Vector2 operator/(const Vector2 &right)const + { + return Vector2(x / right.x, y / right.y); + } + + Vector2& operator/=( const Vector2 &right) + { + x /= right.x; + y /= right.y; + return *this; + } + + Vector2 operator/(T s)const + { + return Vector2(x / s, y / s); + } + + Vector2& operator/=( T s) + { + x /= s; + y /= s; + return *this; + } + + bool operator == (const Vector2 &right)const + { + return x == right.x && y == right.y; + } + + bool operator != (const Vector2 &right)const + { + return !(*this == right); + } + + Vector2 operator < ( const Vector2 &right )const + { + return Vector2(x < right.x ? static_cast(1) : static_cast(0), + y < right.y ? static_cast(1) : static_cast(0)); + } + + Vector2 operator > ( const Vector2 &right )const + { + return Vector2(x > right.x ? static_cast(1) : static_cast(0), + y > right.y ? static_cast(1) : static_cast(0)); + } + + Vector2 operator <= ( const Vector2 &right )const + { + return Vector2(x <= right.x ? static_cast(1) : static_cast(0), + y <= right.y ? static_cast(1) : static_cast(0)); + } + + Vector2 operator >= ( const Vector2 &right )const + { + return Vector2(x >= right.x ? static_cast(1) : static_cast(0), + y >= right.y ? static_cast(1) : static_cast(0)); + } + + T& operator[](size_t index) + { + return reinterpret_cast(this)[index]; + } + + const T& operator[](size_t index)const + { + return reinterpret_cast(this)[index]; + } + + explicit + Vector2(T _x = 0, T _y = 0) : x(_x), y(_y) { } +}; + +template +Vector2 operator*(T s, const Vector2 &a) +{ + return a * s; +} + + +template struct Vector3 +{ + union + { + struct + { + T x; + T y; + T z; + }; + struct + { + T r; + T g; + T b; + }; + struct + { + T u; + T v; + T w; + }; + }; + + + Vector3 operator-( const Vector3 &right )const + { + return Vector3(x - right.x, y - right.y, z - right.z); + } + + Vector3 operator-()const + { + return Vector3(-x, -y, -z); + } + + Vector3& operator-=(const Vector3 &right) + { + x -= right.x; + y -= right.y; + z -= right.z; + return *this; + } + + Vector3 operator+( const Vector3 &right )const + { + return Vector3(x + right.x, y + right.y, z + right.z); + } + + Vector3& operator+=(const Vector3 &right) + { + x += right.x; + y += right.y; + z += right.z; + return *this; + } + + Vector3 operator*( T s )const + { + return Vector3(x * s, y * s, z * s); + } + + Vector3& operator*=( T s) + { + x *= s; + y *= s; + z *= s; + return *this; + } + + Vector3 operator*( const Vector3 &right )const + { + return Vector3(x * right.x, y * right.y, z * right.z); + } + + Vector3 operator* (const Matrix4x4& m)const + { + Vector4 out4 = Vector4(x, y, z, 1) * m; + return Vector3(out4.x / out4.w, out4.y / out4.w, out4.z / out4.w) ; + } + + Vector3& operator*=( const Vector3 &right) + { + x *= right.x; + y *= right.y; + z *= right.z; + return *this; + } + + Vector3 operator/ ( T s)const + { + return Vector3(x / s, y / s, z / s); + } + + Vector3& operator/=( T s) + { + x /= s; + y /= s; + z /= s; + return *this; + } + + Vector3 operator/( const Vector3 &right )const + { + return Vector3(x / right.x, y / right.y, z / right.z); + } + + Vector3& operator/=( const Vector3 &right) + { + x /= right.x; + y /= right.y; + z /= right.z; + return *this; + } + + bool operator == (const Vector3 &right)const + { + return x == right.x && y == right.y && z == right.z; + } + + bool operator != (const Vector3 &right)const + { + return !(*this == right); + } + + Vector3 operator < ( const Vector3 &right )const + { + return Vector3(x < right.x ? static_cast(1) : static_cast(0), + y < right.y ? static_cast(1) : static_cast(0), + z < right.z ? static_cast(1) : static_cast(0)); + } + + Vector3 operator > ( const Vector3 &right )const + { + return Vector3(x > right.x ? static_cast(1) : static_cast(0), + y > right.y ? static_cast(1) : static_cast(0), + z > right.z ? static_cast(1) : static_cast(0)); + } + + Vector3 operator <= ( const Vector3 &right )const + { + return Vector3(x <= right.x ? static_cast(1) : static_cast(0), + y <= right.y ? static_cast(1) : static_cast(0), + z <= right.z ? static_cast(1) : static_cast(0)); + } + + Vector3 operator >= ( const Vector3 &right )const + { + return Vector3(x >= right.x ? static_cast(1) : static_cast(0), + y >= right.y ? static_cast(1) : static_cast(0), + z >= right.z ? static_cast(1) : static_cast(0)); + } + + T& operator[](size_t index) + { + return reinterpret_cast(this)[index]; + } + + const T& operator[](size_t index)const + { + return reinterpret_cast(this)[index]; + } + + explicit + Vector3(T _x = 0, T _y = 0, T _z = 0) : x(_x), y(_y), z(_z) { } + + operator Vector2()const{return Vector2(x,y);} +}; + +template +Vector3 operator*(T s, const Vector3 &a) +{ + return a * s; +} + + +template struct Vector4 +{ + union + { + struct + { + T x; + T y; + T z; + T w; + }; + struct + { + T r; + T g; + T b; + T a; + }; + }; + + Vector4 operator-( const Vector4 &right)const + { + return Vector4(x - right.x, y - right.y, z - right.z, w - right.w); + } + + Vector4 operator-()const + { + return Vector4(-x, -y, -z, -w); + } + + Vector4& operator-=(const Vector4 &right) + { + x -= right.x; + y -= right.y; + z -= right.z; + w -= right.w; + return *this; + } + + Vector4 operator+( const Vector4 &right)const + { + return Vector4(x + right.x, y + right.y, z + right.z, w + right.w); + } + + Vector4& operator+=(const Vector4 &right) + { + x += right.x; + y += right.y; + z += right.z; + w += right.w; + return *this; + } + + Vector4 operator*( T s)const + { + return Vector4(x * s, y * s, z * s, w * s); + } + + Vector4& operator*=( T s) + { + x *= s; + y *= s; + z *= s; + w *= s; + return *this; + } + + Vector4 operator*( const Vector4 &right)const + { + return Vector4(x * right.x, y * right.y, z * right.z, w * right.w); + } + + Vector4& operator*=( const Vector4 &right) + { + x *= right.x; + y *= right.y; + z *= right.z; + w *= right.w; + return *this; + } + + Vector4 operator/( T s)const + { + return Vector4(x / s, y / s, z / s, w / s); + } + + Vector4& operator/=( T s) + { + x /= s; + y /= s; + z /= s; + w /= s; + return *this; + } + + Vector4 operator/( const Vector4 &right)const + { + return Vector4(x / right.x, y / right.y, z / right.z, w / right.w); + } + + Vector4& operator/=( const Vector4 &right) + { + x /= right.x; + y /= right.y; + z /= right.z; + w /= right.w; + return *this; + } + + bool operator == (const Vector4 &right)const + { + return x == right.x && y == right.y && z == right.z && w == right.w; + } + + bool operator != (const Vector4 &right)const + { + return !(*this == right); + } + + Vector4 operator*(const Matrix4x4& m)const + { + Vector4 out; + out[0] = x * m[0][0] + y * m[1][0] + z * m[2][0] + w * m[3][0]; + out[1] = x * m[0][1] + y * m[1][1] + z * m[2][1] + w * m[3][1]; + out[2] = x * m[0][2] + y * m[1][2] + z * m[2][2] + w * m[3][2]; + out[3] = x * m[0][3] + y * m[1][3] + z * m[2][3] + w * m[3][3]; + return out; + } + + Vector4& operator = (const Vector3 &v3) + { + x = v3.x; + y = v3.y; + z = v3.z; + w = 1; + return *this; + } + Vector4& operator = (const Vector4 &) = default; + + Vector4 operator < ( const Vector4 &right )const + { + return Vector4(x < right.x ? static_cast(1) : static_cast(0), + y < right.y ? static_cast(1) : static_cast(0), + z < right.z ? static_cast(1) : static_cast(0), + w < right.w ? static_cast(1) : static_cast(0)); + } + + Vector4 operator > ( const Vector4 &right )const + { + return Vector4(x > right.x ? static_cast(1) : static_cast(0), + y > right.y ? static_cast(1) : static_cast(0), + z > right.z ? static_cast(1) : static_cast(0), + w > right.w ? static_cast(1) : static_cast(0)); + } + + Vector4 operator <= ( const Vector4 &right )const + { + return Vector4(x <= right.x ? static_cast(1) : static_cast(0), + y <= right.y ? static_cast(1) : static_cast(0), + z <= right.z ? static_cast(1) : static_cast(0), + w <= right.w ? static_cast(1) : static_cast(0)); + } + + Vector4 operator >= ( const Vector4 &right )const + { + return Vector4(x >= right.x ? static_cast(1) : static_cast(0), + y >= right.y ? static_cast(1) : static_cast(0), + z >= right.z ? static_cast(1) : static_cast(0), + w >= right.w ? static_cast(1) : static_cast(0)); + } + + T& operator[](size_t index) + { + return reinterpret_cast(this)[index]; + } + + const T& operator[](size_t index)const + { + return reinterpret_cast(this)[index]; + } + + explicit + Vector4(T _x = 0, T _y = 0, T _z = 0, T _w = 0) : x(_x), y(_y), z(_z), w(_w) { } +}; + + +template +Vector4 operator*(T s, const Vector4 &a) +{ + return a * s; +} + +template struct Matrix3x3 +{ + union + { + struct + { + T _11; T _12; T _13; + T _21; T _22; T _23; + T _31; T _32; T _33; + }; + struct + { + T _m00; T _m01; T _m02; + T _m10; T _m11; T _m12; + T _m20; T _m21; T _m22; + }; + }; + + explicit + Matrix3x3(T value = 0) + { + _11 = _12 = _13 =value; + _21 = _22 = _23 =value; + _31 = _32 = _33 =value; + } + + explicit + Matrix3x3( + T i11, T i12, T i13, + T i21, T i22, T i23, + T i31, T i32, T i33 ) + { + _11 = i11; _12 = i12; _13 = i13; + _21 = i21; _22 = i22; _23 = i23; + _31 = i31; _32 = i32; _33 = i33; + } + + bool operator == (const Matrix3x3 &r)const + { + for( int i = 0; i < 3; ++i ) + for( int j = 0; i < 3; ++i ) + if( (*this)[i][j] != r[i][j] ) + return false; + + return true; + } + + bool operator != (const Matrix3x3 &r)const + { + return !(*this == r); + } + + T* operator[](size_t index) + { + return &(reinterpret_cast(this)[index*3]); + } + + const T* operator[](size_t index)const + { + return &(reinterpret_cast(this)[index*3]); + } + + Matrix3x3& operator *=(T s) + { + for( int i = 0; i < 9; ++i ) + (reinterpret_cast(this))[i] *= s; + + return *this; + } +}; + +template struct Matrix4x4 +{ + union + { + struct + { + T _11; T _12; T _13; T _14; + T _21; T _22; T _23; T _24; + T _31; T _32; T _33; T _34; + T _41; T _42; T _43; T _44; + }; + struct + { + T _m00; T _m01; T _m02; T _m03; + T _m10; T _m11; T _m12; T _m13; + T _m20; T _m21; T _m22; T _m23; + T _m30; T _m31; T _m32; T _m33; + }; + }; + + explicit + Matrix4x4(T value = 0) + { + _11 = _12 = _13 = _14 = value; + _21 = _22 = _23 = _24 = value; + _31 = _32 = _33 = _34 = value; + _41 = _42 = _43 = _44 = value; + } + + explicit + Matrix4x4( + T i11, T i12, T i13, T i14, + T i21, T i22, T i23, T i24, + T i31, T i32, T i33, T i34, + T i41, T i42, T i43, T i44 + ) + { + _11 = i11; _12 = i12; _13 = i13; _14 = i14; + _21 = i21; _22 = i22; _23 = i23; _24 = i24; + _31 = i31; _32 = i32; _33 = i33; _34 = i34; + _41 = i41; _42 = i42; _43 = i43; _44 = i44; + } + + bool operator == (const Matrix4x4 &r)const + { + for( int i = 0; i < 4; ++i ) + for( int j = 0; i < 4; ++i ) + if( (*this)[i][j] != r[i][j] ) + return false; + + return true; + } + + bool operator != (const Matrix4x4 &r)const + { + return !(*this == r); + } + + T* operator[](size_t index) + { + return &(reinterpret_cast(this)[index*4]); + } + + const T* operator[](size_t index)const + { + return &(reinterpret_cast(this)[index*4]); + } + + Matrix4x4& operator *=(T s) + { + for( int i = 0; i < 16; ++i ) + (reinterpret_cast(this))[i] *= s; + + return *this; + } +}; + +// Template Vector Operations + + +template +T dot(const Vector2 &a, const Vector2 &b) +{ + return a.x * b.x + a.y * b.y; +} + +template +T dot(const Vector3 &a, const Vector3 &b) +{ + return a.x * b.x + a.y * b.y + a.z * b.z; +} + +template +T dot(const Vector4 &a, const Vector4 &b) +{ + return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; +} + +template +auto length(const VectorType &a)->decltype(dot(a,a)) +{ + return sqrt( dot(a,a) ); +} + + +template +Vector3 min(const Vector3 &a, const Vector3 &b) +{ + return Vector3( std::min(a.x, b.x), std::min(a.y, b.y), std::min(a.z, b.z) ); +} + +template +Vector4 min(const Vector4 &a, const Vector4 &b) +{ + return Vector4( std::min(a.x, b.x), std::min(a.y, b.y), std::min(a.z, b.z), std::min(a.w, b.w) ); +} + +template +Vector3 max(const Vector3 &a, const Vector3 &b) +{ + return Vector3( std::max(a.x, b.x), std::max(a.y, b.y), std::max(a.z, b.z) ); +} + +template +Vector4 max(const Vector4 &a, const Vector4 &b) +{ + return Vector4( std::max(a.x, b.x), std::max(a.y, b.y), std::max(a.z, b.z), std::max(a.w, b.w) ); +} + +template +Vector2 abs(const Vector2 &a) +{ + // WARNING: abs() on gcc is for integers only! + return Vector2( a.x < 0 ? -a.x : a.x, + a.y < 0 ? -a.y : a.y); +} + +template +Vector3 abs(const Vector3 &a) +{ + // WARNING: abs() on gcc is for integers only! + return Vector3( a.x < 0 ? -a.x : a.x, + a.y < 0 ? -a.y : a.y, + a.z < 0 ? -a.z : a.z); +} + +template +Vector4 abs(const Vector4 &a) +{ + // WARNING: abs() on gcc is for integers only! + return Vector4( a.x < 0 ? -a.x : a.x, + a.y < 0 ? -a.y : a.y, + a.z < 0 ? -a.z : a.z, + a.w < 0 ? -a.w : a.w); +} + + +template +Vector3 cross(const Vector3 &a, const Vector3 &b) +{ + // | i j k | + // | a.x a.y a.z | + // | b.x b.y b.z | + return Vector3((a.y*b.z)-(a.z*b.y), (a.z*b.x)-(a.x*b.z), (a.x*b.y)-(a.y*b.x)); +} + +template +VectorType normalize(const VectorType &a) +{ + auto len = length(a); + return a / len; +} + + +// Template Matrix Operations + +template +Matrix4x4 transposeMatrix(const Matrix4x4 &m) +{ + return Matrix4x4( + m._11, m._21, m._31, m._41, + m._12, m._22, m._32, m._42, + m._13, m._23, m._33, m._43, + m._14, m._24, m._34, m._44 + ); +} + +template +Matrix4x4 mul(const Matrix4x4 &m1, const Matrix4x4 &m2) +{ + Matrix4x4 mOut; + + for (int i = 0; i < 4; i++) + { + for (int j = 0; j < 4; j++) + { + for (int k = 0; k < 4; k++) + { + mOut[i][j] += m1[i][k] * m2[k][j]; + } + } + } + + return mOut; +} + +template +Matrix4x4 operator* (const Matrix4x4 &m1, const Matrix4x4 &m2) +{ + return mul( m1, m2 ); +} + + + +template +Matrix3x3 transposeMatrix(const Matrix3x3 &m) +{ + return Matrix3x3( + m._11, m._21, m._31, + m._12, m._22, m._32, + m._13, m._23, m._33 + ); +} + +template +Matrix3x3 mul(const Matrix3x3 &m1, const Matrix3x3 &m2) +{ + Matrix3x3 mOut; + + for (int i = 0; i < 3; i++) + { + for (int j = 0; j < 3; j++) + { + for (int k = 0; k < 3; k++) + { + mOut[i][j] += m1[i][k] * m2[k][j]; + } + } + } + + return mOut; +} + +template +Matrix3x3 operator* (const Matrix3x3 &m1, const Matrix3x3 &m2) +{ + return mul( m1, m2 ); +} + +// Common HLSL-compatible vector typedefs + +typedef unsigned int uint; + +typedef Vector2 float2; +typedef Vector3 float3; +typedef Vector4 float4; + +typedef Matrix4x4 float4x4; +typedef Matrix3x3 float3x3; + +// Standard Matrix Intializers + +inline float4x4 identityMatrix() +{ + return float4x4(1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1); +} + +inline float4x4 translationMatrix(float x, float y, float z) +{ + return float4x4 (1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + x, y, z, 1); +} + +inline float4x4 translationMatrix( const float3 &v ) +{ + return translationMatrix( v.x, v.y, v.z ); +} + + +inline float4x4 scaleMatrix(float x, float y, float z) +{ + return float4x4(x, 0, 0, 0, + 0, y, 0, 0, + 0, 0, z, 0, + 0, 0, 0, 1); +} + +inline float4x4 rotationX(float degreeX) +{ + float angleInRadians = degreeX * (PI_F / 180.0f); + + float sinAngle = sinf(angleInRadians); + float cosAngle = cosf(angleInRadians); + + float4x4 mOut; + + UNSUPPORTED("This function is not tested, it might be incorrect.") + mOut._11 = 1.0f; mOut._12 = 0.0f; mOut._13 = 0.0f; mOut._14 = 0.0f; + mOut._21 = 0.0f; mOut._22 = cosAngle; mOut._23 = -sinAngle; mOut._24 = 0.0f; + mOut._31 = 0.0f; mOut._32 = sinAngle; mOut._33 = cosAngle; mOut._34 = 0.0f; + mOut._41 = 0.0f; mOut._42 = 0.0f; mOut._43 = 0.0f; mOut._44 = 1.0f; + + return mOut; +} + +inline float4x4 rotationY(float degreeY) +{ + float angleInRadians = degreeY * (PI_F / 180.0f); + + float sinAngle = sinf(angleInRadians); + float cosAngle = cosf(angleInRadians); + + float4x4 mOut; + + UNSUPPORTED("This function is not tested, it might be incorrect.") + mOut._11 = cosAngle; mOut._12 = 0.0f; mOut._13 = sinAngle; mOut._14 = 0.0f; + mOut._21 = 0.0f; mOut._22 = 1.0f; mOut._23 = 0.0f; mOut._24 = 0.0f; + mOut._31 = -sinAngle; mOut._32 = 0.0f; mOut._33 = cosAngle; mOut._34 = 0.0f; + mOut._41 = 0.0f; mOut._42 = 0.0f; mOut._43 = 0.0f; mOut._44 = 1.0f; + + return mOut; +} + +inline float4x4 rotationZ(float degreeZ) +{ + float angleInRadians = degreeZ * (PI_F / 180.0f); + + float sinAngle = sinf(angleInRadians); + float cosAngle = cosf(angleInRadians); + + float4x4 mOut; + + UNSUPPORTED("This function is not tested, it might be incorrect.") + mOut._11 = cosAngle; mOut._12 = -sinAngle; mOut._13 = 0.0f; mOut._14 = 0.0f; + mOut._21 = sinAngle; mOut._22 = cosAngle; mOut._23 = 0.0f; mOut._24 = 0.0f; + mOut._31 = 0.0f; mOut._32 = 0.0f; mOut._33 = 1.0f; mOut._34 = 0.0f; + mOut._41 = 0.0f; mOut._42 = 0.0f; mOut._43 = 0.0f; mOut._44 = 1.0f; + + return mOut; +} + +// 3D Rotation matrix for an arbitrary axis specified by x, y and z +inline float4x4 rotationArbitrary(float3 axis, float degree) +{ + UNSUPPORTED("This function is not tested, it might be incorrect") + + axis = normalize(axis); + + float angleInRadians = degree * (PI_F / 180.0f); + + float sinAngle = sinf(angleInRadians); + float cosAngle = cosf(angleInRadians); + float oneMinusCosAngle = 1 - cosAngle; + + float4x4 mOut; + + mOut._11 = 1.0f + oneMinusCosAngle * (axis.x * axis.x - 1.0f); + mOut._12 = axis.z * sinAngle + oneMinusCosAngle * axis.x * axis.y; + mOut._13 = -axis.y * sinAngle + oneMinusCosAngle * axis.x * axis.z; + mOut._41 = 0.0f; + + mOut._21 = -axis.z * sinAngle + oneMinusCosAngle * axis.y * axis.x; + mOut._22 = 1.0f + oneMinusCosAngle * (axis.y * axis.y - 1.0f); + mOut._23 = axis.x * sinAngle + oneMinusCosAngle * axis.y * axis.z; + mOut._24 = 0.0f; + + mOut._31 = axis.y * sinAngle + oneMinusCosAngle * axis.z * axis.x; + mOut._32 = -axis.x * sinAngle + oneMinusCosAngle * axis.z * axis.y; + mOut._33 = 1.0f + oneMinusCosAngle * (axis.z * axis.z - 1.0f); + mOut._34 = 0.0f; + + mOut._41 = 0.0f; + mOut._42 = 0.0f; + mOut._43 = 0.0f; + mOut._44 = 1.0f; + + return mOut; +} + +inline float4x4 ViewMatrixFromBasis( const float3 &f3X, const float3 &f3Y, const float3 &f3Z ) +{ + return float4x4( f3X.x, f3Y.x, f3Z.x, 0, + f3X.y, f3Y.y, f3Z.y, 0, + f3X.z, f3Y.z, f3Z.z, 0, + 0, 0, 0, 1); +} + +inline void SetNearFarClipPlanes( float4x4 &ProjMatrix, float zNear, float zFar, bool bIsDirectX ) +{ + if( bIsDirectX ) + { + ProjMatrix._33 = zFar / (zFar - zNear); + ProjMatrix._43 = -zNear * zFar / (zFar - zNear); + ProjMatrix._34 = 1; + } + else + { + // https://www.opengl.org/sdk/docs/man2/xhtml/gluPerspective.xml + // http://www.terathon.com/gdc07_lengyel.pdf + // Note that OpenGL uses right-handed coordinate system, where + // camera is looking in negative z direction: + // OO + // |__|<-------------------- + // -z +z + // Consequently, OpenGL projection matrix given by these two + // references inverts z axis. + + // We do not need to do this, because we use DX coordinate + // system for the camera space. Thus we need to invert the + // sign of the values in the third column in the matrix + // from the references: + + ProjMatrix._33 = -(-(zFar + zNear) / (zFar - zNear)); + ProjMatrix._43 = -2.0f * zNear * zFar / (zFar - zNear); + ProjMatrix._34 = -(-1); + } +} + +inline void GetNearFarPlaneFromProjMatrix( const float4x4 &ProjMatrix, float &zNear, float &zFar, bool bIsDirectX ) +{ + if( bIsDirectX ) + { + zNear = -ProjMatrix._43 / ProjMatrix._33; + zFar = ProjMatrix._33 / (ProjMatrix._33 - 1) * zNear; + } + else + { + zNear = ProjMatrix._43 / (-1.f - ProjMatrix._33); + zFar = ProjMatrix._43 / (+1.f - ProjMatrix._33); + } +} + +inline float4x4 Projection(float fov, float aspectRatio, float zNear, float zFar, bool bIsDirectX) // Left-handed projection +{ + float4x4 mOut; + float yScale = 1.0f / tan(fov / 2.0f); + float xScale = yScale / aspectRatio; + mOut._11 = xScale; + mOut._22 = yScale; + + SetNearFarClipPlanes( mOut, zNear, zFar, bIsDirectX ); + + return mOut; +} + + +struct Quaternion +{ + float q[4]; +}; + +inline Quaternion RotationFromAxisAngle(const float3& axis, float angle) +{ + Quaternion out; + float norm = length(axis); + float sina2 = sin(0.5f * angle); + out.q[0] = sina2 * axis[0] / norm; + out.q[1] = sina2 * axis[1] / norm; + out.q[2] = sina2 * axis[2] / norm; + out.q[3] = cos(0.5f * angle); + return out; +} + +inline void AxisAngleFromRotation(float3& outAxis, float& outAngle, const Quaternion& quat) +{ + float sina2 = sqrt(quat.q[0]*quat.q[0] + quat.q[1]*quat.q[1] + quat.q[2]*quat.q[2]); + outAngle = 2.0f * atan2(sina2, quat.q[3]); + float r = (sina2 > 0) ? (1.0f / sina2) : 0; + outAxis[0] = r * quat.q[0]; + outAxis[1] = r * quat.q[1]; + outAxis[2] = r * quat.q[2]; +} + +inline float4x4 QuaternionToMatrix(const Quaternion& quat) +{ + float4x4 out; + float yy2 = 2.0f * quat.q[1] * quat.q[1]; + float xy2 = 2.0f * quat.q[0] * quat.q[1]; + float xz2 = 2.0f * quat.q[0] * quat.q[2]; + float yz2 = 2.0f * quat.q[1] * quat.q[2]; + float zz2 = 2.0f * quat.q[2] * quat.q[2]; + float wz2 = 2.0f * quat.q[3] * quat.q[2]; + float wy2 = 2.0f * quat.q[3] * quat.q[1]; + float wx2 = 2.0f * quat.q[3] * quat.q[0]; + float xx2 = 2.0f * quat.q[0] * quat.q[0]; + out[0][0] = - yy2 - zz2 + 1.0f; + out[0][1] = xy2 + wz2; + out[0][2] = xz2 - wy2; + out[0][3] = 0; + out[1][0] = xy2 - wz2; + out[1][1] = - xx2 - zz2 + 1.0f; + out[1][2] = yz2 + wx2; + out[1][3] = 0; + out[2][0] = xz2 + wy2; + out[2][1] = yz2 - wx2; + out[2][2] = - xx2 - yy2 + 1.0f; + out[2][3] = 0; + out[3][0] = out[3][1] = out[3][2] = 0; + out[3][3] = 1; + return out; +} + +inline float determinant( const float3x3& m ) +{ + float det = 0.f; + det += m._11 * (m._22*m._33 - m._32*m._23); + det -= m._12 * (m._21*m._33 - m._31*m._23); + det += m._13 * (m._21*m._32 - m._31*m._22); + return det; +} + + +inline float determinant( const float4x4& m ) +{ + float det = 0.f; + + det += m._11 * determinant( + float3x3 ( m._22,m._23,m._24, + m._32,m._33,m._34, + m._42,m._43,m._44) ); + + det -= m._12 * determinant( + float3x3( m._21,m._23,m._24, + m._31,m._33,m._34, + m._41,m._43,m._44) ); + + det += m._13 * determinant( + float3x3( m._21,m._22,m._24, + m._31,m._32,m._34, + m._41,m._42,m._44) ); + + det -= m._14 * determinant( + float3x3( m._21,m._22,m._23, + m._31,m._32,m._33, + m._41,m._42,m._43) ); + + return det; +} + +inline float4x4 inverseMatrix(const float4x4& m) +{ + float4x4 inv; + + // row 1 + inv._11 = determinant( + float3x3( m._22, m._23, m._24, + m._32, m._33, m._34, + m._42, m._43, m._44 ) ); + + inv._12 = -determinant( + float3x3( m._21, m._23, m._24, + m._31, m._33, m._34, + m._41, m._43, m._44) ); + + inv._13 = determinant( + float3x3 ( m._21, m._22, m._24, + m._31, m._32, m._34, + m._41, m._42, m._44) ); + + inv._14 = -determinant( + float3x3 ( m._21, m._22, m._23, + m._31, m._32, m._33, + m._41, m._42, m._43) ); + + + // row 2 + inv._21 = -determinant( + float3x3( m._12, m._13, m._14, + m._32, m._33, m._34, + m._42, m._43, m._44) ); + + inv._22 = determinant( + float3x3( m._11, m._13, m._14, + m._31, m._33, m._34, + m._41, m._43, m._44) ); + + inv._23 = -determinant( + float3x3( m._11, m._12, m._14, + m._31, m._32, m._34, + m._41, m._42, m._44) ); + + inv._24 = determinant( + float3x3( m._11, m._12, m._13, + m._31, m._32, m._33, + m._41, m._42, m._43) ); + + + // row 3 + inv._31 = determinant( + float3x3( m._12,m._13,m._14, + m._22,m._23,m._24, + m._42,m._43,m._44) ); + + inv._32 = -determinant( + float3x3( m._11,m._13,m._14, + m._21,m._23,m._24, + m._41,m._43,m._44) ); + + inv._33 = determinant( + float3x3( m._11,m._12,m._14, + m._21,m._22,m._24, + m._41,m._42,m._44) ); + + inv._34 = -determinant( + float3x3( m._11,m._12,m._13, + m._21,m._22,m._23, + m._41,m._42,m._43) ); + + // row 4 + inv._41 = -determinant( + float3x3( m._12, m._13, m._14, + m._22, m._23, m._24, + m._32, m._33, m._34) ); + + inv._42 = determinant( + float3x3( m._11, m._13, m._14, + m._21, m._23, m._24, + m._31, m._33, m._34) ); + + inv._43 = -determinant( + float3x3( m._11, m._12, m._14, + m._21, m._22, m._24, + m._31, m._32, m._34) ); + + inv._44 = determinant( + float3x3( m._11, m._12, m._13, + m._21, m._22, m._23, + m._31, m._32, m._33) ); + + auto det = m._11 * inv._11 + m._12 * inv._12 + m._13 * inv._13 + m._14 * inv._14; + inv = transposeMatrix(inv); + inv *= 1.0f/det; + + return inv; +} + +namespace std +{ + template + Vector2 max( const Vector2 &Left, const Vector2 &Right ) + { + return Vector2( + std::max( Left.x, Right.x ), + std::max( Left.y, Right.y ) + ); + } + + template + Vector3 max( const Vector3 &Left, const Vector3 &Right ) + { + return Vector3( + std::max( Left.x, Right.x ), + std::max( Left.y, Right.y ), + std::max( Left.z, Right.z ) + ); + } + + template + Vector4 max( const Vector4 &Left, const Vector4 &Right ) + { + return Vector4( + std::max( Left.x, Right.x ), + std::max( Left.y, Right.y ), + std::max( Left.z, Right.z ), + std::max( Left.w, Right.w ) + ); + } + + + template + Vector2 min( const Vector2 &Left, const Vector2 &Right ) + { + return Vector2( + std::min( Left.x, Right.x ), + std::min( Left.y, Right.y ) + ); + } + + template + Vector3 min( const Vector3 &Left, const Vector3 &Right ) + { + return Vector3( + std::min( Left.x, Right.x ), + std::min( Left.y, Right.y ), + std::min( Left.z, Right.z ) + ); + } + + template + Vector4 min( const Vector4 &Left, const Vector4 &Right ) + { + return Vector4( + std::min( Left.x, Right.x ), + std::min( Left.y, Right.y ), + std::min( Left.z, Right.z ), + std::min( Left.w, Right.w ) + ); + } +} \ No newline at end of file diff --git a/Common/interface/ComPtr.h b/Common/interface/ComPtr.h new file mode 100644 index 00000000..94e4b1f2 --- /dev/null +++ b/Common/interface/ComPtr.h @@ -0,0 +1,43 @@ +/* Copyright 2015 Egor Yusov + * + * 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 + * + * 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 OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#pragma once + +/// \file +/// Defines Diligent::CComPtr + +#include "RefCntAutoPtr.h" + +namespace Diligent +{ + template + class BlockAddRefReleaseCOM : public T + { + private: + virtual decltype( reinterpret_cast(nullptr)->AddRef() ) STDMETHODCALLTYPE AddRef()override = 0; + virtual decltype( reinterpret_cast(nullptr)->Release() ) STDMETHODCALLTYPE Release()override = 0; + }; + + template + using CComPtr = Diligent::RefCntAutoPtr; +} diff --git a/Common/interface/DataBlob.h b/Common/interface/DataBlob.h new file mode 100644 index 00000000..2940f1d3 --- /dev/null +++ b/Common/interface/DataBlob.h @@ -0,0 +1,53 @@ +/* Copyright 2015 Egor Yusov + * + * 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 + * + * 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 OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#pragma once + +/// \file +/// Defines Diligent::IDataBlob interface + +#include "Object.h" + +namespace Diligent +{ + +// {F578FF0D-ABD2-4514-9D32-7CB454D4A73B} +static const Diligent::INTERFACE_ID IID_DataBlob = +{ 0xf578ff0d, 0xabd2, 0x4514, { 0x9d, 0x32, 0x7c, 0xb4, 0x54, 0xd4, 0xa7, 0x3b } }; + +/// Base interface for a file stream +class IDataBlob : public Diligent::IObject +{ +public: + + /// Sets the size of the internal data buffer + virtual void Resize( size_t NewSize ) = 0; + + /// Returns the size of the internal data buffer + virtual size_t GetSize() = 0; + + /// Returns the pointer to the internal data buffer + virtual void* GetDataPtr() = 0; +}; + +} diff --git a/Common/interface/FileStream.h b/Common/interface/FileStream.h new file mode 100644 index 00000000..1263ef42 --- /dev/null +++ b/Common/interface/FileStream.h @@ -0,0 +1,58 @@ +/* Copyright 2015 Egor Yusov + * + * 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 + * + * 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 OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#pragma once + +/// \file +/// Defines Diligent::IFileStream interface + +#include "Object.h" +#include "FileSystem.h" +#include "DataBlob.h" + +namespace Diligent +{ + +/// IFileStream interface unique identifier +// {E67F386C-6A5A-4A24-A0CE-C66435465D41} +static const Diligent::INTERFACE_ID IID_FileStream = +{ 0xe67f386c, 0x6a5a, 0x4a24, { 0xa0, 0xce, 0xc6, 0x64, 0x35, 0x46, 0x5d, 0x41 } }; + +/// Base interface for a file stream +class IFileStream : public IObject +{ +public: + /// Reads data from the stream + virtual bool Read( void *Data, size_t BufferSize ) = 0; + + virtual void Read( Diligent::IDataBlob *pData ) = 0; + + /// Writes data to the stream + virtual bool Write( const void *Data, size_t Size ) = 0; + + virtual size_t GetSize() = 0; + + virtual bool IsValid() = 0; +}; + +} diff --git a/Common/interface/Object.h b/Common/interface/Object.h new file mode 100644 index 00000000..b404889e --- /dev/null +++ b/Common/interface/Object.h @@ -0,0 +1,79 @@ +/* Copyright 2015 Egor Yusov + * + * 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 + * + * 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 OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#pragma once + +/// \file +/// Defines Diligent::IObject interface + +#include "InterfaceID.h" +#include "Atomics.h" +#include "ReferenceCounters.h" + +namespace Diligent +{ + +/// Base interface for all dynamic objects in the engine +class IObject +{ +public: + /// Queries the specific interface. + + /// \param [in] IID - Unique identifier of the requested interface. + /// \param [out] ppInterface - Memory address where the pointer to the requested interface will be written. + /// If the interface is not supported, null pointer will be returned. + /// \remark The method increments the number of strong references by 1. The interface must be + /// released by a call to Release() method when it is no longer needed. + virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface ) = 0; + + + /// Increments the number of strong references by 1. + + /// \remark This method is equivalent to GetReferenceCounters()->AddStrongRef().\n + /// The method is thread-safe and does not require explicit synchronization. + /// \return The number of strong references after incrementing the counter. + /// \note In a multithreaded environment, the returned number may not be reliable + /// as other threads may simultaneously change the actual value of the counter. + virtual Atomics::Long AddRef() = 0; + + + /// Decrements the number of strong references by 1 and destroys the object when the + /// counter reaches zero. + + /// \remark This method is equivalent to GetReferenceCounters()->ReleaseStrongRef().\n + /// The method is thread-safe and does not require explicit synchronization. + /// \return The number of strong references after decrementing the counter. + /// \note In a multithreaded environment, the returned number may not be reliable + /// as other threads may simultaneously change the actual value of the counter. + /// The only reliable value is 0 as the object is destroyed when the last + /// strong reference is released. + virtual Atomics::Long Release() = 0; + + + /// Returns the pointer to IReferenceCounters interface of the associated + /// reference counters object. The metod does *NOT* increment + /// the number of strong references to the returned object. + virtual IReferenceCounters* GetReferenceCounters()const = 0; +}; + +} diff --git a/Common/interface/ReferenceCounters.h b/Common/interface/ReferenceCounters.h new file mode 100644 index 00000000..ffef91d5 --- /dev/null +++ b/Common/interface/ReferenceCounters.h @@ -0,0 +1,115 @@ +/* Copyright 2015 Egor Yusov + * + * 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 + * + * 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 OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#pragma once + +/// \file +/// Defines Diligent::IReferenceCounters interface + +#include "InterfaceID.h" +#include "Atomics.h" + +namespace Diligent +{ + +/// Base interface for a reference counter object that stores the number of strong and +/// weak references and the pointer to the object. It is necessary to separate reference +/// counters from the object to support weak pointers. +class IReferenceCounters +{ +public: + /// Increments the number of strong references by 1. + + /// \return The number of strong references after incrementing the counter. + /// \remark The method is thread-safe and does not require explicit synchronization. + /// \note In a multithreaded environment, the returned number may not be reliable + /// as other threads may simultaneously change the actual value of the counter. + virtual Atomics::Long AddStrongRef() = 0; + + + /// Decrements the number of strong references by 1 and destroys the referenced object + /// when the counter reaches zero. If there are no more weak references, destroys the + /// reference counters object itself. + + /// \return The number of strong references after decrementing the counter. + /// \remark The referenced object is destroyed when the last strong reference is released.\n + /// If there are no more weak references, the reference counters object itself is + /// also destroyed.\n + /// The method is thread-safe and does not require explicit synchronization. + /// \note In a multithreaded environment, the returned number may not be reliable + /// as other threads may simultaneously change the actual value of the counter. + /// The only reliable value is 0 as the object is destroyed when the last + /// strong reference is released. + virtual Atomics::Long ReleaseStrongRef() = 0; + + + /// Increments the number of weak references by 1. + + /// \return The number of weak references after incrementing the counter. + /// \remark The method is thread-safe and does not require explicit synchronization. + /// \note In a multithreaded environment, the returned number may not be reliable + /// as other threads may simultaneously change the actual value of the counter. + virtual Atomics::Long AddWeakRef() = 0; + + + /// Decrements the number of weak references by 1. If there are no more strong and weak + /// references, destroys the reference counters object itself. + + /// \return The number of weak references after decrementing the counter. + /// \remark The method is thread-safe and does not require explicit synchronization. + /// \note In a multithreaded environment, the returned number may not be reliable + /// as other threads may simultaneously change the actual value of the counter. + virtual Atomics::Long ReleaseWeakRef() = 0; + + + /// Gets the pointer to the IUnknown interface of the referenced object. + + /// \param [out] ppObject - Memory address where the pointer to the object + /// will be stored. + /// \remark If the object was destroyed, nullptr will be written to *ppObject. + /// If the object was not released, the pointer to the object's IUnknown interface + /// will be stored. In this case, the number of strong references to the object + /// will be incremented by 1.\n + /// The method is thread-safe and does not require explicit synchronization. + virtual void GetObject(class IObject **ppObject) = 0; + + + /// Returns the number of outstanding strong references. + + /// \return The number of strong references. + /// \note In a multithreaded environment, the returned number may not be reliable + /// as other threads may simultaneously change the actual value of the counter. + /// The only reliable value is 0 as the object is destroyed when the last + /// strong reference is released. + virtual Atomics::Long GetNumStrongRefs()const = 0; + + + /// Returns the number of outstanding weak references. + + /// \return The number of weak references. + /// \note In a multithreaded environment, the returned number may not be reliable + /// as other threads may simultaneously change the actual value of the counter. + virtual Atomics::Long GetNumWeakRefs()const = 0; +}; + +} -- cgit v1.2.3