Scissor Rects

What it says on the tin: a place to discuss proposed new features.
Post Reply
Llock
Greenskin
Posts: 100
Joined: Wed Nov 22, 2006 4:51 pm

Scissor Rects

Post by Llock »

This may blur the line between help and features, but it's more of a "could we get this feature if it doesn't exist".

I'm building a GUI engine in ogre, based around Manual Object. What I'm looking for now is a scissor rect for clipping my 2D Text, and, in the case of a complex list box, clipping the list box data.

By complex I mean, list box items are like forms where you can specify that this list box item has a check box, button, text and radio buttons on it. I'd love for that to be smoothly scrolled, but not pop between elements. The best way to do this, I would think is through a scissor rect for both text and a complicated list box like this.

I'm wondering
1) Do we have scissor rects at all (I'm having trouble finding anything about them online here). If we don't can we get them <grin>

2) Do we have scissor rects in the software level so if people don't natively support it, it's still handled? If we don't, can we get them?

3) And as more of a "help" question, if we do have these rects already, can they be applied easily in the roles I described above, and are there any examples of these somewhere?

4) If we don't have these, and I was too pursue building them myself, where would you guys suggest/want something like this added in case you want to integrate it later on to the code base.

Thanks!
Llock
User avatar
Falagard
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 2060
Joined: Thu Feb 26, 2004 12:11 am
Location: Toronto, Canada
x 4
Contact:

Post by Falagard »

Take a look at RenderSystem::setScissorTest()

Always a good idea to search the Ogre source code for what you're looking for.

It's dependent on hardware support, and you can check for the capabilities.

I'm guessing any competent hardware can support it.
Llock
Greenskin
Posts: 100
Joined: Wed Nov 22, 2006 4:51 pm

Post by Llock »

Thanks for the feeback, I moved my follow up questions on the topic to
http://www.ogre3d.org/phpBB2/viewtopic. ... highlight=

Someone else is searching for the same solution, but without answers thus far.

Thanks again for the quick response!
Llock
jorgecabezas
Gnoblar
Posts: 9
Joined: Mon Jun 04, 2007 4:01 pm

Post by jorgecabezas »

Hi,

I was looking for the same and I finally inherited from SceneManager and overwrite the _updateFromParent method ( I added virtual to it on SceneNode, I think ), and did all the stuff by myself, here is the code.

This code it will work only on my system, but I hope it could help ( SetScissorClipping is added to my TSurface class, which is inherited from SimpleRenderable ), and it activates scissor clipping.

See you!

Code: Select all

		/*! Update the clipping area
		 */
		void TNode::UpdateClipping( TBool *clipping_flag, SDL_Rect *clipping_rect ) const
		{

			SDL_Rect canvas_clipping = m_ClippingArea;
			
			canvas_clipping.x += mDerivedPosition.x;
			canvas_clipping.y += mDerivedPosition.y;
			canvas_clipping.w *= mScale.x;
			canvas_clipping.h *= mScale.y;

			if( *clipping_flag ) {
				if(m_Clipping)
				{
					if( canvas_clipping.x > clipping_rect->x + clipping_rect->w  ||
						canvas_clipping.y > clipping_rect->y + clipping_rect->h  ||
						canvas_clipping.x + canvas_clipping.w < clipping_rect->x ||
						canvas_clipping.y + canvas_clipping.h < clipping_rect->y ) {

							SDL_Rect r = {0, 0, 0, 0};
							*clipping_rect = r;

					} else {
						float right  = (float)min( canvas_clipping.x + canvas_clipping.w,
							clipping_rect->x + clipping_rect->w );
						float left   = max( canvas_clipping.x,
							clipping_rect->x);
						float bottom = (float)min( canvas_clipping.y + canvas_clipping.h,
							clipping_rect->y + clipping_rect->h );
						float top    = max( canvas_clipping.y,
							clipping_rect->y );
						SDL_Rect r = { left, top, (right - left), (bottom - top) };
						*clipping_rect = r;
					}
				}
			} else {
				*clipping_rect = canvas_clipping;
				*clipping_flag = m_Clipping;				
			}
		} 

		//-----------------------------------------------------------------------
		void TNode::_updateFromParent(void) const
		{
			if (mParent)
			{
				// Transformations : T1*R1*S1*T2*R2*S2				

				const TNode *parent_tnode = dynamic_cast<const TNode *>(mParent);

				// parent transformation
				Matrix4 m = Matrix4::IDENTITY;
				if(parent_tnode)
				{
					m = parent_tnode->m_WorldMat;
				} 
				else
				{ 
					m.makeTransform(mParent->_getDerivedPosition(),
						mParent->_getDerivedScale(),
						mParent->_getDerivedOrientation());
				}

				// node transformation
				// translate
				Matrix4 t(  1.0f,			0.0f,			0.0f,			mPosition.x,
							0.0f,			1.0f,			0.0f,			mPosition.y,
							0.0f,			0.0f,			1.0f,			mPosition.z,
							0.0f,			0.0f,			0.0f,			1.0f);

				// skewing matrix
				Matrix4 sk( mScale.x,				m_SkewX,						0.0f,			0.0f,
							m_SkewY,				mScale.y,						0.0f,			0.0f,
							0.0f,					0.0f,							mScale.z,		0.0f,
							0.0f,					0.0f,							0.0f,			1.0f);

				// scale
				Matrix4 s( mScale.x,				0.0f,							0.0f,			0.0f,
						   0.0f,					mScale.y,						0.0f,			0.0f,
						   0.0f,					0.0f,							mScale.z,		0.0f,
						   0.0f,					0.0f,							0.0f,			1.0f);

				// translate pivot
				Matrix4 p( 1.0f,			0.0f,			0.0f,			-m_PivotX,
						   0.0f,			1.0f,			0.0f,			-m_PivotY,
						   0.0f,			0.0f,			1.0f,			0.0f,
						   0.0f,			0.0f,			0.0f,			1.0f);

				m = m*t;
				if(m_Skew)
				{
					m = m*sk;
				}
				else
				{
					m = m*mOrientation;
					m = m*s;
				}
				for(TU32 j=0;j<16;j++)
					m_WorldMat._m[j] = m._m[j];

				m = m*p; 

				Matrix3 m3;
				m.extract3x3Matrix(m3);

				mDerivedScale = Presentation::getScale(m3);

				RemoveScale(m3);
				mDerivedOrientation = Quaternion(m3);

				mDerivedPosition = m.getTrans();

				// update clipping
				if(parent_tnode)
				{
					m_PaintClippingFlag = parent_tnode->m_PaintClippingFlag;
					m_PaintClippingRect = parent_tnode->m_PaintClippingRect;

					UpdateClipping(&m_PaintClippingFlag,&m_PaintClippingRect);
				}

				m_Min.x = 10000000.0f;
				m_Min.y = 10000000.0f;
				m_Max.x = -10000000.0f;
				m_Max.y = -10000000.0f;

				// get the clipping from the parent
				ConstObjectIterator obji = this->getAttachedObjectIterator();
				while (obji.hasMoreElements())
				{
					MovableObject* mobj = obji.getNext();
					if (mobj->getMovableType() == "Surface")
					{	
						if(((TSurface *)mobj)->getVisible())
						{
							((TSurface *)mobj)->SetScissorClipping(m_PaintClippingFlag,
								m_PaintClippingRect.x,m_PaintClippingRect.y,
								m_PaintClippingRect.w,m_PaintClippingRect.h);
							if(!m_Container) ((TSurface *)mobj)->CalculateBoundingBox(m,m_PaintClippingFlag,&m_PaintClippingRect);
							else ((TSurface *)mobj)->CalculateBoundingBox(m,m_ContainerWidth,m_ContainerHeight,m_PaintClippingFlag,&m_PaintClippingRect);

							if(((TSurface *)mobj)->m_Min.x < m_Min.x) m_Min.x = ((TSurface *)mobj)->m_Min.x;
							if(((TSurface *)mobj)->m_Min.y < m_Min.y) m_Min.y = ((TSurface *)mobj)->m_Min.y;
							if(((TSurface *)mobj)->m_Max.x > m_Max.x) m_Max.x = ((TSurface *)mobj)->m_Max.x;
							if(((TSurface *)mobj)->m_Max.y > m_Max.y) m_Max.y = ((TSurface *)mobj)->m_Max.y;
						}
					}
					if (mobj->getMovableType() == "FontSurface")
					{
						if(((TSurface *)mobj)->getVisible())
						{
							((TFontSurface *)mobj)->SetScissorClipping(m_PaintClippingFlag,
								m_PaintClippingRect.x,m_PaintClippingRect.y,
								m_PaintClippingRect.w,m_PaintClippingRect.h);
							((TFontSurface *)mobj)->CalculateBoundingBox(m,m_PaintClippingFlag,&m_PaintClippingRect);							

							if(((TFontSurface *)mobj)->m_Min.x < m_Min.x) m_Min.x = ((TFontSurface *)mobj)->m_Min.x;
							if(((TFontSurface *)mobj)->m_Min.y < m_Min.y) m_Min.y = ((TFontSurface *)mobj)->m_Min.y;
							if(((TFontSurface *)mobj)->m_Max.x > m_Max.x) m_Max.x = ((TFontSurface *)mobj)->m_Max.x;
							if(((TFontSurface *)mobj)->m_Max.y > m_Max.y) m_Max.y = ((TFontSurface *)mobj)->m_Max.y;
						}
					}
				}

			}
			else
			{
				// Root node, no parent
				mDerivedOrientation = mOrientation;
				mDerivedPosition = mPosition;
				mDerivedScale = mScale;
			}

			mCachedTransformOutOfDate = true;
			mNeedParentUpdate = false;

			// Call listener (note, this method only called if there's something to do)
			if (mListener)
			{
				mListener->nodeUpdated(this);
			}
		}
Llock wrote:Thanks for the feeback, I moved my follow up questions on the topic to
http://www.ogre3d.org/phpBB2/viewtopic. ... highlight=

Someone else is searching for the same solution, but without answers thus far.

Thanks again for the quick response!
Llock
Post Reply