void BackdropNodeGadget::frame( const std::vector<Gaffer::Node *> &nodes )
{
	GraphGadget *graph = ancestor<GraphGadget>();
	if( !graph )
	{
		return;
	}
	
	Box3f b;
	for( std::vector<Node *>::const_iterator it = nodes.begin(), eIt = nodes.end(); it != eIt; ++it )
	{
		NodeGadget *nodeGadget = graph->nodeGadget( *it );
		if( nodeGadget )
		{
			b.extendBy( nodeGadget->transformedBound( NULL ) );
		}
	}
	
	if( b.isEmpty() )
	{
		return;
	}
	
	graph->setNodePosition( node(), V2f( b.center().x, b.center().y ) );
	
	V2f s( b.size().x / 2.0f, b.size().y / 2.0f );
	
	boundPlug()->setValue(
		Box2f( 
			V2f( -s ) - V2f( g_margin ),
			V2f( s ) + V2f( g_margin + 2.0f * g_margin )
		)
	);
}
void CameraController::frame( const Imath::Box3f &box, const Imath::V3f &viewDirection, const Imath::V3f &upVector )
{
	// make a matrix to centre the camera on the box, with the appropriate view direction
	M44f cameraMatrix = rotationMatrixWithUpDir( V3f( 0, 0, -1 ), viewDirection, upVector );
	M44f translationMatrix;
	translationMatrix.translate( box.center() );
	cameraMatrix *= translationMatrix;

	// translate the camera back until the box is completely visible
	M44f inverseCameraMatrix = cameraMatrix.inverse();
	Box3f cBox = transform( box, inverseCameraMatrix );

	Box2f screenWindow = m_data->screenWindow->readable();
	if( m_data->projection->readable()=="perspective" )
	{
		// perspective. leave the field of view and screen window as is and translate
		// back till the box is wholly visible. this currently assumes the screen window
		// is centred about the camera axis.
		float z0 = cBox.size().x / screenWindow.size().x;
		float z1 = cBox.size().y / screenWindow.size().y;

		m_data->centreOfInterest = std::max( z0, z1 ) / tan( M_PI * m_data->fov->readable() / 360.0 ) + cBox.max.z +
			m_data->clippingPlanes->readable()[0];

		cameraMatrix.translate( V3f( 0.0f, 0.0f, m_data->centreOfInterest ) );
	}
	else
	{
		// orthographic. translate to front of box and set screen window
		// to frame the box, maintaining the aspect ratio of the screen window.
		m_data->centreOfInterest = cBox.max.z + m_data->clippingPlanes->readable()[0] + 0.1; // 0.1 is a fudge factor
		cameraMatrix.translate( V3f( 0.0f, 0.0f, m_data->centreOfInterest ) );

		float xScale = cBox.size().x / screenWindow.size().x;
		float yScale = cBox.size().y / screenWindow.size().y;
		float scale = std::max( xScale, yScale );

		V2f newSize = screenWindow.size() * scale;
		screenWindow.min.x = cBox.center().x - newSize.x / 2.0f;
		screenWindow.min.y = cBox.center().y - newSize.y / 2.0f;
		screenWindow.max.x = cBox.center().x + newSize.x / 2.0f;
		screenWindow.max.y = cBox.center().y + newSize.y / 2.0f;
	}

	m_data->transform->matrix = cameraMatrix;
	m_data->screenWindow->writable() = screenWindow;
}
Beispiel #3
0
Imath::Box3f StandardNodeGadget::bound() const
{
	Box3f b = IndividualContainer::bound();
	
	LinearContainer::Orientation orientation = inputNoduleContainer()->getOrientation();

	if( orientation == LinearContainer::X )
	{
		// enforce a minimum width
		float width = std::max( b.size().x, g_minWidth );
		float c = b.center().x;
		b.min.x = c - width / 2.0f;
		b.max.x = c + width / 2.0f;
	}
	
	// add the missing spacing to the border if we have no nodules on a given side
			
	Box3f inputContainerBound = inputNoduleContainer()->transformedBound( this );
	Box3f outputContainerBound = outputNoduleContainer()->transformedBound( this );
	if( inputContainerBound.isEmpty() )
	{
		if( orientation == LinearContainer::X )
		{
			b.max.y += g_spacing + g_borderWidth;
		}
		else
		{
			b.min.x -= g_spacing + g_borderWidth;		
		}
	}
	
	if( outputContainerBound.isEmpty() )
	{
		if( orientation == LinearContainer::X )
		{
			b.min.y -= g_spacing + g_borderWidth;
		}
		else
		{
			b.max.x += g_spacing + g_borderWidth;
		}
	}
	
	// add on a little bit in the major axis, so that the nodules don't get drawn in the frame corner
	
	if( orientation == LinearContainer::X )
	{
		b.min.x -= g_borderWidth;
		b.max.x += g_borderWidth;
	}
	else
	{
		b.min.y -= g_borderWidth;
		b.max.y += g_borderWidth;
	}
	
	return b;
}
Beispiel #4
0
void StandardNodule::renderLabel( const Style *style ) const
{
	const NodeGadget *nodeGadget = ancestor<NodeGadget>();
	if( !nodeGadget )
	{
		return;
	}

	const std::string &label = plug()->getName().string();

	// we rotate the label based on the angle the connection exits the node at.
	V3f tangent = nodeGadget->noduleTangent( this );
	float theta = IECore::radiansToDegrees( atan2f( tangent.y, tangent.x ) );

	// but we don't want the text to be vertical, so we bend it away from the
	// vertical axis.
	if( ( theta > 0.0f && theta < 90.0f ) || ( theta < 0.0f && theta >= -90.0f ) )
	{
		theta = sign( theta ) * lerp( 0.0f, 45.0f, fabs( theta ) / 90.0f );
	}
	else
	{
		theta = sign( theta ) * lerp( 135.0f, 180.0f, (fabs( theta ) - 90.0f) / 90.0f );
	}

	// we also don't want the text to be upside down, so we correct the rotation
	// if that would be the case.
	Box3f labelBound = style->textBound( Style::LabelText, label );
	V2f anchor( labelBound.min.x - 1.0f, labelBound.center().y );

	if( theta > 90.0f || theta < -90.0f )
	{
		theta = theta - 180.0f;
		anchor.x = labelBound.max.x + 1.0f;
	}

	// now we can actually do the rendering.

	if( getHighlighted() )
	{
		glScalef( 1.2, 1.2, 1.2 );
	}

	glRotatef( theta, 0, 0, 1.0f );
	glTranslatef( -anchor.x, -anchor.y, 0.0f );

	style->renderText( Style::LabelText, label );
}
Beispiel #5
0
static Mat4f getTransformationToBox(Box3f box)
{
	// T_to_box to transform the unit circle in the bounding box
    Vec3f mid=box.center();
    Vec3f size=box.size();


	float max_size=box.maxsize();
	size=Vec3f(max_size,max_size,max_size);

    float cos_pi_4= cos((float)M_PI/4.0);

	float _mat[16]={
	   size.x?(0.5*size.x/cos_pi_4):1.0f , 0                                , 0                               , mid.x,  
	   0                                 , size.y?(0.5*size.y/cos_pi_4):1.0f, 0                               , mid.y, 
	   0                                 , 0                                , size.z?0.5*size.z/cos_pi_4:1.0f , mid.z, 
	   0                                 , 0                                , 0                               , 1    
	};

    Mat4f T_to_box=Mat4f(_mat);
	return T_to_box;
}
Beispiel #6
0
Mesh Mesh::createBox(const Box3f &box) {
    Vector3f center = box.center();
    Vector3f extents = box.extents() * 0.5;
    Mesh mesh;
    int i = 0;
    for (int f = 0; f < 3; ++f) {
        for (int s = -1; s <= 1; s += 2) {
            Vector3f p(center), n(0.f), u(0.f), v(0.f);
            p[f] += extents[f] * s;
            n[f] = s;
            u[(f + 1) % 3] = extents[(f + 1) % 3];
            v[(f + 2) % 3] = extents[(f + 2) % 3];
            mesh.addVertex(p - u - v, n, Vector2f(0.f, 0.f));
            mesh.addVertex(p + u - v, n, Vector2f(1.f, 0.f));
            mesh.addVertex(p - u + v, n, Vector2f(0.f, 1.f));
            mesh.addVertex(p + u + v, n, Vector2f(1.f, 1.f));
            mesh.addTriangle(i, i + 1, i + 2);
            mesh.addTriangle(i + 1, i + 2, i + 3);
            i += 4;
        }
    }
    return mesh;
}
void MultiQuadLight::prepareForRender()
{
    Bvh::PrimVector prims;
    prims.reserve(_geometry.size());

    _bounds = Box3f();

    for (int i = 0; i < _geometry.size(); ++i) {
        Box3f bounds = _geometry.bounds(i);
        _bounds.grow(bounds);

        prims.emplace_back(bounds, bounds.center(), i);
    }

    _triangleAreas.resize(_geometry.triangleCount());
    for (int i = 0; i < _geometry.triangleCount(); ++i) {
        const QuadGeometry::TriangleInfo &t = _geometry.triangle(i);
        _triangleAreas[i] = MathUtil::triangleArea(t.p0, t.p1, t.p2);
    }

    _bvh.reset(new Bvh::BinaryBvh(std::move(prims), 1));

    constructSampleBounds();
}
Beispiel #8
0
// static
bool GeometryUtils::boxTriangleIntersection(
    const Vector3f& u0, const Vector3f& u1, const Vector3f& u2,
    const Box3f& box )
{
    // use separating axis theorem to test overlap between triangle and box
    // need to test for overlap in these directions:
    // 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle
    //    we do not even need to test these)
    // 2) normal of the triangle
    // 3) crossproduct(edge from tri, {x,y,z}-direction)
    //    this gives 3x3=9 more tests

    Vector3f v0;
    Vector3f v1;
    Vector3f v2;

    float min;
    float max;
    float p0;
    float p1;
    float p2;
    float rad;

    float fex;
    float fey;
    float fez;

    Vector3f normal;
    // These are the triangle edges.
    Vector3f e0;
    Vector3f e1;
    Vector3f e2;

    Vector3f boxCenter = box.center();
    Vector3f boxHalfSize = 0.5f * box.size;

    // Move everything so that the box center is in (0,0,0).
    v0 = u0 - boxCenter;
    v1 = u0 - boxCenter;
    v2 = u0 - boxCenter;

    // Compute triangle edges.
    e0 = v1 - v0;
    e1 = v2 - v1;
    e2 = v0 - v2;

    // Bullet 3:
    // Test the 9 tests first (this was faster).
    fex = std::abs( e0.x );
    fey = std::abs( e0.y );
    fez = std::abs( e0.z );
    AXISTEST_X01( e0.z, e0.y, fez, fey );
    AXISTEST_Y02( e0.z, e0.x, fez, fex );
    AXISTEST_Z12( e0.y, e0.x, fey, fex );

    fex = std::abs( e1.x );
    fey = std::abs( e1.y );
    fez = std::abs( e1.z );
    AXISTEST_X01( e1.z, e1.y, fez, fey );
    AXISTEST_Y02( e1.z, e1.x, fez, fex );
    AXISTEST_Z0(  e1.y, e1.x, fey, fex );

    fex = std::abs( e2.x );
    fey = std::abs( e2.y );
    fez = std::abs( e2.z );
    AXISTEST_X2(  e2.z, e2.y, fez, fey );
    AXISTEST_Y1(  e2.z, e2.x, fez, fex );
    AXISTEST_Z12( e2.y, e2.x, fey, fex );


    // Bullet 1:
    //  first test overlap in the {x,y,z}-directions
    //  find min, max of the triangle each direction, and test for overlap in
    //  that direction -- this is equivalent to testing a minimal AABB around
    //  the triangle against the AABB.

    // Test in x direction.
    minMax3( v0.x, v1.x, v2.x, min, max );
    if( min > boxHalfSize.x || max < -boxHalfSize.x )
    {
        return false;
    }


    // Test in y direction.
    minMax3( v0.y, v1.y, v2.y, min, max );
    if( min > boxHalfSize.y || max < -boxHalfSize.y )
    {
        return false;
    }

    // Test in z direction.
    minMax3( v0.z, v1.z, v2.z, min, max );
    if( min > boxHalfSize.z || max < -boxHalfSize.z )
    {
        return false;
    }

    /* Bullet 2: */
    /*  test if the box intersects the plane of the triangle */
    /*  compute plane equation of triangle: normal*x+d=0 */
    normal = Vector3f::cross( e0, e1 );
    if( !planeBoxOverlap( normal, v0, boxHalfSize ) )
    {
        return false;
    }

    return true;   /* box and triangle overlaps */
}
Beispiel #9
0
// static
Box3f Box3f::scale( const Box3f& b, const Vector3f& s )
{
    Vector3f size = s * b.size;
    return{ b.center() - 0.5f * size, size };
}