* fix alt + m1 indirect faces picking, when object is partially or fully out of camera view
refactor math functions
This commit is contained in:
@@ -195,7 +195,7 @@ void bestPlaneDirect( const AABB& aabb, SelectionTest& test, Plane3& plane, Sele
|
||||
}
|
||||
m_bounds = aabb;
|
||||
}
|
||||
void bestPlaneIndirect( const AABB& aabb, SelectionTest& test, Plane3& plane, Vector3& intersection, float& dist, const Vector3& viewer, const Matrix4& rotation = g_matrix4_identity ){
|
||||
void bestPlaneIndirect( const AABB& aabb, SelectionTest& test, Plane3& plane, Vector3& intersection, float& dist, const Matrix4& rotation = g_matrix4_identity ){
|
||||
Vector3 corners[8];
|
||||
aabb_corners_oriented( aabb, rotation, corners );
|
||||
|
||||
@@ -256,33 +256,32 @@ void bestPlaneIndirect( const AABB& aabb, SelectionTest& test, Plane3& plane, Ve
|
||||
3, 1,
|
||||
};
|
||||
|
||||
for( std::size_t i = 0; i < 8; ++i ){
|
||||
corners[i] = vector4_projected( matrix4_transformed_vector4( test.getVolume().GetViewMatrix(), Vector4( corners[i], 1 ) ) );
|
||||
}
|
||||
|
||||
for ( std::size_t i = 0; i < 24; ++++i ){
|
||||
const Vector3 intersection_new = line_closest_point( Line( corners[edges[i]], corners[edges[i + 1]] ), g_vector3_identity );
|
||||
const float dist_new = vector3_length_squared( intersection_new );
|
||||
if( dist_new < dist ){
|
||||
const Plane3& plane1 = planes[adjacent_planes[i]];
|
||||
const Plane3& plane2 = planes[adjacent_planes[i + 1]];
|
||||
if( ( vector3_dot( plane1.normal(), viewer ) - plane1.dist() ) <= 0 ){
|
||||
if( aabb.extents[( ( adjacent_planes[i] >> 1 ) << 1 ) / 2] == 0 ) /* select the other, if zero bound */
|
||||
plane = plane2;
|
||||
else
|
||||
plane = plane1;
|
||||
intersection = intersection_new;
|
||||
dist = dist_new;
|
||||
}
|
||||
else{
|
||||
if( ( vector3_dot( plane2.normal(), viewer ) - plane2.dist() ) <= 0 ){
|
||||
if( aabb.extents[( ( adjacent_planes[i + 1] >> 1 ) << 1 ) / 2] == 0 ) /* select the other, if zero bound */
|
||||
plane = plane1;
|
||||
else
|
||||
Line line( corners[edges[i]], corners[edges[i + 1]] );
|
||||
if( matrix4_clip_line_by_nearplane( test.getVolume().GetViewMatrix(), line ) == 2 ){
|
||||
const Vector3 intersection_new = line_closest_point( line, g_vector3_identity );
|
||||
const float dist_new = vector3_length_squared( intersection_new );
|
||||
if( dist_new < dist ){
|
||||
const Plane3& plane1 = planes[adjacent_planes[i]];
|
||||
const Plane3& plane2 = planes[adjacent_planes[i + 1]];
|
||||
if( plane3_distance_to_point( plane1, test.getVolume().getViewer() ) <= 0 ){
|
||||
if( aabb.extents[( ( adjacent_planes[i] >> 1 ) << 1 ) / 2] == 0 ) /* select the other, if zero bound */
|
||||
plane = plane2;
|
||||
else
|
||||
plane = plane1;
|
||||
intersection = intersection_new;
|
||||
dist = dist_new;
|
||||
}
|
||||
else{
|
||||
if( plane3_distance_to_point( plane2, test.getVolume().getViewer() ) <= 0 ){
|
||||
if( aabb.extents[( ( adjacent_planes[i + 1] >> 1 ) << 1 ) / 2] == 0 ) /* select the other, if zero bound */
|
||||
plane = plane1;
|
||||
else
|
||||
plane = plane2;
|
||||
intersection = intersection_new;
|
||||
dist = dist_new;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -363,6 +363,51 @@ inline std::size_t matrix4_clip_line( const Matrix4& self, const Vector3& p0, co
|
||||
return homogenous_clip_line( clipped );
|
||||
}
|
||||
|
||||
inline std::size_t matrix4_clip_line_by_nearplane( const Matrix4& self, Line& line ){
|
||||
Vector4 points[2] = { matrix4_transformed_vector4( self, Vector4( line.start, 1 ) ), matrix4_transformed_vector4( self, Vector4( line.end, 1 ) ) };
|
||||
const Vector4& p0 = points[0];
|
||||
const Vector4& p1 = points[1];
|
||||
|
||||
// early out
|
||||
{
|
||||
const bool passed0 = CLIP_Z_GT_W( p0 );
|
||||
const bool passed1 = CLIP_Z_GT_W( p1 );
|
||||
|
||||
if ( passed0 && passed1 ) { // both points passed all planes
|
||||
line.start = vector4_projected( p0 );
|
||||
line.end = vector4_projected( p1 );
|
||||
return 2;
|
||||
}
|
||||
|
||||
if ( !passed0 && !passed1 ) { // both points failed any one plane
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const bool index = CLIP_Z_GT_W( p0 );
|
||||
if ( index ^ CLIP_Z_GT_W( p1 ) ) {
|
||||
Vector4 clip( vector4_subtracted( p1, p0 ) );
|
||||
|
||||
double scale = ( p0[2] + p0[3] ) / ( -clip[3] - clip[2] );
|
||||
|
||||
clip[0] = static_cast<float>( p0[0] + scale * clip[0] );
|
||||
clip[1] = static_cast<float>( p0[1] + scale * clip[1] );
|
||||
clip[2] = static_cast<float>( p0[2] + scale * clip[2] );
|
||||
clip[3] = static_cast<float>( p0[3] + scale * clip[3] );
|
||||
|
||||
points[index] = clip;
|
||||
}
|
||||
else if ( index == 0 ) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
line.start = vector4_projected( p0 );
|
||||
line.end = vector4_projected( p1 );
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -91,20 +91,25 @@ inline unsigned int segment_classify_plane( const Segment& segment, const Plane3
|
||||
}
|
||||
|
||||
|
||||
class Ray
|
||||
template<typename T>
|
||||
class BasicRay
|
||||
{
|
||||
public:
|
||||
Vector3 origin, direction;
|
||||
BasicVector3<T> origin, direction;
|
||||
|
||||
Ray(){
|
||||
BasicRay(){
|
||||
}
|
||||
Ray( const Vector3& origin_, const Vector3& direction_ ) :
|
||||
BasicRay( const BasicVector3<T>& origin_, const BasicVector3<T>& direction_ ) :
|
||||
origin( origin_ ), direction( direction_ ){
|
||||
}
|
||||
};
|
||||
|
||||
inline Ray ray_for_points( const Vector3& origin, const Vector3& p2 ){
|
||||
return Ray( origin, vector3_normalised( vector3_subtracted( p2, origin ) ) );
|
||||
typedef BasicRay<float> Ray;
|
||||
typedef BasicRay<double> DoubleRay;
|
||||
|
||||
template<typename T>
|
||||
inline BasicRay<T> ray_for_points( const BasicVector3<T>& origin, const BasicVector3<T>& p2 ){
|
||||
return BasicRay<T>( origin, vector3_normalised( vector3_subtracted( p2, origin ) ) );
|
||||
}
|
||||
|
||||
inline void ray_transform( Ray& ray, const Matrix4& matrix ){
|
||||
@@ -132,7 +137,45 @@ inline double ray_squared_distance_to_point( const Ray& ray, const Vector3& poin
|
||||
}
|
||||
|
||||
inline double ray_distance_to_plane( const Ray& ray, const Plane3& plane ){
|
||||
return -( vector3_dot( plane.normal(), ray.origin ) - plane.dist() ) / vector3_dot( ray.direction, plane.normal() );
|
||||
return -plane3_distance_to_point( plane, ray.origin ) / vector3_dot( ray.direction, plane.normal() );
|
||||
}
|
||||
|
||||
/// \brief Returns the point at which \p ray intersects \p plane, or an undefined value if there is no intersection.
|
||||
template<typename T>
|
||||
inline BasicVector3<T> ray_intersect_plane( const BasicRay<T>& ray, const Plane3& plane ){
|
||||
return ray.origin + vector3_scaled(
|
||||
ray.direction,
|
||||
-plane3_distance_to_point( plane, ray.origin )
|
||||
/ vector3_dot( ray.direction, plane.normal() )
|
||||
);
|
||||
}
|
||||
|
||||
/// \brief Returns the infinite line that is the intersection of \p plane and \p other.
|
||||
inline DoubleRay plane3_intersect_plane3( const Plane3& plane, const Plane3& other ){
|
||||
DoubleRay line;
|
||||
line.direction = vector3_cross( plane.normal(), other.normal() );
|
||||
switch ( vector3_max_abs_component_index( line.direction ) )
|
||||
{
|
||||
case 0:
|
||||
line.origin.x() = 0;
|
||||
line.origin.y() = ( -other.dist() * plane.normal().z() - -plane.dist() * other.normal().z() ) / line.direction.x();
|
||||
line.origin.z() = ( -plane.dist() * other.normal().y() - -other.dist() * plane.normal().y() ) / line.direction.x();
|
||||
break;
|
||||
case 1:
|
||||
line.origin.x() = ( -plane.dist() * other.normal().z() - -other.dist() * plane.normal().z() ) / line.direction.y();
|
||||
line.origin.y() = 0;
|
||||
line.origin.z() = ( -other.dist() * plane.normal().x() - -plane.dist() * other.normal().x() ) / line.direction.y();
|
||||
break;
|
||||
case 2:
|
||||
line.origin.x() = ( -other.dist() * plane.normal().y() - -plane.dist() * other.normal().y() ) / line.direction.z();
|
||||
line.origin.y() = ( -plane.dist() * other.normal().x() - -other.dist() * plane.normal().x() ) / line.direction.z();
|
||||
line.origin.z() = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -138,5 +138,10 @@ inline Plane3 plane3_for_points( const BasicVector3<Element> planepts[3] ){
|
||||
return plane3_for_points( planepts[2], planepts[1], planepts[0] );
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline double plane3_distance_to_point( const Plane3& plane, const BasicVector3<T>& point ){
|
||||
return vector3_dot( point, plane.normal() ) - plane.dist();
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user