| 27 | using namespace MR; |
| 28 | |
| 29 | float findAngleDegOfPick( const Vector3f& center, const Vector3f& zeroPoint, const Vector3f& norm, |
| 30 | const Line3f& ray, Viewport& vp, const Vector3f& vpPoint ) |
| 31 | { |
| 32 | Plane3f plane1 = Plane3f::fromDirAndPt( norm, center ).normalized(); |
| 33 | Plane3f plane2 = Plane3f::fromDirAndPt( cross( ray.d, center - ray.p ), center ).normalized(); |
| 34 | auto centerVp = vp.projectToViewportSpace( center ); |
| 35 | auto centerRay = vp.unprojectPixelRay( to2dim( centerVp ) ); |
| 36 | bool parallel = std::abs( dot( centerRay.d.normalized(), norm.normalized() ) ) < 0.25f; |
| 37 | auto planeIntersectionLine = intersection( plane1, plane2 ); |
| 38 | auto radiusVec = ( zeroPoint - center ); |
| 39 | if ( parallel || !planeIntersectionLine ) |
| 40 | { |
| 41 | auto pickProjS = plane1.project( ray.p ); |
| 42 | auto pickProjF = plane1.project( ray.p + ray.d ); |
| 43 | |
| 44 | auto centerProjOnPickLine = Line3f( pickProjS, pickProjF - pickProjS ).project( center ); |
| 45 | |
| 46 | auto radiusSq = radiusVec.lengthSq(); |
| 47 | auto line = center - centerProjOnPickLine; |
| 48 | auto lineSq = line.lengthSq(); |
| 49 | if ( lineSq >= radiusSq ) |
| 50 | planeIntersectionLine = Line3f( centerProjOnPickLine, line ); |
| 51 | else |
| 52 | { |
| 53 | auto pInter = centerProjOnPickLine + ( pickProjS - pickProjF ).normalized() * |
| 54 | std::sqrt( radiusSq - lineSq ); |
| 55 | planeIntersectionLine = Line3f( pInter, center - pInter ); |
| 56 | } |
| 57 | parallel = true; |
| 58 | } |
| 59 | auto vec2 = radiusVec.normalized(); |
| 60 | auto angleSign = mixed( norm.normalized(), planeIntersectionLine->d, vec2 ) < 0.0f ? 1.0f : -1.0f; |
| 61 | auto angleRes = angleSign * angle( planeIntersectionLine->d.normalized(), vec2 ); |
| 62 | auto sinA = std::sin( angleRes ); |
| 63 | auto cosA = std::cos( angleRes ); |
| 64 | auto crossVec = cross( norm.normalized(), vec2 ).normalized(); |
| 65 | auto p1 = center + cosA * vec2 + sinA * crossVec; |
| 66 | auto p2 = center - cosA * vec2 - sinA * crossVec; |
| 67 | |
| 68 | auto p1Vp = vp.projectToViewportSpace( p1 ); |
| 69 | auto p2Vp = vp.projectToViewportSpace( p2 ); |
| 70 | auto dist1 = p1Vp - vpPoint; |
| 71 | auto dist2 = p2Vp - vpPoint; |
| 72 | float diff = 0.0f; |
| 73 | if ( !parallel ) |
| 74 | diff = to2dim( dist1 ).lengthSq() - to2dim( dist2 ).lengthSq(); |
| 75 | else |
| 76 | diff = dist1.z - dist2.z; |
| 77 | |
| 78 | if ( diff > 0.0f || parallel ) |
| 79 | { |
| 80 | if ( angleRes < 0.0f ) |
| 81 | return angleRes + PI_F; |
| 82 | return angleRes - PI_F; |
| 83 | } |
| 84 | return angleRes; |
| 85 | } |
| 86 | } |
no test coverage detected