Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
	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; 
	}
Ejemplo n.º 3
0
	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; 
	} 
Ejemplo n.º 4
0
/// \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 );
}
Ejemplo n.º 5
0
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() );
	}
	
}