size_t closestPointToRay(const V3f* points, size_t nPoints, const V3f& rayOrigin, const V3f& rayDirection, double longitudinalScale, double* distance) { const V3f T = rayDirection.normalized(); const double f = longitudinalScale*longitudinalScale - 1; size_t nearestIdx = -1; double nearestDist2 = DBL_MAX; for(size_t i = 0; i < nPoints; ++i) { const V3f v = points[i] - rayOrigin; // vector from ray origin to point const double a = v.dot(T); // distance along ray to point of closest approach to test point const double r2 = v.length2() + f*a*a; if(r2 < nearestDist2) { // new closest angle to axis nearestDist2 = r2; nearestIdx = i; } } if(distance) { if(nPoints == 0) *distance = DBL_MAX; else *distance = sqrt(nearestDist2); } return nearestIdx; }
bool intersectP(CRay& _ray) { if (_ray.m_id == m_id) return false; V3f oc = _ray.m_pos - m_c; float a = _ray.m_dir.dot(_ray.m_dir); // dir should be unit float b = _ray.m_dir.dot(oc); float c = oc.dot(oc) - m_r2; float delta = b * b - a * c; if (delta < 0) // no solution return false; else if (delta > -EPS && delta < EPS) { // one solution float t = - b / a; if (t > _ray.m_t_max || t < _ray.m_t_min) // out of range return false; } else { // two solutions float deltasqrt = sqrt(delta); float t1 = (- b - deltasqrt) / a; float t2 = (- b + deltasqrt) / a; if (t1 >= _ray.m_t_max || t1 <= _ray.m_t_min) return false; if (t2 >= _ray.m_t_max || t2 <= _ray.m_t_min) return false; } return true; }
bool intersect(CRay& _ray, float* _thit, CLocalGeo* _local, int& _id) { if (_ray.m_id == m_id) return false; float t; V3f oc = _ray.m_pos - m_c; float a = _ray.m_dir.dot(_ray.m_dir); // dir should be unit float b = _ray.m_dir.dot(oc); float c = oc.dot(oc) - m_r2; float delta = b * b - a * c; if (delta < 0) // no solution return false; else if (delta > -EPS && delta < EPS) { // one solution t = - b / a; if (t > _ray.m_t_max || t < _ray.m_t_min) // out of range return false; } else { // two solutions float deltasqrt = sqrt(delta); float t1 = (- b - deltasqrt) / a; float t2 = (- b + deltasqrt) / a; bool flag = false; t = _ray.m_t_max; if (t1 <= _ray.m_t_max && t1 >= _ray.m_t_min) { flag = true; t = min(t, t1); } if (t2 <= _ray.m_t_max && t2 >= _ray.m_t_min) { flag = true; t = min(t, t2); } if (!flag) // both out of range return false; } // pass t, compute CLocalGeo *_thit = t; _id = m_id; _local->m_pos = _ray.Ray_t(t); _local->m_n = _local->m_pos - m_c; _local->m_n = _local->m_n / _local->m_n.norm(); return true; }
/// \todo Use IECore::RadixSort (might still want to use std::sort for small numbers of points - profile to check this) void PointsPrimitive::depthSort() const { V3f cameraDirection = Camera::viewDirectionInObjectSpace(); cameraDirection.normalize(); const vector<V3f> &points = m_memberData->points->readable(); if( !m_memberData->depthOrder.size() ) { // never sorted before. initialize space. m_memberData->depthOrder.resize( points.size() ); for( unsigned int i=0; i<m_memberData->depthOrder.size(); i++ ) { m_memberData->depthOrder[i] = i; } m_memberData->depths.resize( points.size() ); } else { // sorted before. see if the camera direction has changed enough // to warrant resorting. if( cameraDirection.dot( m_memberData->depthCameraDirection ) > 0.95 ) { return; } } m_memberData->depthCameraDirection = cameraDirection; // calculate all distances for( unsigned int i=0; i<m_memberData->depths.size(); i++ ) { m_memberData->depths[i] = points[i].dot( m_memberData->depthCameraDirection ); } // sort based on those distances SortFn sorter( m_memberData->depths ); sort( m_memberData->depthOrder.begin(), m_memberData->depthOrder.end(), sorter ); }
void GraphGadget::calculateDragSnapOffsets( Gaffer::Set *nodes ) { m_dragSnapOffsets[0].clear(); m_dragSnapOffsets[1].clear(); std::vector<const ConnectionGadget *> connections; for( size_t i = 0, s = nodes->size(); i < s; ++i ) { Gaffer::Node *node = runTimeCast<Gaffer::Node>( nodes->member( i ) ); if( !node ) { continue; } connections.clear(); connectionGadgets( node, connections, nodes ); for( std::vector<const ConnectionGadget *>::const_iterator it = connections.begin(), eIt = connections.end(); it != eIt; ++it ) { // get the node gadgets at either end of the connection const ConnectionGadget *connection = *it; const Nodule *srcNodule = connection->srcNodule(); const Nodule *dstNodule = connection->dstNodule(); const NodeGadget *srcNodeGadget = srcNodule->ancestor<NodeGadget>(); const NodeGadget *dstNodeGadget = dstNodule->ancestor<NodeGadget>(); if( !srcNodeGadget || !dstNodeGadget ) { continue; } // check that the connection tangents are opposed - if not we don't want to snap V3f srcTangent = srcNodeGadget->noduleTangent( srcNodule ); V3f dstTangent = dstNodeGadget->noduleTangent( dstNodule ); if( srcTangent.dot( dstTangent ) > -0.5f ) { continue; } // compute an offset that will bring the src and destination nodules into line const int snapAxis = fabs( srcTangent.x ) > 0.5 ? 1 : 0; V3f srcPosition = V3f( 0 ) * srcNodule->fullTransform(); V3f dstPosition = V3f( 0 ) * dstNodule->fullTransform(); float offset = srcPosition[snapAxis] - dstPosition[snapAxis]; if( dstNodule->plug()->node() != node ) { offset *= -1; } m_dragSnapOffsets[snapAxis].push_back( offset ); // compute an offset that will bring the src and destination nodes into line V3f srcNodePosition = V3f( 0 ) * srcNodeGadget->fullTransform(); V3f dstNodePosition = V3f( 0 ) * dstNodeGadget->fullTransform(); offset = srcNodePosition[snapAxis] - dstNodePosition[snapAxis]; if( dstNodule->plug()->node() != node ) { offset *= -1; } m_dragSnapOffsets[snapAxis].push_back( offset ); // compute an offset that will position the node snugly next to its input // in the other axis. Box3f srcNodeBound = srcNodeGadget->transformedBound( 0 ); Box3f dstNodeBound = dstNodeGadget->transformedBound( 0 ); const int otherAxis = snapAxis == 1 ? 0 : 1; if( otherAxis == 1 ) { offset = dstNodeBound.max[otherAxis] - srcNodeBound.min[otherAxis] + 1.0f; } else { offset = dstNodeBound.min[otherAxis] - srcNodeBound.max[otherAxis] - 1.0f; } if( dstNodule->plug()->node() == node ) { offset *= -1; } m_dragSnapOffsets[otherAxis].push_back( offset ); } } // sort and remove duplicates so that we can use lower_bound() to find appropriate // snap points in dragMove(). for( int axis = 0; axis <= 1; ++axis ) { std::sort( m_dragSnapOffsets[axis].begin(), m_dragSnapOffsets[axis].end() ); m_dragSnapOffsets[axis].erase( std::unique( m_dragSnapOffsets[axis].begin(), m_dragSnapOffsets[axis].end()), m_dragSnapOffsets[axis].end() ); } }