remove IntegralConstant hack
This commit is contained in:
parent
dc5dea6d21
commit
f8ab9a3b59
|
|
@ -66,39 +66,39 @@ inline AABB aabb_for_minmax( const Vector3& min, const Vector3& max ){
|
|||
return aabb;
|
||||
}
|
||||
|
||||
template<typename Index>
|
||||
template<size_t Index>
|
||||
class AABBExtend
|
||||
{
|
||||
public:
|
||||
static void apply( AABB& aabb, const Vector3& point ){
|
||||
float displacement = point[Index::VALUE] - aabb.origin[Index::VALUE];
|
||||
float half_difference = static_cast<float>( 0.5 * ( fabs( displacement ) - aabb.extents[Index::VALUE] ) );
|
||||
float displacement = point[Index] - aabb.origin[Index];
|
||||
float half_difference = static_cast<float>( 0.5 * ( fabs( displacement ) - aabb.extents[Index] ) );
|
||||
if ( half_difference > 0.0f ) {
|
||||
aabb.origin[Index::VALUE] += ( displacement >= 0.0f ) ? half_difference : -half_difference;
|
||||
aabb.extents[Index::VALUE] += half_difference;
|
||||
aabb.origin[Index] += ( displacement >= 0.0f ) ? half_difference : -half_difference;
|
||||
aabb.extents[Index] += half_difference;
|
||||
}
|
||||
}
|
||||
static void apply( AABB& aabb, const AABB& other ){
|
||||
float displacement = other.origin[Index::VALUE] - aabb.origin[Index::VALUE];
|
||||
float difference = other.extents[Index::VALUE] - aabb.extents[Index::VALUE];
|
||||
float displacement = other.origin[Index] - aabb.origin[Index];
|
||||
float difference = other.extents[Index] - aabb.extents[Index];
|
||||
if ( fabs( displacement ) > fabs( difference ) ) {
|
||||
float half_difference = static_cast<float>( 0.5 * ( fabs( displacement ) + difference ) );
|
||||
if ( half_difference > 0.0f ) {
|
||||
aabb.origin[Index::VALUE] += ( displacement >= 0.0f ) ? half_difference : -half_difference;
|
||||
aabb.extents[Index::VALUE] += half_difference;
|
||||
aabb.origin[Index] += ( displacement >= 0.0f ) ? half_difference : -half_difference;
|
||||
aabb.extents[Index] += half_difference;
|
||||
}
|
||||
}
|
||||
else if ( difference > 0.0f ) {
|
||||
aabb.origin[Index::VALUE] = other.origin[Index::VALUE];
|
||||
aabb.extents[Index::VALUE] = other.extents[Index::VALUE];
|
||||
aabb.origin[Index] = other.origin[Index];
|
||||
aabb.extents[Index] = other.extents[Index];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
inline void aabb_extend_by_point( AABB& aabb, const Vector3& point ){
|
||||
AABBExtend< IntegralConstant<0> >::apply( aabb, point );
|
||||
AABBExtend< IntegralConstant<1> >::apply( aabb, point );
|
||||
AABBExtend< IntegralConstant<2> >::apply( aabb, point );
|
||||
AABBExtend< 0 >::apply( aabb, point );
|
||||
AABBExtend< 1 >::apply( aabb, point );
|
||||
AABBExtend< 2 >::apply( aabb, point );
|
||||
}
|
||||
|
||||
inline void aabb_extend_by_point_safe( AABB& aabb, const Vector3& point ){
|
||||
|
|
@ -124,9 +124,9 @@ public:
|
|||
};
|
||||
|
||||
inline void aabb_extend_by_aabb( AABB& aabb, const AABB& other ){
|
||||
AABBExtend< IntegralConstant<0> >::apply( aabb, other );
|
||||
AABBExtend< IntegralConstant<1> >::apply( aabb, other );
|
||||
AABBExtend< IntegralConstant<2> >::apply( aabb, other );
|
||||
AABBExtend< 0 >::apply( aabb, other );
|
||||
AABBExtend< 1 >::apply( aabb, other );
|
||||
AABBExtend< 2 >::apply( aabb, other );
|
||||
}
|
||||
|
||||
inline void aabb_extend_by_aabb_safe( AABB& aabb, const AABB& other ){
|
||||
|
|
@ -145,26 +145,26 @@ inline void aabb_extend_by_vec3( AABB& aabb, const Vector3& extension ){
|
|||
|
||||
|
||||
|
||||
template<typename Index>
|
||||
template<size_t Index>
|
||||
inline bool aabb_intersects_point_dimension( const AABB& aabb, const Vector3& point ){
|
||||
return fabs( point[Index::VALUE] - aabb.origin[Index::VALUE] ) < aabb.extents[Index::VALUE];
|
||||
return fabs( point[Index] - aabb.origin[Index] ) < aabb.extents[Index];
|
||||
}
|
||||
|
||||
inline bool aabb_intersects_point( const AABB& aabb, const Vector3& point ){
|
||||
return aabb_intersects_point_dimension< IntegralConstant<0> >( aabb, point )
|
||||
&& aabb_intersects_point_dimension< IntegralConstant<1> >( aabb, point )
|
||||
&& aabb_intersects_point_dimension< IntegralConstant<2> >( aabb, point );
|
||||
return aabb_intersects_point_dimension< 0 >( aabb, point )
|
||||
&& aabb_intersects_point_dimension< 1 >( aabb, point )
|
||||
&& aabb_intersects_point_dimension< 2 >( aabb, point );
|
||||
}
|
||||
|
||||
template<typename Index>
|
||||
template<size_t Index>
|
||||
inline bool aabb_intersects_aabb_dimension( const AABB& aabb, const AABB& other ){
|
||||
return fabs( other.origin[Index::VALUE] - aabb.origin[Index::VALUE] ) < ( aabb.extents[Index::VALUE] + other.extents[Index::VALUE] );
|
||||
return fabs( other.origin[Index] - aabb.origin[Index] ) < ( aabb.extents[Index] + other.extents[Index] );
|
||||
}
|
||||
|
||||
inline bool aabb_intersects_aabb( const AABB& aabb, const AABB& other ){
|
||||
return aabb_intersects_aabb_dimension< IntegralConstant<0> >( aabb, other )
|
||||
&& aabb_intersects_aabb_dimension< IntegralConstant<1> >( aabb, other )
|
||||
&& aabb_intersects_aabb_dimension< IntegralConstant<2> >( aabb, other );
|
||||
return aabb_intersects_aabb_dimension< 0 >( aabb, other )
|
||||
&& aabb_intersects_aabb_dimension< 1 >( aabb, other )
|
||||
&& aabb_intersects_aabb_dimension< 2 >( aabb, other );
|
||||
}
|
||||
|
||||
inline unsigned int aabb_classify_plane( const AABB& aabb, const Plane3& plane ){
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
#include <math/matrix.h>
|
||||
|
||||
|
||||
template<typename I, typename Degree>
|
||||
template<int I, int Degree>
|
||||
struct BernsteinPolynomial
|
||||
{
|
||||
static double apply( double t ){
|
||||
|
|
@ -38,14 +38,8 @@ struct BernsteinPolynomial
|
|||
}
|
||||
};
|
||||
|
||||
typedef IntegralConstant<0> Zero;
|
||||
typedef IntegralConstant<1> One;
|
||||
typedef IntegralConstant<2> Two;
|
||||
typedef IntegralConstant<3> Three;
|
||||
typedef IntegralConstant<4> Four;
|
||||
|
||||
template<>
|
||||
struct BernsteinPolynomial<Zero, Zero>
|
||||
struct BernsteinPolynomial<0, 0>
|
||||
{
|
||||
static double apply( double t ){
|
||||
return 1;
|
||||
|
|
@ -53,7 +47,7 @@ struct BernsteinPolynomial<Zero, Zero>
|
|||
};
|
||||
|
||||
template<>
|
||||
struct BernsteinPolynomial<Zero, One>
|
||||
struct BernsteinPolynomial<0, 1>
|
||||
{
|
||||
static double apply( double t ){
|
||||
return 1 - t;
|
||||
|
|
@ -61,7 +55,7 @@ struct BernsteinPolynomial<Zero, One>
|
|||
};
|
||||
|
||||
template<>
|
||||
struct BernsteinPolynomial<One, One>
|
||||
struct BernsteinPolynomial<1, 1>
|
||||
{
|
||||
static double apply( double t ){
|
||||
return t;
|
||||
|
|
@ -69,7 +63,7 @@ struct BernsteinPolynomial<One, One>
|
|||
};
|
||||
|
||||
template<>
|
||||
struct BernsteinPolynomial<Zero, Two>
|
||||
struct BernsteinPolynomial<0, 2>
|
||||
{
|
||||
static double apply( double t ){
|
||||
return ( 1 - t ) * ( 1 - t );
|
||||
|
|
@ -77,7 +71,7 @@ struct BernsteinPolynomial<Zero, Two>
|
|||
};
|
||||
|
||||
template<>
|
||||
struct BernsteinPolynomial<One, Two>
|
||||
struct BernsteinPolynomial<1, 2>
|
||||
{
|
||||
static double apply( double t ){
|
||||
return 2 * ( 1 - t ) * t;
|
||||
|
|
@ -85,7 +79,7 @@ struct BernsteinPolynomial<One, Two>
|
|||
};
|
||||
|
||||
template<>
|
||||
struct BernsteinPolynomial<Two, Two>
|
||||
struct BernsteinPolynomial<2, 2>
|
||||
{
|
||||
static double apply( double t ){
|
||||
return t * t;
|
||||
|
|
@ -93,7 +87,7 @@ struct BernsteinPolynomial<Two, Two>
|
|||
};
|
||||
|
||||
template<>
|
||||
struct BernsteinPolynomial<Zero, Three>
|
||||
struct BernsteinPolynomial<0, 3>
|
||||
{
|
||||
static double apply( double t ){
|
||||
return ( 1 - t ) * ( 1 - t ) * ( 1 - t );
|
||||
|
|
@ -101,7 +95,7 @@ struct BernsteinPolynomial<Zero, Three>
|
|||
};
|
||||
|
||||
template<>
|
||||
struct BernsteinPolynomial<One, Three>
|
||||
struct BernsteinPolynomial<1, 3>
|
||||
{
|
||||
static double apply( double t ){
|
||||
return 3 * ( 1 - t ) * ( 1 - t ) * t;
|
||||
|
|
@ -109,7 +103,7 @@ struct BernsteinPolynomial<One, Three>
|
|||
};
|
||||
|
||||
template<>
|
||||
struct BernsteinPolynomial<Two, Three>
|
||||
struct BernsteinPolynomial<2, 3>
|
||||
{
|
||||
static double apply( double t ){
|
||||
return 3 * ( 1 - t ) * t * t;
|
||||
|
|
@ -117,7 +111,7 @@ struct BernsteinPolynomial<Two, Three>
|
|||
};
|
||||
|
||||
template<>
|
||||
struct BernsteinPolynomial<Three, Three>
|
||||
struct BernsteinPolynomial<3, 3>
|
||||
{
|
||||
static double apply( double t ){
|
||||
return t * t * t;
|
||||
|
|
@ -131,22 +125,22 @@ inline Vector3 CubicBezier_evaluate( const Vector3* firstPoint, double t ){
|
|||
double denominator = 0;
|
||||
|
||||
{
|
||||
double weight = BernsteinPolynomial<Zero, Three>::apply( t );
|
||||
double weight = BernsteinPolynomial<0, 3>::apply( t );
|
||||
result += vector3_scaled( *firstPoint++, weight );
|
||||
denominator += weight;
|
||||
}
|
||||
{
|
||||
double weight = BernsteinPolynomial<One, Three>::apply( t );
|
||||
double weight = BernsteinPolynomial<1, 3>::apply( t );
|
||||
result += vector3_scaled( *firstPoint++, weight );
|
||||
denominator += weight;
|
||||
}
|
||||
{
|
||||
double weight = BernsteinPolynomial<Two, Three>::apply( t );
|
||||
double weight = BernsteinPolynomial<2, 3>::apply( t );
|
||||
result += vector3_scaled( *firstPoint++, weight );
|
||||
denominator += weight;
|
||||
}
|
||||
{
|
||||
double weight = BernsteinPolynomial<Three, Three>::apply( t );
|
||||
double weight = BernsteinPolynomial<3, 3>::apply( t );
|
||||
result += vector3_scaled( *firstPoint++, weight );
|
||||
denominator += weight;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,13 @@
|
|||
|
||||
#include <math/matrix.h>
|
||||
|
||||
/// \brief A compile-time-constant integer.
|
||||
template<int VALUE_>
|
||||
struct IntegralConstant
|
||||
{
|
||||
enum unnamed_ { VALUE = VALUE_ };
|
||||
};
|
||||
|
||||
template<typename Value>
|
||||
class Literal
|
||||
{
|
||||
|
|
|
|||
|
|
@ -64,27 +64,27 @@ const ClipResult c_CLIP_LT_Z = 0x10; // 010000
|
|||
const ClipResult c_CLIP_GT_Z = 0x20; // 100000
|
||||
const ClipResult c_CLIP_FAIL = 0x3F; // 111111
|
||||
|
||||
template<typename Index>
|
||||
template<size_t Index>
|
||||
class Vector4ClipLT
|
||||
{
|
||||
public:
|
||||
static bool compare( const Vector4& self ){
|
||||
return self[Index::VALUE] < self[3];
|
||||
return self[Index] < self[3];
|
||||
}
|
||||
static double scale( const Vector4& self, const Vector4& other ){
|
||||
return ( self[Index::VALUE] - self[3] ) / ( other[3] - other[Index::VALUE] );
|
||||
return ( self[Index] - self[3] ) / ( other[3] - other[Index] );
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Index>
|
||||
template<size_t Index>
|
||||
class Vector4ClipGT
|
||||
{
|
||||
public:
|
||||
static bool compare( const Vector4& self ){
|
||||
return self[Index::VALUE] > -self[3];
|
||||
return self[Index] > -self[3];
|
||||
}
|
||||
static double scale( const Vector4& self, const Vector4& other ){
|
||||
return ( self[Index::VALUE] + self[3] ) / ( -other[3] - other[Index::VALUE] );
|
||||
return ( self[Index] + self[3] ) / ( -other[3] - other[Index] );
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -131,12 +131,12 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
#define CLIP_X_LT_W( p ) ( Vector4ClipLT< IntegralConstant<0> >::compare( p ) )
|
||||
#define CLIP_X_GT_W( p ) ( Vector4ClipGT< IntegralConstant<0> >::compare( p ) )
|
||||
#define CLIP_Y_LT_W( p ) ( Vector4ClipLT< IntegralConstant<1> >::compare( p ) )
|
||||
#define CLIP_Y_GT_W( p ) ( Vector4ClipGT< IntegralConstant<1> >::compare( p ) )
|
||||
#define CLIP_Z_LT_W( p ) ( Vector4ClipLT< IntegralConstant<2> >::compare( p ) )
|
||||
#define CLIP_Z_GT_W( p ) ( Vector4ClipGT< IntegralConstant<2> >::compare( p ) )
|
||||
#define CLIP_X_LT_W( p ) ( Vector4ClipLT< 0 >::compare( p ) )
|
||||
#define CLIP_X_GT_W( p ) ( Vector4ClipGT< 0 >::compare( p ) )
|
||||
#define CLIP_Y_LT_W( p ) ( Vector4ClipLT< 1 >::compare( p ) )
|
||||
#define CLIP_Y_GT_W( p ) ( Vector4ClipGT< 1 >::compare( p ) )
|
||||
#define CLIP_Z_LT_W( p ) ( Vector4ClipLT< 2 >::compare( p ) )
|
||||
#define CLIP_Z_GT_W( p ) ( Vector4ClipGT< 2 >::compare( p ) )
|
||||
|
||||
inline ClipResult homogenous_clip_point( const Vector4& clipped ){
|
||||
ClipResult result = c_CLIP_FAIL;
|
||||
|
|
@ -177,12 +177,12 @@ inline ClipResult matrix4_clip_point( const Matrix4& self, const Vector3& point,
|
|||
inline std::size_t homogenous_clip_triangle( Vector4 clipped[9] ){
|
||||
Vector4 buffer[9];
|
||||
std::size_t count = 3;
|
||||
count = Vector4ClipPolygon< Vector4ClipLT< IntegralConstant<0> > >::apply( clipped, clipped + count, buffer );
|
||||
count = Vector4ClipPolygon< Vector4ClipGT< IntegralConstant<0> > >::apply( buffer, buffer + count, clipped );
|
||||
count = Vector4ClipPolygon< Vector4ClipLT< IntegralConstant<1> > >::apply( clipped, clipped + count, buffer );
|
||||
count = Vector4ClipPolygon< Vector4ClipGT< IntegralConstant<1> > >::apply( buffer, buffer + count, clipped );
|
||||
count = Vector4ClipPolygon< Vector4ClipLT< IntegralConstant<2> > >::apply( clipped, clipped + count, buffer );
|
||||
return Vector4ClipPolygon< Vector4ClipGT< IntegralConstant<2> > >::apply( buffer, buffer + count, clipped );
|
||||
count = Vector4ClipPolygon< Vector4ClipLT< 0 > >::apply( clipped, clipped + count, buffer );
|
||||
count = Vector4ClipPolygon< Vector4ClipGT< 0 > >::apply( buffer, buffer + count, clipped );
|
||||
count = Vector4ClipPolygon< Vector4ClipLT< 1 > >::apply( clipped, clipped + count, buffer );
|
||||
count = Vector4ClipPolygon< Vector4ClipGT< 1 > >::apply( buffer, buffer + count, clipped );
|
||||
count = Vector4ClipPolygon< Vector4ClipLT< 2 > >::apply( clipped, clipped + count, buffer );
|
||||
return Vector4ClipPolygon< Vector4ClipGT< 2 > >::apply( buffer, buffer + count, clipped );
|
||||
}
|
||||
|
||||
/// \brief Transforms and clips the triangle formed by \p p0, \p p1, \p p2 by the canonical matrix \p self.
|
||||
|
|
|
|||
|
|
@ -501,55 +501,41 @@ inline void matrix4_affine_invert( Matrix4& self ){
|
|||
self = matrix4_affine_inverse( self );
|
||||
}
|
||||
|
||||
/// \brief A compile-time-constant integer.
|
||||
template<int VALUE_>
|
||||
struct IntegralConstant
|
||||
{
|
||||
enum unnamed_ { VALUE = VALUE_ };
|
||||
};
|
||||
|
||||
/// \brief A compile-time-constant row/column index into a 4x4 matrix.
|
||||
template<typename Row, typename Col>
|
||||
class Matrix4Index
|
||||
{
|
||||
public:
|
||||
typedef IntegralConstant<Row::VALUE> r;
|
||||
typedef IntegralConstant<Col::VALUE> c;
|
||||
typedef IntegralConstant<( r::VALUE * 4 ) + c::VALUE> i;
|
||||
};
|
||||
|
||||
/// \brief A functor which returns the cofactor of a 3x3 submatrix obtained by ignoring a given row and column of a 4x4 matrix.
|
||||
/// \param Row Defines the compile-time-constant integers x, y and z with values corresponding to the indices of the three rows to use.
|
||||
/// \param Col Defines the compile-time-constant integers x, y and z with values corresponding to the indices of the three columns to use.
|
||||
template<typename Row, typename Col>
|
||||
class Matrix4Cofactor
|
||||
{
|
||||
static constexpr size_t Matrix4Index( size_t row, size_t col ){
|
||||
return ( row * 4 ) + col;
|
||||
}
|
||||
public:
|
||||
typedef typename Matrix4Index<typename Row::x, typename Col::x>::i xx;
|
||||
typedef typename Matrix4Index<typename Row::x, typename Col::y>::i xy;
|
||||
typedef typename Matrix4Index<typename Row::x, typename Col::z>::i xz;
|
||||
typedef typename Matrix4Index<typename Row::y, typename Col::x>::i yx;
|
||||
typedef typename Matrix4Index<typename Row::y, typename Col::y>::i yy;
|
||||
typedef typename Matrix4Index<typename Row::y, typename Col::z>::i yz;
|
||||
typedef typename Matrix4Index<typename Row::z, typename Col::x>::i zx;
|
||||
typedef typename Matrix4Index<typename Row::z, typename Col::y>::i zy;
|
||||
typedef typename Matrix4Index<typename Row::z, typename Col::z>::i zz;
|
||||
static constexpr size_t xx = Matrix4Index( Row::x, Col::x );
|
||||
static constexpr size_t xy = Matrix4Index( Row::x, Col::y );
|
||||
static constexpr size_t xz = Matrix4Index( Row::x, Col::z );
|
||||
static constexpr size_t yx = Matrix4Index( Row::y, Col::x );
|
||||
static constexpr size_t yy = Matrix4Index( Row::y, Col::y );
|
||||
static constexpr size_t yz = Matrix4Index( Row::y, Col::z );
|
||||
static constexpr size_t zx = Matrix4Index( Row::z, Col::x );
|
||||
static constexpr size_t zy = Matrix4Index( Row::z, Col::y );
|
||||
static constexpr size_t zz = Matrix4Index( Row::z, Col::z );
|
||||
static double apply( const Matrix4& self ){
|
||||
return self[xx::VALUE] * ( self[yy::VALUE] * self[zz::VALUE] - self[zy::VALUE] * self[yz::VALUE] )
|
||||
- self[xy::VALUE] * ( self[yx::VALUE] * self[zz::VALUE] - self[zx::VALUE] * self[yz::VALUE] )
|
||||
+ self[xz::VALUE] * ( self[yx::VALUE] * self[zy::VALUE] - self[zx::VALUE] * self[yy::VALUE] );
|
||||
return self[xx] * ( self[yy] * self[zz] - self[zy] * self[yz] )
|
||||
- self[xy] * ( self[yx] * self[zz] - self[zx] * self[yz] )
|
||||
+ self[xz] * ( self[yx] * self[zy] - self[zx] * self[yy] );
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief The cofactor element indices for a 4x4 matrix row or column.
|
||||
/// \param Element The index of the element to ignore.
|
||||
template<int Element>
|
||||
template<size_t Element>
|
||||
class Cofactor4
|
||||
{
|
||||
public:
|
||||
typedef IntegralConstant<( Element <= 0 ) ? 1 : 0> x;
|
||||
typedef IntegralConstant<( Element <= 1 ) ? 2 : 1> y;
|
||||
typedef IntegralConstant<( Element <= 2 ) ? 3 : 2> z;
|
||||
static constexpr size_t x = ( Element <= 0 ) ? 1 : 0;
|
||||
static constexpr size_t y = ( Element <= 1 ) ? 2 : 1;
|
||||
static constexpr size_t z = ( Element <= 2 ) ? 3 : 2;
|
||||
};
|
||||
|
||||
/// \brief Returns the determinant of \p self.
|
||||
|
|
|
|||
|
|
@ -1789,19 +1789,19 @@ inline PatchControl QuadraticBezier_evaluate( const PatchControl* firstPoint, do
|
|||
double denominator = 0;
|
||||
|
||||
{
|
||||
double weight = BernsteinPolynomial<Zero, Two>::apply( t );
|
||||
double weight = BernsteinPolynomial<0, 2>::apply( t );
|
||||
vector3_add( result.m_vertex, vector3_scaled( firstPoint[0].m_vertex, weight ) );
|
||||
vector2_add( result.m_texcoord, vector2_scaled( firstPoint[0].m_texcoord, weight ) );
|
||||
denominator += weight;
|
||||
}
|
||||
{
|
||||
double weight = BernsteinPolynomial<One, Two>::apply( t );
|
||||
double weight = BernsteinPolynomial<1, 2>::apply( t );
|
||||
vector3_add( result.m_vertex, vector3_scaled( firstPoint[1].m_vertex, weight ) );
|
||||
vector2_add( result.m_texcoord, vector2_scaled( firstPoint[1].m_texcoord, weight ) );
|
||||
denominator += weight;
|
||||
}
|
||||
{
|
||||
double weight = BernsteinPolynomial<Two, Two>::apply( t );
|
||||
double weight = BernsteinPolynomial<2, 2>::apply( t );
|
||||
vector3_add( result.m_vertex, vector3_scaled( firstPoint[2].m_vertex, weight ) );
|
||||
vector2_add( result.m_texcoord, vector2_scaled( firstPoint[2].m_texcoord, weight ) );
|
||||
denominator += weight;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user