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 )
		)
	);
}
Exemple #2
0
void StandardNodeGadget::doRender( const Style *style ) const
{
	// decide what state we're rendering in
	Gaffer::ConstScriptNodePtr script = node()->scriptNode();
	
	Style::State state = Style::NormalState;
	if( script && script->selection()->contains( node() ) )
	{
		state = Style::HighlightedState;
	}
	
	// draw 
	Box3f b = bound();

	LinearContainer::Orientation orientation = inputNoduleContainer()->getOrientation();
	
	Box3f inputContainerBound = inputNoduleContainer()->transformedBound( this );
	Box3f outputContainerBound = outputNoduleContainer()->transformedBound( this );
	
	if( !inputContainerBound.isEmpty() )
	{
		if( orientation == LinearContainer::X )
		{
			b.max.y -= inputContainerBound.size().y / 2.0f;
		}
		else
		{
			b.min.x += inputContainerBound.size().x / 2.0f;
		}
	}
	if( !outputContainerBound.isEmpty() )
	{
		if( orientation == LinearContainer::X )
		{
			b.min.y += outputContainerBound.size().y / 2.0f;
		}
		else
		{
			b.max.x -= outputContainerBound.size().x / 2.0f;		
		}
	}

	style->renderFrame( Box2f( V2f( b.min.x, b.min.y ) + V2f( g_borderWidth ), V2f( b.max.x, b.max.y ) - V2f( g_borderWidth ) ), g_borderWidth, state );
	
	NodeGadget::doRender( style );
	
	if( !m_nodeEnabled && !IECoreGL::Selector::currentSelector() )
	{
		/// \todo Replace renderLine() with a specific method (renderNodeStrikeThrough?) on the Style class
		/// so that styles can do customised drawing based on knowledge of what is being drawn.
		style->renderLine( IECore::LineSegment3f( V3f( b.min.x, b.min.y, 0 ), V3f( b.max.x, b.max.y, 0 ) ) );	
	}
}
bool Manipulator::canManipulate(Ray3f ray,Box3f box,Mat4f* T)
{
	//nothing to do
	if (!box.isValid())
		return false;

	Vec3f size=box.size();

	Mat4f Direct=(*T) * getTransformationToBox(box);
    Mat4f Inverse=Direct.invert();

    // the ray is in world coordinate
    Vec3f P1=Inverse * (ray.origin        );
    Vec3f P2=Inverse * (ray.origin+ray.dir);
    
    // should be the unit bounding ball not the bounding box, but seems good enough (probably better)
    // is objects does not overlap too much!
	float epsilon=1e-4f;
	Box3f unit_box(
		Vec3f(
			size[0]?-1:-epsilon,
			size[1]?-1:-epsilon,
			size[2]?-1:-epsilon),
		Vec3f(
			size[0]?+1:+epsilon,
			size[1]?+1:+epsilon,
			size[2]?+1:+epsilon));


	float tmin,tmax;
    return (Ray3f(P1,P2-P1).intersectBox(tmin,tmax,unit_box) && tmin>0);
}
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;
}
Exemple #5
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;
}
Exemple #6
0
void DotNodeGadget::doRender( const Style *style ) const
{
	Style::State state = getHighlighted() ? Style::HighlightedState : Style::NormalState;

	const Box3f b = bound();
	const V3f s = b.size();
	style->renderNodeFrame( Box2f( V2f( 0 ), V2f( 0 ) ), std::min( s.x, s.y ) / 2.0f, state, userColor() );

	NodeGadget::doRender( style );
}
void StandardNodeGadget::doRenderLayer( Layer layer, const Style *style ) const
{
	NodeGadget::doRenderLayer( layer, style );

	switch( layer )
	{
		case GraphLayer::Nodes :
		{
			// decide what state we're rendering in
			Style::State state = getHighlighted() ? Style::HighlightedState : Style::NormalState;

			// draw our background frame
			const Box3f b = bound();
			float borderWidth = g_borderWidth;
			if( m_oval )
			{
				const V3f s = b.size();
				borderWidth = std::min( s.x, s.y ) / 2.0f;
			}

			style->renderNodeFrame(
				Box2f( V2f( b.min.x, b.min.y ) + V2f( borderWidth ), V2f( b.max.x, b.max.y ) - V2f( borderWidth ) ),
				borderWidth,
				state,
				m_userColor.get_ptr()
			);

			break;
		}
		case GraphLayer::Overlay :
		{
			const Box3f b = bound();

			if( !m_nodeEnabled && !IECoreGL::Selector::currentSelector() )
			{
				/// \todo Replace renderLine() with a specific method (renderNodeStrikeThrough?) on the Style class
				/// so that styles can do customised drawing based on knowledge of what is being drawn.
				style->renderLine( IECore::LineSegment3f( V3f( b.min.x, b.min.y, 0 ), V3f( b.max.x, b.max.y, 0 ) ) );
			}
			break;
		}
		default :
			break;
	}
}
Exemple #8
0
void DotNodeGadget::doRender( const Style *style ) const
{
	Style::State state = getHighlighted() ? Style::HighlightedState : Style::NormalState;

	const Box3f b = bound();
	const V3f s = b.size();
	style->renderNodeFrame( Box2f( V2f( 0 ), V2f( 0 ) ), std::min( s.x, s.y ) / 2.0f, state, userColor() );

	if( !m_label.empty() && !IECoreGL::Selector::currentSelector() )
	{
		glPushMatrix();
		IECoreGL::glTranslate( m_labelPosition );
		style->renderText( Style::LabelText, m_label );
		glPopMatrix();
	}

	NodeGadget::doRender( style );
}
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;
}
Exemple #10
0
SmartPointer<Batch> Batch::Cube(const Box3f& box)
{
	SmartPointer<Vector> vertices;
	vertices.reset(new Vector(6*4*3));float* V=vertices->mem();
	
	SmartPointer<Vector> normals;
	normals.reset (new Vector(6*4*3));float* N=normals->mem();

	static float n[6][3]   = {{-1.0, 0.0, 0.0},{0.0, 1.0, 0.0},{1.0, 0.0, 0.0},{0.0, -1.0, 0.0},{0.0, 0.0, 1.0},{0.0, 0.0, -1.0}};
	static int faces[6][4] = {{0, 1, 2, 3},{3, 2, 6, 7},{7, 6, 5, 4},{4, 5, 1, 0},{5, 6, 2, 1},{7, 4, 0, 3}};

	float v[8][3];
	v[0][0] = v[1][0] = v[2][0] = v[3][0] = v[0][1] = v[1][1] = v[4][1] = v[5][1] = v[0][2] = v[3][2] = v[4][2] = v[7][2] = 0;
	v[4][0] = v[5][0] = v[6][0] = v[7][0] = v[2][1] = v[3][1] = v[6][1] = v[7][1] = v[1][2] = v[2][2] = v[5][2] = v[6][2] = 1;

	for (int i = 5; i >= 0; i--) 
	{
		float* v0=&v[faces[i][0]][0];* V++=v0[0]; *V++=v0[1]; *V++=v0[2];
		float* v1=&v[faces[i][1]][0];* V++=v1[0]; *V++=v1[1]; *V++=v1[2];
		float* v2=&v[faces[i][2]][0];* V++=v2[0]; *V++=v2[1]; *V++=v2[2];
		float* v3=&v[faces[i][3]][0];* V++=v3[0]; *V++=v3[1]; *V++=v3[2];

		float* normal=&n[i][0];
		
		*N++=normal[0];*N++=normal[1];*N++=normal[2];
		*N++=normal[0];*N++=normal[1];*N++=normal[2];
		*N++=normal[0];*N++=normal[1];*N++=normal[2];
		*N++=normal[0];*N++=normal[1];*N++=normal[2];
	}

	SmartPointer<Batch> batch(new Batch);
	batch->primitive=Batch::QUADS;
	batch->matrix=Mat4f::translate(box.p1)*Mat4f::scale(box.size());
	batch->vertices = vertices;
	batch->normals  = normals;
	return batch;
}
void BackdropNodeGadget::doRender( const Style *style ) const
{
	// this is our bound in gadget space
	Box2f bound = boundPlug()->getValue();
	
	// but because we're going to draw our contents at an arbitrary scale,
	// we need to compute a modified bound which will be in the right place
	// following scaling. 
	
	const Backdrop *backdrop = static_cast<const Backdrop *>( node() );
	const float scale = backdrop->scalePlug()->getValue();
	
	bound.min /= scale;
	bound.max /= scale;
	
	glPushMatrix();
	
	glScalef( scale, scale, scale );

	const Box3f titleCharacterBound = style->characterBound( Style::HeadingText );
	const float titleBaseline = bound.max.y - g_margin - titleCharacterBound.max.y;

	if( IECoreGL::Selector::currentSelector() )
	{
		// when selecting we render in a simplified form.
		// we only draw a thin strip around the edge of the backdrop
		// to allow the edges to be grabbed for dragging, and a strip
		// at the top to allow the title header to be grabbed for moving
		// around. leaving the main body of the backdrop as a hole is
		// necessary to allow the GraphGadget to continue to perform
		// drag selection on the nodes on top of the backdrop.
		
		const float width = hoverWidth() / scale;
			
		style->renderSolidRectangle( Box2f( bound.min, V2f( bound.min.x + width, bound.max.y ) ) ); // left
		style->renderSolidRectangle( Box2f( V2f( bound.max.x - width, bound.min.y ), bound.max ) ); // right
		style->renderSolidRectangle( Box2f( bound.min, V2f( bound.max.x, bound.min.y + width ) ) ); // bottom
		style->renderSolidRectangle( Box2f( V2f( bound.min.x, bound.max.y - width ), bound.max ) ); // top
		style->renderSolidRectangle( Box2f( V2f( bound.min.x, titleBaseline - g_margin ), bound.max ) ); // heading
	}
	else
	{
		// normal drawing mode
	
		style->renderBackdrop( bound, getHighlighted() ? Style::HighlightedState : Style::NormalState );

		const std::string title = backdrop->titlePlug()->getValue();
		if( title.size() )
		{
			Box3f titleBound = style->textBound( Style::HeadingText, title );
			glPushMatrix();
				glTranslatef( bound.center().x - titleBound.size().x / 2.0f, titleBaseline, 0.0f );
				style->renderText( Style::HeadingText, title );
			glPopMatrix();
		}

		if( m_hovered )
		{
			style->renderHorizontalRule(
				V2f( bound.center().x, titleBaseline - g_margin / 2.0f ),
				bound.size().x - g_margin * 2.0f,
				Style::HighlightedState
			);
		}

		Box2f textBound = bound;
		textBound.min += V2f( g_margin );
		textBound.max = V2f( textBound.max.x - g_margin, titleBaseline - g_margin );
		if( textBound.hasVolume() )
		{
			std::string description = backdrop->descriptionPlug()->getValue();
			style->renderWrappedText( Style::BodyText, description, textBound );
		}
	}
	
	glPopMatrix();
}
void LinearContainer::calculateChildTransforms() const
{
	if( m_clean )
	{
		return;
	}

	int axis = m_orientation - 1;
	V3f size( 0 );
	vector<Box3f> bounds;
	for( ChildContainer::const_iterator it=children().begin(); it!=children().end(); it++ )
	{
		const Gadget *child = static_cast<const Gadget *>( it->get() );
		if( !child->getVisible() )
		{
			continue;
		}

		Box3f b = child->bound();
		if( !b.isEmpty() )
		{
			for( int a=0; a<3; a++ )
			{
				if( a==axis )
				{
					size[a] += b.size()[a];
				}
				else
				{
					size[a] = max( size[a], b.size()[a] );
				}
			}
		}
		bounds.push_back( b );
	}
	size[axis] += (bounds.size() - 1) * m_spacing;

	float offset = size[axis] / 2.0f  * ( m_direction==Increasing ? -1.0f : 1.0f );

	int i = 0;
	for( ChildContainer::const_iterator it=children().begin(); it!=children().end(); it++ )
	{
		Gadget *child = static_cast<Gadget *>( it->get() );
		if( !child->getVisible() )
		{
			continue;
		}

		const Box3f &b = bounds[i++];

		V3f childOffset( 0 );
		if( !b.isEmpty() )
		{
			for( int a=0; a<3; a++ )
			{
				if( a==axis )
				{
					childOffset[a] = offset - ( m_direction==Increasing ? b.min[a] : b.max[a] );
				}
				else
				{
					switch( m_alignment )
					{
						case Min :
							childOffset[a] = -size[a]/2.0f - b.min[a];
							break;
						case Centre :
							childOffset[a] = -b.center()[a];
							break;
						default :
							// max
							childOffset[a] = size[a]/2.0f - b.max[a];
					}
				}
			}
			offset += b.size()[axis] * ( m_direction==Increasing ? 1.0f : -1.0f );
		}
		offset += m_spacing * ( m_direction==Increasing ? 1.0f : -1.0f );

		M44f m; m.translate( childOffset );
		child->setTransform( m );
	}

	m_clean = true;
}
Exemple #13
0
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
void Batch::saveObj(std::string filename,std::vector<SmartPointer<Batch> > batches)
{
	FILE* file=fopen(FileSystem::FullPath(filename).c_str(),"wt");
	XgeReleaseAssert(file);

	Box3f box;
	for (int I=0;I<(int)batches.size();I++)
	{
		SmartPointer<Batch> batch=batches[I];
		box.add(batch->getBox());
	}

	Mat4f ToUnitBox= Mat4f::scale(1.0f/box.size().x,1.0f/box.size().y,1.0f/box.size().z) * Mat4f::translate(-box.p1.x,-box.p1.y,-box.p1.z);


	int Cont=1;

	for (int I=0;I<(int)batches.size();I++)
	{
		SmartPointer<Batch> batch=batches[I];

		//TODO: all other cases
		XgeReleaseAssert(batch->primitive==Batch::TRIANGLES);

		Mat4f matrix=batch->matrix;

		matrix=ToUnitBox * matrix;

		Mat4f inv=matrix.invert();

		/*XgeReleaseAssert(batch->texture1);
		XgeReleaseAssert(batch->texture1->width==batch->texture1->height);
		int texturedim=batch->texture1->width;*/

		int nv=batch->vertices->size()/3;
		int nt=nv/3;

		XgeReleaseAssert(batch->vertices);
		XgeReleaseAssert(batch->normals);
		//XgeReleaseAssert(batch->texture1coords);

		float* vertex     = batch->vertices->mem();
		float* normal     = batch->normals ->mem();
		//float* lightcoord = batch->texture1coords->mem();

		for (int i=0;i<nt;i++,vertex+=9,normal+=9)
		{
			Vec3f v0(vertex[0],vertex[1],vertex[2]) ; v0=matrix * v0; 
			Vec3f v1(vertex[3],vertex[4],vertex[5]) ; v1=matrix * v1; 
			Vec3f v2(vertex[6],vertex[7],vertex[8]) ; v2=matrix * v2; 

			Vec4f _n0(normal[0],normal[1],normal[2],0.0);  _n0=_n0 * inv;  Vec3f n0=Vec3f(_n0.x,_n0.y,_n0.z).normalize();
			Vec4f _n1(normal[3],normal[4],normal[5],0.0);  _n1=_n1 * inv;  Vec3f n1=Vec3f(_n1.x,_n1.y,_n1.z).normalize();
			Vec4f _n2(normal[6],normal[7],normal[8],0.0);  _n2=_n2 * inv;  Vec3f n2=Vec3f(_n2.x,_n2.y,_n2.z).normalize();

			/*float s0=lightcoord[i*6+0],t0=lightcoord[i*6+1];
			float s1=lightcoord[i*6+2],t1=lightcoord[i*6+3];
			float s2=lightcoord[i*6+4],t2=lightcoord[i*6+5];*/

			// force the regeneration of float values (seems perfect  for opengl/ renderman scan line conversion!)
			/*s0=(0.5f/(float)texturedim)+(((int)(s0*(float)texturedim))/(float)texturedim);t0=(0.5f/(float)texturedim)+(((int)(t0*(float)texturedim))/(float)texturedim);
			s1=(0.5f/(float)texturedim)+(((int)(s1*(float)texturedim))/(float)texturedim);t1=(0.5f/(float)texturedim)+(((int)(t1*(float)texturedim))/(float)texturedim);
			s2=(0.5f/(float)texturedim)+(((int)(s2*(float)texturedim))/(float)texturedim);t2=(0.5f/(float)texturedim)+(((int)(t2*(float)texturedim))/(float)texturedim);
			*/

			fprintf(file,Utils::Format("v %e %e %e\n",v0.x,v0.y,v0.z).c_str());
			fprintf(file,Utils::Format("v %e %e %e\n",v1.x,v1.y,v1.z).c_str());
			fprintf(file,Utils::Format("v %e %e %e\n",v2.x,v2.y,v2.z).c_str());

			//fprintf(file,Utils::Format("vt %e %e\n",s0,t0).c_str());
			//fprintf(file,Utils::Format("vt %e %e\n",s1,t1).c_str());
			//fprintf(file,Utils::Format("vt %e %e\n",s2,t2).c_str());

			fprintf(file,Utils::Format("vn %e %e %e\n",n0.x,n0.y,n0.z).c_str());
			fprintf(file,Utils::Format("vn %e %e %e\n",n1.x,n1.y,n1.z).c_str());
			fprintf(file,Utils::Format("vn %e %e %e\n",n2.x,n2.y,n2.z).c_str());

			fprintf(file,Utils::Format("f %d//%d %d//%d %d//%d\n",
				Cont+0,Cont+0,
				Cont+1,Cont+1,
				Cont+2,Cont+2).c_str());

			/*fprintf(file,Utils::Format("f %d/%d/%d %d/%d/%d %d/%d/%d\n",
				Cont+0,Cont+0,Cont+0,
				Cont+1,Cont+1,Cont+1,
				Cont+2,Cont+2,Cont+2).c_str());*/

			Cont+=3;
		}
	}

	fclose(file);
}