diff --git a/include/selectable.h b/include/selectable.h index 55861ec5..daf0491c 100644 --- a/include/selectable.h +++ b/include/selectable.h @@ -300,7 +300,7 @@ virtual void selectPlanes( Selector& selector, SelectionTest& test, const PlaneC virtual void selectReversedPlanes( Selector& selector, const SelectedPlanes& selectedPlanes ) = 0; virtual void bestPlaneDirect( SelectionTest& test, Plane3& plane, SelectionIntersection& intersection ) = 0; -virtual void bestPlaneIndirect( SelectionTest& test, Plane3& plane, Vector3& intersection, float& dist, const Vector3& viewer ) = 0; +virtual void bestPlaneIndirect( SelectionTest& test, Plane3& plane, Vector3& intersection, float& dist ) = 0; virtual void selectByPlane( const Plane3& plane ) = 0; }; diff --git a/libs/dragplanes.h b/libs/dragplanes.h index d5d0bf21..c8e4d568 100644 --- a/libs/dragplanes.h +++ b/libs/dragplanes.h @@ -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; + } + } } } } diff --git a/libs/math/frustum.h b/libs/math/frustum.h index eb635d5e..2cc083f1 100644 --- a/libs/math/frustum.h +++ b/libs/math/frustum.h @@ -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( p0[0] + scale * clip[0] ); + clip[1] = static_cast( p0[1] + scale * clip[1] ); + clip[2] = static_cast( p0[2] + scale * clip[2] ); + clip[3] = static_cast( 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; +} + diff --git a/libs/math/line.h b/libs/math/line.h index cf3bec54..04af0ba5 100644 --- a/libs/math/line.h +++ b/libs/math/line.h @@ -91,20 +91,25 @@ inline unsigned int segment_classify_plane( const Segment& segment, const Plane3 } -class Ray +template +class BasicRay { public: -Vector3 origin, direction; +BasicVector3 origin, direction; -Ray(){ +BasicRay(){ } -Ray( const Vector3& origin_, const Vector3& direction_ ) : +BasicRay( const BasicVector3& origin_, const BasicVector3& 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 Ray; +typedef BasicRay DoubleRay; + +template +inline BasicRay ray_for_points( const BasicVector3& origin, const BasicVector3& p2 ){ + return BasicRay( 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 +inline BasicVector3 ray_intersect_plane( const BasicRay& 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 diff --git a/libs/math/plane.h b/libs/math/plane.h index 10dca357..3913cc56 100644 --- a/libs/math/plane.h +++ b/libs/math/plane.h @@ -138,5 +138,10 @@ inline Plane3 plane3_for_points( const BasicVector3 planepts[3] ){ return plane3_for_points( planepts[2], planepts[1], planepts[0] ); } +template +inline double plane3_distance_to_point( const Plane3& plane, const BasicVector3& point ){ + return vector3_dot( point, plane.normal() ) - plane.dist(); +} + #endif diff --git a/plugins/entity/light.cpp b/plugins/entity/light.cpp index 1177fff6..f9a362fa 100644 --- a/plugins/entity/light.cpp +++ b/plugins/entity/light.cpp @@ -1873,10 +1873,10 @@ void bestPlaneDirect( SelectionTest& test, Plane3& plane, SelectionIntersection& m_dragPlanes.bestPlaneDirect( m_contained.aabb(), test, plane, intersection, rotation() ); } } -void bestPlaneIndirect( SelectionTest& test, Plane3& plane, Vector3& intersection, float& dist, const Vector3& viewer ){ +void bestPlaneIndirect( SelectionTest& test, Plane3& plane, Vector3& intersection, float& dist ){ if ( g_lightType == LIGHTTYPE_DOOM3 ) { test.BeginMesh( localToWorld() ); - m_dragPlanes.bestPlaneIndirect( m_contained.aabb(), test, plane, intersection, dist, viewer, rotation() ); + m_dragPlanes.bestPlaneIndirect( m_contained.aabb(), test, plane, intersection, dist, rotation() ); } } void selectByPlane( const Plane3& plane ){ diff --git a/radiant/brush.h b/radiant/brush.h index 744df64b..30aca8c0 100644 --- a/radiant/brush.h +++ b/radiant/brush.h @@ -1507,16 +1507,6 @@ Face& getFace() const { void testSelect( SelectionTest& test, SelectionIntersection& best ){ test.TestPoint( getEdge(), best ); } -Vector3 bestPlaneIndirect( const SelectionTest& test ) const { - const Winding& winding = getFace().getWinding(); - Vector3 points[2]; - points[0] = winding[m_faceVertex.getVertex()].vertex; - points[1] = winding[Winding_next( winding, m_faceVertex.getVertex() )].vertex; - for( std::size_t i = 0; i < 2; ++i ){ - points[i] = vector4_projected( matrix4_transformed_vector4( test.getVolume().GetViewMatrix(), Vector4( points[i], 1 ) ) ); - } - return line_closest_point( Line( points[0], points[1] ), g_vector3_identity ); -} }; class SelectableVertex @@ -3208,25 +3198,30 @@ void testSelect( Selector& selector, SelectionTest& test ){ Selector_add( selector, *this, best ); } } -void bestPlaneIndirect( const SelectionTest& test, Plane3& plane, Vector3& intersection, float& dist, const Vector3& viewer ) const { - const Vector3 intersection_new = m_edge->bestPlaneIndirect( test ); - const float dist_new = vector3_length_squared( intersection_new ); - if( dist_new < dist ){ - FaceVertexId faceVertex = m_edge->m_faceVertex; - const Plane3& plane1 = m_faceInstances[faceVertex.getFace()].getFace().plane3(); - if( ( vector3_dot( plane1.normal(), viewer ) - plane1.dist() ) <= 0 ){ - plane = plane1; - intersection = intersection_new; - dist = dist_new; - } - else{ - faceVertex = next_edge( m_edge->m_faces, faceVertex ); - const Plane3& plane2 = m_faceInstances[faceVertex.getFace()].getFace().plane3(); - if( ( vector3_dot( plane2.normal(), viewer ) - plane2.dist() ) <= 0 ){ - plane = plane2; + +void bestPlaneIndirect( const SelectionTest& test, Plane3& plane, Vector3& intersection, float& dist ) const { + const Winding& winding = m_edge->getFace().getWinding(); + FaceVertexId faceVertex = m_edge->m_faceVertex; + Line line( winding[faceVertex.getVertex()].vertex, winding[Winding_next( winding, faceVertex.getVertex() )].vertex ); + 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 = m_faceInstances[faceVertex.getFace()].getFace().plane3(); + if( plane3_distance_to_point( plane1, test.getVolume().getViewer() ) <= 0 ){ + plane = plane1; intersection = intersection_new; dist = dist_new; } + else{ + faceVertex = next_edge( m_edge->m_faces, faceVertex ); + const Plane3& plane2 = m_faceInstances[faceVertex.getFace()].getFace().plane3(); + if( plane3_distance_to_point( plane2, test.getVolume().getViewer() ) <= 0 ){ + plane = plane2; + intersection = intersection_new; + dist = dist_new; + } + } } } } @@ -3834,11 +3829,11 @@ void bestPlaneDirect( SelectionTest& test, Plane3& plane, SelectionIntersection& } } } -void bestPlaneIndirect( SelectionTest& test, Plane3& plane, Vector3& intersection, float& dist, const Vector3& viewer ){ +void bestPlaneIndirect( SelectionTest& test, Plane3& plane, Vector3& intersection, float& dist ){ test.BeginMesh( localToWorld() ); for ( EdgeInstances::iterator i = m_edgeInstances.begin(); i != m_edgeInstances.end(); ++i ) { - ( *i ).bestPlaneIndirect( test, plane, intersection, dist, viewer ); + ( *i ).bestPlaneIndirect( test, plane, intersection, dist ); } } void selectByPlane( const Plane3& plane ){ diff --git a/radiant/patch.h b/radiant/patch.h index 6df57ce0..b0b1cdb8 100644 --- a/radiant/patch.h +++ b/radiant/patch.h @@ -1629,9 +1629,9 @@ void bestPlaneDirect( SelectionTest& test, Plane3& plane, SelectionIntersection& test.BeginMesh( localToWorld() ); m_dragPlanes.bestPlaneDirect( m_patch.localAABB(), test, plane, intersection ); } -void bestPlaneIndirect( SelectionTest& test, Plane3& plane, Vector3& intersection, float& dist, const Vector3& viewer ){ +void bestPlaneIndirect( SelectionTest& test, Plane3& plane, Vector3& intersection, float& dist ){ test.BeginMesh( localToWorld() ); - m_dragPlanes.bestPlaneIndirect( m_patch.localAABB(), test, plane, intersection, dist, viewer ); + m_dragPlanes.bestPlaneIndirect( m_patch.localAABB(), test, plane, intersection, dist ); } void selectByPlane( const Plane3& plane ){ m_dragPlanes.selectByPlane( m_patch.localAABB(), plane ); diff --git a/radiant/selection.cpp b/radiant/selection.cpp index d465d774..1444113c 100644 --- a/radiant/selection.cpp +++ b/radiant/selection.cpp @@ -69,94 +69,75 @@ struct Pivot2World }; -void point_for_device_point( Vector3& point, const Matrix4& device2object, const float x, const float y, const float z ){ +inline Vector3 point_for_device_point( const Matrix4& device2object, const float x, const float y, const float z ){ // transform from normalised device coords to object coords - point = vector4_projected( matrix4_transformed_vector4( device2object, Vector4( x, y, z, 1 ) ) ); + return vector4_projected( matrix4_transformed_vector4( device2object, Vector4( x, y, z, 1 ) ) ); } -void ray_for_device_point( Ray& ray, const Matrix4& device2object, const float x, const float y ){ - // point at x, y, zNear - point_for_device_point( ray.origin, device2object, x, y, -1 ); - - // point at x, y, zFar - //point_for_device_point( ray.direction, device2object, x, y, 1 ); //sometimes is inaccurate up to negative ray direction - point_for_device_point( ray.direction, device2object, x, y, 0 ); - - // construct ray - vector3_subtract( ray.direction, ray.origin ); - vector3_normalise( ray.direction ); +inline Ray ray_for_device_point( const Matrix4& device2object, const float x, const float y ){ + return ray_for_points( point_for_device_point( device2object, x, y, -1 ), // point at x, y, zNear + point_for_device_point( device2object, x, y, 0 ) // point at x, y, zFar + //point_for_device_point( device2object, x, y, 1 ) //sometimes is inaccurate up to negative ray direction + ); } -bool sphere_intersect_ray( const Vector3& origin, float radius, const Ray& ray, Vector3& intersection ){ - intersection = vector3_subtracted( origin, ray.origin ); +inline Vector3 sphere_intersect_ray( const Vector3& origin, float radius, const Ray& ray ){ + const Vector3 intersection = vector3_subtracted( origin, ray.origin ); const double a = vector3_dot( intersection, ray.direction ); const double d = radius * radius - ( vector3_dot( intersection, intersection ) - a * a ); if ( d > 0 ) { - intersection = vector3_added( ray.origin, vector3_scaled( ray.direction, a - sqrt( d ) ) ); - return true; + return vector3_added( ray.origin, vector3_scaled( ray.direction, a - sqrt( d ) ) ); +// return true; } else { - intersection = vector3_added( ray.origin, vector3_scaled( ray.direction, a ) ); - return false; + return vector3_added( ray.origin, vector3_scaled( ray.direction, a ) ); +// return false; } } -void ray_intersect_ray( const Ray& ray, const Ray& other, Vector3& intersection ){ - intersection = vector3_subtracted( ray.origin, other.origin ); +inline Vector3 ray_intersect_ray( const Ray& ray, const Ray& other ){ + const Vector3 intersection = vector3_subtracted( ray.origin, other.origin ); //float a = 1;//vector3_dot(ray.direction, ray.direction); // always >= 0 - double dot = vector3_dot( ray.direction, other.direction ); + const double dot = vector3_dot( ray.direction, other.direction ); //float c = 1;//vector3_dot(other.direction, other.direction); // always >= 0 - double d = vector3_dot( ray.direction, intersection ); - double e = vector3_dot( other.direction, intersection ); - double D = 1 - dot * dot; //a*c - dot*dot; // always >= 0 + const double d = vector3_dot( ray.direction, intersection ); + const double e = vector3_dot( other.direction, intersection ); + const double D = 1 - dot * dot; //a*c - dot*dot; // always >= 0 if ( D < 0.000001 ) { // the lines are almost parallel - intersection = vector3_added( other.origin, vector3_scaled( other.direction, e ) ); + return vector3_added( other.origin, vector3_scaled( other.direction, e ) ); } else { - intersection = vector3_added( other.origin, vector3_scaled( other.direction, ( e - dot * d ) / D ) ); + return vector3_added( other.origin, vector3_scaled( other.direction, ( e - dot * d ) / D ) ); } } const Vector3 g_origin( 0, 0, 0 ); const float g_radius = 64; -void point_on_sphere( Vector3& point, const Matrix4& device2object, const float x, const float y, const float radius = g_radius ){ - Ray ray; - ray_for_device_point( ray, device2object, x, y ); - sphere_intersect_ray( g_origin, radius, ray, point ); +inline Vector3 point_on_sphere( const Matrix4& device2object, const float x, const float y, const float radius = g_radius ){ + return sphere_intersect_ray( g_origin, + radius, + ray_for_device_point( device2object, x, y ) ); } -void point_on_axis( Vector3& point, const Vector3& axis, const Matrix4& device2object, const float x, const float y ){ - Ray ray; - ray_for_device_point( ray, device2object, x, y ); - ray_intersect_ray( ray, Ray( Vector3( 0, 0, 0 ), axis ), point ); +inline Vector3 point_on_axis( const Vector3& axis, const Matrix4& device2object, const float x, const float y ){ + return ray_intersect_ray( ray_for_device_point( device2object, x, y ), + Ray( Vector3( 0, 0, 0 ), axis ) ); } -void point_on_plane( Vector3& point, const Matrix4& device2object, const float x, const float y ){ - Matrix4 object2device( matrix4_full_inverse( device2object ) ); - point = vector4_projected( matrix4_transformed_vector4( device2object, Vector4( x, y, object2device[14] / object2device[15], 1 ) ) ); +inline Vector3 point_on_plane( const Matrix4& device2object, const float x, const float y ){ + const Matrix4 object2device( matrix4_full_inverse( device2object ) ); + return vector4_projected( matrix4_transformed_vector4( device2object, Vector4( x, y, object2device[14] / object2device[15], 1 ) ) ); } -inline double plane3_distance_to_point( const Plane3& plane, const Vector3& point ){ - return vector3_dot( point, plane.normal() ) - plane.dist(); -} - -inline Vector3 ray_intersect_plane( const Ray& ray, const Plane3& plane ){ - return ray.origin + vector3_scaled( - ray.direction, - -plane3_distance_to_point( plane, ray.origin ) - / vector3_dot( ray.direction, plane.normal() ) - ); -} -Vector3 point_on_plane( const Plane3& plane, const Matrix4& object2device, const float x, const float y ){ - Ray ray; - ray_for_device_point( ray, matrix4_full_inverse( object2device ), x, y ); - return ray_intersect_plane( ray, plane ); +inline Vector3 point_on_plane( const Plane3& plane, const Matrix4& object2device, const float x, const float y ){ + return ray_intersect_plane( ray_for_device_point( matrix4_full_inverse( object2device ), x, y ), + plane ); } //! a and b are unit vectors .. returns angle in radians @@ -188,7 +169,7 @@ inline void constrain_to_axis( Vector3& vec, const Vector3& axis ){ } //! a and b are unit vectors .. a and b must be orthogonal to axis .. returns angle in radians -float angle_for_axis( const Vector3& a, const Vector3& b, const Vector3& axis ){ +inline float angle_for_axis( const Vector3& a, const Vector3& b, const Vector3& axis ){ if ( vector3_dot( axis, vector3_cross( a, b ) ) > 0.0 ) { return angle_between( a, b ); } @@ -197,7 +178,7 @@ float angle_for_axis( const Vector3& a, const Vector3& b, const Vector3& axis ){ } } -float distance_for_axis( const Vector3& a, const Vector3& b, const Vector3& axis ){ +inline float distance_for_axis( const Vector3& a, const Vector3& b, const Vector3& axis ){ return static_cast( vector3_dot( b, axis ) - vector3_dot( a, axis ) ); } @@ -244,12 +225,11 @@ RotateFree( Rotatable& rotatable ) : m_rotatable( rotatable ){ } void Construct( const Matrix4& device2manip, const float x, const float y, const AABB& bounds, const Vector3& transform_origin ){ - point_on_sphere( m_start, device2manip, x, y ); + m_start = point_on_sphere( device2manip, x, y ); vector3_normalise( m_start ); } void Transform( const Matrix4& manip2object, const Matrix4& device2manip, const float x, const float y, const bool snap, const bool snapbbox, const bool alt ){ - Vector3 current; - point_on_sphere( current, device2manip, x, y ); + Vector3 current = point_on_sphere( device2manip, x, y ); vector3_normalise( current ); if( snap ) @@ -286,7 +266,7 @@ void Construct( const Matrix4& device2manip, const float x, const float y, const vector3_normalise( m_start ); } else{ - point_on_sphere( m_start, device2manip, x, y, m_radius ); + m_start = point_on_sphere( device2manip, x, y, m_radius ); constrain_to_axis( m_start, m_axis ); } } @@ -298,7 +278,7 @@ void Transform( const Matrix4& manip2object, const Matrix4& device2manip, const vector3_normalise( current ); } else{ - point_on_sphere( current, device2manip, x, y, m_radius ); + current = point_on_sphere( device2manip, x, y, m_radius ); constrain_to_axis( current, m_axis ); } @@ -365,12 +345,11 @@ TranslateAxis( Translatable& translatable ) : m_translatable( translatable ){ } void Construct( const Matrix4& device2manip, const float x, const float y, const AABB& bounds, const Vector3& transform_origin ){ - point_on_axis( m_start, m_axis, device2manip, x, y ); + m_start = point_on_axis( m_axis, device2manip, x, y ); m_bounds = bounds; } void Transform( const Matrix4& manip2object, const Matrix4& device2manip, const float x, const float y, const bool snap, const bool snapbbox, const bool alt ){ - Vector3 current; - point_on_axis( current, m_axis, device2manip, x, y ); + Vector3 current = point_on_axis( m_axis, device2manip, x, y ); current = vector3_scaled( m_axis, distance_for_axis( m_start, current, m_axis ) ); translation_local2object( current, current, manip2object ); @@ -435,12 +414,11 @@ TranslateFree( Translatable& translatable ) : m_translatable( translatable ){ } void Construct( const Matrix4& device2manip, const float x, const float y, const AABB& bounds, const Vector3& transform_origin ){ - point_on_plane( m_start, device2manip, x, y ); + m_start = point_on_plane( device2manip, x, y ); m_bounds = bounds; } void Transform( const Matrix4& manip2object, const Matrix4& device2manip, const float x, const float y, const bool snap, const bool snapbbox, const bool alt ){ - Vector3 current; - point_on_plane( current, device2manip, x, y ); + Vector3 current = point_on_plane( device2manip, x, y ); current = vector3_subtracted( current, m_start ); if( snap ) @@ -537,7 +515,7 @@ ScaleAxis( Scalable& scalable ) : m_scalable( scalable ){ } void Construct( const Matrix4& device2manip, const float x, const float y, const AABB& bounds, const Vector3& transform_origin ){ - point_on_axis( m_start, m_axis, device2manip, x, y ); + m_start = point_on_axis( m_axis, device2manip, x, y ); m_choosen_extent = Vector3( std::max( bounds.origin[0] + bounds.extents[0] - transform_origin[0], - bounds.origin[0] + bounds.extents[0] + transform_origin[0] ), @@ -548,8 +526,7 @@ void Construct( const Matrix4& device2manip, const float x, const float y, const } void Transform( const Matrix4& manip2object, const Matrix4& device2manip, const float x, const float y, const bool snap, const bool snapbbox, const bool alt ){ //globalOutputStream() << "manip2object: " << manip2object << " device2manip: " << device2manip << " x: " << x << " y:" << y <<"\n"; - Vector3 current; - point_on_axis( current, m_axis, device2manip, x, y ); + Vector3 current = point_on_axis( m_axis, device2manip, x, y ); Vector3 delta = vector3_subtracted( current, m_start ); translation_local2object( delta, delta, manip2object ); @@ -611,7 +588,7 @@ ScaleFree( Scalable& scalable ) : m_scalable( scalable ){ } void Construct( const Matrix4& device2manip, const float x, const float y, const AABB& bounds, const Vector3& transform_origin ){ - point_on_plane( m_start, device2manip, x, y ); + m_start = point_on_plane( device2manip, x, y ); m_choosen_extent = Vector3( std::max( bounds.origin[0] + bounds.extents[0] - transform_origin[0], -( bounds.origin[0] - bounds.extents[0] - transform_origin[0] ) ), @@ -621,8 +598,7 @@ void Construct( const Matrix4& device2manip, const float x, const float y, const m_bounds = bounds; } void Transform( const Matrix4& manip2object, const Matrix4& device2manip, const float x, const float y, const bool snap, const bool snapbbox, const bool alt ){ - Vector3 current; - point_on_plane( current, device2manip, x, y ); + Vector3 current = point_on_plane( device2manip, x, y ); Vector3 delta = vector3_subtracted( current, m_start ); translation_local2object( delta, delta, manip2object ); @@ -866,64 +842,6 @@ Shader* g_state_clipped; RenderableClippedPrimitive g_render_clipped; #endif - -#if 0 -// dist_Point_to_Line(): get the distance of a point to a line. -// Input: a Point P and a Line L (in any dimension) -// Return: the shortest distance from P to L -float -dist_Point_to_Line( Point P, Line L ){ - Vector v = L.P1 - L.P0; - Vector w = P - L.P0; - - double c1 = dot( w,v ); - double c2 = dot( v,v ); - double b = c1 / c2; - - Point Pb = L.P0 + b * v; - return d( P, Pb ); -} -#endif - -class Segment3D -{ -typedef Vector3 point_type; -public: -Segment3D( const point_type& _p0, const point_type& _p1 ) - : p0( _p0 ), p1( _p1 ){ -} - -point_type p0, p1; -}; - -typedef Vector3 Point3D; - -inline double vector3_distance_squared( const Point3D& a, const Point3D& b ){ - return vector3_length_squared( b - a ); -} - -// get the distance of a point to a segment. -Point3D segment_closest_point_to_point( const Segment3D& segment, const Point3D& point ){ - Vector3 v = segment.p1 - segment.p0; - Vector3 w = point - segment.p0; - - double c1 = vector3_dot( w,v ); - if ( c1 <= 0 ) { - return segment.p0; - } - - double c2 = vector3_dot( v,v ); - if ( c2 <= c1 ) { - return segment.p1; - } - - return Point3D( segment.p0 + v * ( c1 / c2 ) ); -} - -double segment_dist_to_point_3d( const Segment3D& segment, const Point3D& point ){ - return vector3_distance_squared( point, segment_closest_point_to_point( segment, point ) ); -} - typedef Vector3 point_t; typedef const Vector3* point_iterator_t; @@ -985,8 +903,7 @@ void BestPoint( std::size_t count, Vector4 clipped[9], SelectionIntersection& be } if ( count == 2 ) { - Segment3D segment( normalised[0], normalised[1] ); - Point3D point = segment_closest_point_to_point( segment, Vector3( 0, 0, 0 ) ); + const Vector3 point = line_closest_point( Line( normalised[0], normalised[1] ), Vector3( 0, 0, 0 ) ); assign_if_closer( best, SelectionIntersection( point.z(), 0 ) ); } else if ( count > 2 && !point_test_polygon_2d( Vector3( 0, 0, 0 ), normalised, normalised + count ) ) { @@ -996,11 +913,10 @@ void BestPoint( std::size_t count, Vector4 clipped[9], SelectionIntersection& be plane = &plaine; } //globalOutputStream() << plane.a << " " << plane.b << " " << plane.c << " " << "\n"; - point_iterator_t end = normalised + count; + const point_iterator_t end = normalised + count; for ( point_iterator_t previous = end - 1, current = normalised; current != end; previous = current, ++current ) { - Segment3D segment( *previous, *current ); - Point3D point = segment_closest_point_to_point( segment, Vector3( 0, 0, 0 ) ); + Vector3 point = line_closest_point( Line( *previous, *current ), Vector3( 0, 0, 0 ) ); float depth = point.z(); point.z() = 0; float distance = static_cast( vector3_length_squared( point ) ); @@ -2722,11 +2638,10 @@ class PlaneSelectable_bestPlaneIndirect : public scene::Graph::Walker SelectionTest& m_test; Plane3& m_plane; Vector3& m_intersection; -const Vector3& m_viewer; mutable float m_dist; public: -PlaneSelectable_bestPlaneIndirect( SelectionTest& test, Plane3& plane, Vector3& intersection, const Vector3& viewer ) - : m_test( test ), m_plane( plane ), m_intersection( intersection ), m_viewer( viewer ), m_dist( FLT_MAX ){ +PlaneSelectable_bestPlaneIndirect( SelectionTest& test, Plane3& plane, Vector3& intersection ) + : m_test( test ), m_plane( plane ), m_intersection( intersection ), m_dist( FLT_MAX ){ } bool pre( const scene::Path& path, scene::Instance& instance ) const { if ( path.top().get().visible() ) { @@ -2734,7 +2649,7 @@ bool pre( const scene::Path& path, scene::Instance& instance ) const { if ( selectable != 0 && selectable->isSelected() ) { PlaneSelectable* planeSelectable = Instance_getPlaneSelectable( instance ); if ( planeSelectable != 0 ) { - planeSelectable->bestPlaneIndirect( m_test, m_plane, m_intersection, m_dist, m_viewer ); + planeSelectable->bestPlaneIndirect( m_test, m_plane, m_intersection, m_dist ); } } } @@ -2763,7 +2678,7 @@ bool pre( const scene::Path& path, scene::Instance& instance ) const { } }; -bool Scene_forEachPlaneSelectable_selectPlanes2( scene::Graph& graph, SelectionTest& test, const Vector3& viewer, TranslateAxis2& translateAxis ){ +bool Scene_forEachPlaneSelectable_selectPlanes2( scene::Graph& graph, SelectionTest& test, TranslateAxis2& translateAxis ){ Plane3 plane( 0, 0, 0, 0 ); graph.traverse( PlaneSelectable_bestPlaneDirect( test, plane ) ); if( plane3_valid( plane ) ){ @@ -2772,7 +2687,7 @@ bool Scene_forEachPlaneSelectable_selectPlanes2( scene::Graph& graph, SelectionT } else{ Vector3 intersection; - graph.traverse( PlaneSelectable_bestPlaneIndirect( test, plane, intersection, viewer ) ); + graph.traverse( PlaneSelectable_bestPlaneIndirect( test, plane, intersection ) ); if( plane3_valid( plane ) ){ test.BeginMesh( g_matrix4_identity ); /* may introduce some screen space offset in manipulatable to handle far-from-edge clicks perfectly; thought clicking not so far isn't too nasty, right? */ @@ -3895,7 +3810,7 @@ Vector3 testSelected_scene_snapped_point( const SelectionVolume& test, ClipperSe } } { /* try edges */ - Vector3 edgePoint = segment_closest_point_to_point( Segment3D( ( *prev ).vertex, ( *curr ).vertex ), point ); + Vector3 edgePoint = line_closest_point( Line( ( *prev ).vertex, ( *curr ).vertex ), point ); if( edgePoint != ( *prev ).vertex && edgePoint != ( *curr ).vertex ){ const Vector3 edgedir = vector3_normalised( ( *curr ).vertex - ( *prev ).vertex ); const std::size_t maxi = vector3_max_abs_component_index( edgedir ); @@ -4026,7 +3941,7 @@ void testSelect( const View& view, const Matrix4& pivot2world ){ if( GlobalSelectionSystem().countSelected() != 0 ){ if ( GlobalSelectionSystem().Mode() == SelectionSystem::ePrimitive ){ if( g_bAltResize_AltSelect && view.fill() ){ - m_selected2 = Scene_forEachPlaneSelectable_selectPlanes2( GlobalSceneGraph(), test, Manipulatable::m_view->getViewer(), m_axisResize ); + m_selected2 = Scene_forEachPlaneSelectable_selectPlanes2( GlobalSceneGraph(), test, m_axisResize ); } else{ BooleanSelector booleanSelector; @@ -4492,11 +4407,10 @@ TransformOriginTranslate( TransformOriginTranslatable& transformOriginTranslatab : m_transformOriginTranslatable( transformOriginTranslatable ){ } void Construct( const Matrix4& device2manip, const float x, const float y, const AABB& bounds, const Vector3& transform_origin ){ - point_on_plane( m_start, device2manip, x, y ); + m_start = point_on_plane( device2manip, x, y ); } void Transform( const Matrix4& manip2object, const Matrix4& device2manip, const float x, const float y, const bool snap, const bool snapbbox, const bool alt ){ - Vector3 current; - point_on_plane( current, device2manip, x, y ); + Vector3 current = point_on_plane( device2manip, x, y ); current = vector3_subtracted( current, m_start ); if( snap ){ diff --git a/radiant/surfacedialog.cpp b/radiant/surfacedialog.cpp index 80dfdb1e..19e4a752 100644 --- a/radiant/surfacedialog.cpp +++ b/radiant/surfacedialog.cpp @@ -1557,7 +1557,7 @@ void Face_setTexture( Face& face, const char* shader, const FaceTexture& clipboa face.ProjectTexture( clipboard.m_projection, clipboard.m_plane.normal() ); } else if( mode == ePasteSeamless ){ - DoubleLine line = plane3_intersect_plane3( clipboard.m_plane, face.getPlane().plane3() ); + DoubleRay line = plane3_intersect_plane3( clipboard.m_plane, face.getPlane().plane3() ); if( vector3_length_squared( line.direction ) == 0 ){ face.ProjectTexture( clipboard.m_projection, clipboard.m_plane.normal() ); return; diff --git a/radiant/winding.cpp b/radiant/winding.cpp index 48b9778a..f35d53c6 100644 --- a/radiant/winding.cpp +++ b/radiant/winding.cpp @@ -26,66 +26,6 @@ #include "math/line.h" -inline double plane3_distance_to_point( const Plane3& plane, const DoubleVector3& point ){ - return vector3_dot( point, plane.normal() ) - plane.dist(); -} - -inline double plane3_distance_to_point( const Plane3& plane, const Vector3& point ){ - return vector3_dot( point, plane.normal() ) - plane.dist(); -} - -/// \brief Returns the point at which \p line intersects \p plane, or an undefined value if there is no intersection. -inline DoubleVector3 line_intersect_plane( const DoubleLine& line, const Plane3& plane ){ - return line.origin + vector3_scaled( - line.direction, - -plane3_distance_to_point( plane, line.origin ) - / vector3_dot( line.direction, plane.normal() ) - ); -} - -inline bool float_is_largest_absolute( double axis, double other ){ - return fabs( axis ) > fabs( other ); -} - -/// \brief Returns the index of the component of \p v that has the largest absolute value. -inline int vector3_largest_absolute_component_index( const DoubleVector3& v ){ - return ( float_is_largest_absolute( v[1], v[0] ) ) - ? ( float_is_largest_absolute( v[1], v[2] ) ) - ? 1 - : 2 - : ( float_is_largest_absolute( v[0], v[2] ) ) - ? 0 - : 2; -} - -/// \brief Returns the infinite line that is the intersection of \p plane and \p other. -DoubleLine plane3_intersect_plane3( const Plane3& plane, const Plane3& other ){ - DoubleLine line; - line.direction = vector3_cross( plane.normal(), other.normal() ); - switch ( vector3_largest_absolute_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; -} - #if 0 #include "math/aabb.h" void windingTestInfinity(){ @@ -158,7 +98,7 @@ void windingTestInfinity(){ for( ; i < winding.size(); ++i ){ for( std::size_t j = 0; j < 6; ++j ){ if( vector3_dot( winding[i].edge.direction, worldplanes[j].normal() ) != 0 ){ - const DoubleVector3 v = line_intersect_plane( winding[i].edge, worldplanes[j] ); + const DoubleVector3 v = ray_intersect_plane( winding[i].edge, worldplanes[j] ); if( aabb_intersects_point( world, v ) ){ // globalWarningStream() << " INFINITE POINT INSIDE WORLD\n"; ++windingTestInfinity_FAIL; @@ -226,7 +166,7 @@ void Winding_createInfinite( FixedWinding& winding, const Plane3& plane, double // project a really big axis aligned box onto the plane - DoubleLine r1, r2, r3, r4; + DoubleRay r1, r2, r3, r4; r1.origin = vector3_added( vector3_subtracted( org, vright ), vup ); r1.direction = vector3_normalised( vright ); winding.push_back( FixedWindingVertex( r1.origin, r1, c_brush_maxFaces ) ); @@ -258,7 +198,7 @@ void Winding_createInfinite( FixedWinding& winding, const Plane3& plane, double // project a really big axis aligned box onto the plane - DoubleLine ray; + DoubleRay ray; ray.origin = org - vright + vup; ray.direction = vector3_normalised( vright0 ); winding.push_back( FixedWindingVertex( ray.origin, ray, c_brush_maxFaces ) ); @@ -368,7 +308,7 @@ void Winding_Clip( const FixedWinding& winding, const Plane3& plane, const Plane else { // append intersection point of line and plane to output winding - DoubleVector3 mid( line_intersect_plane( vertex.edge, clipPlane ) ); + DoubleVector3 mid( ray_intersect_plane( vertex.edge, clipPlane ) ); if ( classification == ePlaneFront ) { // this edge lies on the clip plane diff --git a/radiant/winding.h b/radiant/winding.h index b68fdb0f..6c43c395 100644 --- a/radiant/winding.h +++ b/radiant/winding.h @@ -27,6 +27,7 @@ #include #include "math/vector.h" +#include "math/line.h" #include "container/array.h" enum ProjectionAxis @@ -148,21 +149,14 @@ struct Winding } }; -class DoubleLine -{ -public: -DoubleVector3 origin; -DoubleVector3 direction; -}; - class FixedWindingVertex { public: DoubleVector3 vertex; -DoubleLine edge; +DoubleRay edge; std::size_t adjacent; -FixedWindingVertex( const DoubleVector3& vertex_, const DoubleLine& edge_, std::size_t adjacent_ ) +FixedWindingVertex( const DoubleVector3& vertex_, const DoubleRay& edge_, std::size_t adjacent_ ) : vertex( vertex_ ), edge( edge_ ), adjacent( adjacent_ ){ } }; @@ -234,8 +228,6 @@ inline std::size_t Winding_next( const Winding& winding, std::size_t i ){ } -class Plane3; - void Winding_createInfinite( FixedWinding& w, const Plane3& plane, double infinity ); const double ON_EPSILON = 1.0 / ( 1 << 8 ); @@ -285,6 +277,4 @@ inline void Winding_printConnectivity( Winding& winding ){ } } -DoubleLine plane3_intersect_plane3( const Plane3& plane, const Plane3& other ); - #endif