double precision clipper points

This commit is contained in:
Garux 2021-11-23 16:33:16 +03:00
parent f366f6cc6e
commit e62483970f
3 changed files with 43 additions and 38 deletions

View File

@ -28,32 +28,37 @@
#include "math/plane.h"
/// \brief A line segment defined by a start point and and end point.
class Line
template<typename T>
class Line___
{
public:
Vector3 start, end;
BasicVector3<T> start, end;
Line(){
Line___(){
}
Line( const Vector3& start_, const Vector3& end_ ) : start( start_ ), end( end_ ){
Line___( const BasicVector3<T>& start_, const BasicVector3<T>& end_ ) : start( start_ ), end( end_ ){
}
};
inline Vector3 line_closest_point( const Line& line, const Vector3& point ){
Vector3 v = line.end - line.start;
Vector3 w = point - line.start;
using Line = Line___<float>;
using DoubleLine = Line___<double>;
double c1 = vector3_dot( w,v );
template<typename T>
inline BasicVector3<T> line_closest_point( const Line___<T>& line, const BasicVector3<T>& point ){
BasicVector3<T> v = line.end - line.start;
BasicVector3<T> w = point - line.start;
double c1 = vector3_dot( w, v );
if ( c1 <= 0 ) {
return line.start;
}
double c2 = vector3_dot( v,v );
double c2 = vector3_dot( v, v );
if ( c2 <= c1 ) {
return line.end;
}
return Vector3( line.start + v * ( c1 / c2 ) );
return BasicVector3<T>( line.start + v * ( c1 / c2 ) );
}

View File

@ -26,21 +26,21 @@
class ClipperPoints
{
public:
Vector3 _points[3];
DoubleVector3 _points[3];
std::size_t _count;
ClipperPoints( const Vector3& p0, const Vector3& p1, const Vector3& p2, std::size_t count ){
ClipperPoints( const DoubleVector3& p0, const DoubleVector3& p1, const DoubleVector3& p2, std::size_t count ){
_points[0] = p0;
_points[1] = p1;
_points[2] = p2;
_count = count;
}
ClipperPoints() : _count( 0 ){
_points[0] = _points[1] = _points[2] = Vector3( 0, 0, 0 );
_points[0] = _points[1] = _points[2] = DoubleVector3( 0, 0, 0 );
}
const Vector3& operator[]( std::size_t i ) const {
const DoubleVector3& operator[]( std::size_t i ) const {
return _points[i];
}
Vector3& operator[]( std::size_t i ){
DoubleVector3& operator[]( std::size_t i ){
return _points[i];
}
};

View File

@ -4093,31 +4093,31 @@ public:
}
};
Vector3 testSelected_scene_snapped_point( const SelectionVolume& test, ClipperSelector& clipperSelector ){
Vector3 point = vector4_projected( matrix4_transformed_vector4( test.getScreen2world(), Vector4( 0, 0, clipperSelector.best().depth(), 1 ) ) );
DoubleVector3 testSelected_scene_snapped_point( const SelectionVolume& test, ClipperSelector& clipperSelector ){
DoubleVector3 point = vector4_projected( matrix4_transformed_vector4( test.getScreen2world(), Vector4( 0, 0, clipperSelector.best().depth(), 1 ) ) );
if( clipperSelector.face() ){
const Face& face = *clipperSelector.face();
float bestDist = FLT_MAX;
Vector3 wannabePoint;
double bestDist = FLT_MAX;
DoubleVector3 wannabePoint;
for ( Winding::const_iterator prev = face.getWinding().end() - 1, curr = face.getWinding().begin(); curr != face.getWinding().end(); prev = curr, ++curr ){
const Vector3 v1( prev->vertex );
const Vector3 v2( curr->vertex );
const DoubleVector3 v1( prev->vertex );
const DoubleVector3 v2( curr->vertex );
{ /* try vertices */
const float dist = vector3_length_squared( v2 - point );
const double dist = vector3_length_squared( v2 - point );
if( dist < bestDist ){
wannabePoint = v2;
bestDist = dist;
}
}
{ /* try edges */
Vector3 edgePoint = line_closest_point( Line( v1, v2 ), point );
DoubleVector3 edgePoint = line_closest_point( DoubleLine( v1, v2 ), point );
if( edgePoint != v1 && edgePoint != v2 ){
const Vector3 edgedir = vector3_normalised( v2 - v1 );
const DoubleVector3 edgedir = vector3_normalised( v2 - v1 );
const std::size_t maxi = vector3_max_abs_component_index( edgedir );
// v1[maxi] + edgedir[maxi] * coef = float_snapped( point[maxi], GetSnapGridSize() )
const float coef = ( float_snapped( point[maxi], GetSnapGridSize() ) - v1[maxi] ) / edgedir[maxi];
const double coef = ( float_snapped( point[maxi], GetSnapGridSize() ) - v1[maxi] ) / edgedir[maxi];
edgePoint = v1 + edgedir * coef;
const float dist = vector3_length_squared( edgePoint - point );
const double dist = vector3_length_squared( edgePoint - point );
if( dist < bestDist ){
wannabePoint = edgePoint;
bestDist = dist;
@ -4127,12 +4127,12 @@ Vector3 testSelected_scene_snapped_point( const SelectionVolume& test, ClipperSe
}
if( clipperSelector.best().distance() == 0.f ){ /* try plane, if pointing inside of polygon */
const std::size_t maxi = vector3_max_abs_component_index( face.plane3().normal() );
Vector3 planePoint( vector3_snapped( point, GetSnapGridSize() ) );
DoubleVector3 planePoint( vector3_snapped( point, GetSnapGridSize() ) );
// face.plane3().normal().dot( point snapped ) = face.plane3().dist()
planePoint[maxi] = ( face.plane3().dist()
- face.plane3().normal()[( maxi + 1 ) % 3] * planePoint[( maxi + 1 ) % 3]
- face.plane3().normal()[( maxi + 2 ) % 3] * planePoint[( maxi + 2 ) % 3] ) / face.plane3().normal()[maxi];
const float dist = vector3_length_squared( planePoint - point );
const double dist = vector3_length_squared( planePoint - point );
if( dist < bestDist ){
wannabePoint = planePoint;
bestDist = dist;
@ -4167,7 +4167,7 @@ bool scene_insert_brush_vertices( const View& view, TranslateFreeXY_Z& freeDragX
test.BeginMesh( g_matrix4_identity, true );
if( clipperSelector.isSelected() ){
freeDragXY_Z.set0( vector4_projected( matrix4_transformed_vector4( test.getScreen2world(), Vector4( 0, 0, clipperSelector.best().depth(), 1 ) ) ) );
Vector3 point = testSelected_scene_snapped_point( test, clipperSelector );
DoubleVector3 point = testSelected_scene_snapped_point( test, clipperSelector );
if( !view.fill() ){
point -= view.getViewDir() * GetGridSize();
}
@ -4184,9 +4184,9 @@ bool scene_insert_brush_vertices( const View& view, TranslateFreeXY_Z& freeDragX
freeDragXY_Z.set0( g_vector3_identity );
const AABB bounds = GlobalSelectionSystem().getBoundsSelected();
if( aabb_valid( bounds ) ){
Vector3 xy = vector4_projected( matrix4_transformed_vector4( test.getScreen2world(), Vector4( 0, 0, 0, 1 ) ) );
DoubleVector3 xy = vector4_projected( matrix4_transformed_vector4( test.getScreen2world(), Vector4( 0, 0, 0, 1 ) ) );
vector3_snap( xy, GetSnapGridSize() );
Vector3 a( xy ), b( xy );
DoubleVector3 a( xy ), b( xy );
const std::size_t max = vector3_max_abs_component_index( view.getViewDir() );
a[max] = bounds.origin[max] + bounds.extents[max];
b[max] = bounds.origin[max] - bounds.extents[max];
@ -4528,8 +4528,8 @@ class ClipManipulator : public Manipulator, public ManipulatorSelectionChangeabl
m_p.colour = colour;
}
bool m_set;
Vector3 m_point;
Vector3 m_pointNonTransformed;
DoubleVector3 m_point;
DoubleVector3 m_pointNonTransformed;
char m_name;
Vector3 m_namePos;
};
@ -4648,7 +4648,7 @@ public:
break;
return i % maxi;
}
void newPoint( const Vector3& point, const View& view ){
void newPoint( const DoubleVector3& point, const View& view ){
const std::size_t i = newPointIndex( view.fill() );
if( i == 0 )
m_points[1].m_set = m_points[2].m_set = false;
@ -4664,7 +4664,7 @@ public:
updatePlane();
}
bool testSelect_scene( const View& view, Vector3& point ){
bool testSelect_scene( const View& view, DoubleVector3& point ){
SelectionVolume test( view );
ClipperSelector clipperSelector;
Scene_forEachVisible( GlobalSceneGraph(), view, testselect_scene_4clipper( clipperSelector, test ) );
@ -4679,12 +4679,12 @@ public:
testSelect_points( view );
if( !isSelected() ){
if( view.fill() ){
Vector3 point;
DoubleVector3 point;
if( testSelect_scene( view, point ) )
newPoint( point, view );
}
else{
Vector3 point = vector4_projected( matrix4_transformed_vector4( matrix4_full_inverse( view.GetViewMatrix() ), Vector4( 0, 0, 0, 1 ) ) );
DoubleVector3 point = vector4_projected( matrix4_transformed_vector4( matrix4_full_inverse( view.GetViewMatrix() ), Vector4( 0, 0, 0, 1 ) ) );
vector3_snap( point, GetSnapGridSize() );
{
const std::size_t maxi = vector3_max_abs_component_index( view.getViewDir() );
@ -4752,7 +4752,7 @@ public:
const float device_point[2] = { x, y };
ConstructSelectionTest( scissored, SelectionBoxForPoint( device_point, m_device_epsilon ) );
Vector3 point;
DoubleVector3 point;
if( testSelect_scene( scissored, point ) )
for( std::size_t i = 0; i < 3; ++i )
if( m_points[i].isSelected() ){