* fix alt + m1 indirect faces picking, when object is partially or fully out of camera view

refactor math functions
This commit is contained in:
Garux 2019-04-28 20:54:29 +03:00
parent b9a43074f0
commit 71c63fbdc6
12 changed files with 218 additions and 287 deletions

View File

@ -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;
};

View File

@ -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;
}
}
}
}
}

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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 ){

View File

@ -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 ){

View File

@ -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 );

View File

@ -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<float>( 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<float>( 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 ){

View File

@ -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;

View File

@ -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

View File

@ -27,6 +27,7 @@
#include <vector>
#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