• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
mldaalder

Problem with glScissors

21 posts in this topic

Hello everyone, I'm having a slight problem with glScissors, I'm trying to make a basis for my GUI for a template project I'm trying to make. I'm using glScissors to clip the child GUI nodes to fit in their parents. This is result of the code below: This is how it looks like without glScissors enabled: Free Image Hosting at www.ImageShack.us And this is how it should look like: Free Image Hosting at www.ImageShack.us What you see here is that the red rectangle is the root node (for testing I've made it smaller, but normally this would be screen sized and with the colour: 0,0,0,0). The green quad is the first child of the root it has the same dimensions (0.5:0.05) and is offsetted the same as the root (except that it is relative to the root instead of the screen). The blue quad is the grand child of root, it has the same size, but it is offsetted by -0.15:-0.15 so it should disappear partly at the left and top. Last but not least, here is my Node render source:
void GUINode::Render()
{
  // Draw current GUI
  glTranslated(x,y,0);
  glBegin(GL_QUADS);

  glColor4d(r,g,b,a);

  glVertex2d(w,0);
  glVertex2d(0,0);
  glVertex2d(0,h);
  glVertex2d(w,h);

  glEnd();

  // Retrieve viewport and scissor size
  GLint* viewport = new GLint[4];
  GLint* scissor  = new GLint[4];
  glGetIntegerv(GL_VIEWPORT, viewport);
  glGetIntegerv(GL_SCISSOR_BOX, scissor);

  // Calculate new scissor size (if it would be the root node)
  GLint nX,nY,nW,nH;
  nX = (GLint)(scalar(viewport[2])*x)+scissor[0];
  nY = (GLint)(scalar(viewport[3])*y)+scissor[1];
  nW = (GLint)(scalar(viewport[2])*w);
  nH = (GLint)(scalar(viewport[3])*h);

  std::cout<<"Requested:"<<nX<<":"<<nY<<":"<<nW<<":"<<nH<<std::endl;
  std::cout<<"Got:      "<<(scissor[0] > nX ? scissor[0] : nX)<<":"<<
                           (scissor[1] > nY ? scissor[1] : nY)<<":"<<
                           (scissor[2] < nW ? scissor[2] : nW)<<":"<<
                           (scissor[3] < nH ? scissor[3] : nH)<<std::endl;

  // Make the scissor size always smaller
  /* This means that the X and Y values can only get bigger
   * And that the W and H values can only get smaller*/
  glScissor((scissor[0] > nX ? scissor[0] : nX),
            (scissor[1] > nY ? scissor[1] : nY),
            (scissor[2] < nW ? scissor[2] : nW),
            (scissor[3] < nH ? scissor[3] : nH));

  // Go through the child nodes and render them into the visible space of this node
  BOOST_FOREACH(boost::shared_ptr<GUINode>& node, children)
    node->Render();
  // Reset translation for the siblings
  glTranslated(-x,-y,0);
  // Reset scissor for the siblings
  glScissor(scissor[0],scissor[1],
            scissor[2],scissor[3]);
  delete[] viewport;
  delete[] scissor;
}
This is the code that starts the rendering:
void GUIManager::Render()
{
  glPushAttrib(GL_ALL_ATTRIB_BITS);

  glMatrixMode(GL_PROJECTION);
  glPushMatrix();
  glLoadIdentity();

  glMatrixMode(GL_MODELVIEW);
  glPushMatrix();
  glLoadIdentity();

  glOrtho(0.0f,1.0f,1.0f,0.0f,-1.0f,1.0f);


  glDisable(GL_DEPTH_TEST);
  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

  glEnable(GL_SCISSOR_TEST);

  GLint* viewport = new GLint[4];
  glGetIntegerv(GL_VIEWPORT, viewport);
  glScissor(viewport[0],viewport[1],
            viewport[2],viewport[3]);
  delete[] viewport;
  std::cout<<"Starting"<<std::endl;

  root->Render();

  glMatrixMode(GL_PROJECTION);
  glPopMatrix();

  glMatrixMode(GL_MODELVIEW);
  glPopMatrix();

  glPopAttrib();
}
Here is root a GUINode to which all the other nodes are attached to. I'm staring the problem in the face and I can't find it... I just hope that a fresh pair of eyes will spot the error. Thank you for your time.
0

Share this post


Link to post
Share on other sites
Just a guess, but nY seems to be calculated wrong. y=0 is the top of your screen because you flipped the view vertically in glOrtho. Scissor[1] is the bottom of your scissor region though. So try negating y.

I think if you flipped that red box horizontally long the center line you would see the green box is clipped along it's top edge. I would guess the logic for setting the scissor, i.e. "?:", is also wrong and causing the clipping on the blue box to be offset. Correcting nY may correct that though.
0

Share this post


Link to post
Share on other sites
My coordinate system is set correctly (ie. as I wanted it).

The top left corner is 0:0, this is the same as in the clip region, right?
Or is it that the lower left is 0:0 when it comes to clip regions?
I always thought it was the top left, since all the other window coordinate things that I have done is this as well (same screen coordinates, I mean hardware wise here).


I've tried what you suggested, and negating nY is making it worse.

But deducting scissor[1] from nY made the blue box clip correctly.
Just not the green box.


My ?: is correct, as far as I saw it, since the clip region should only get smaller.

The X value of the clip region should either get larger or stay the same.
The Y value of the clip region should either get larger or stay the same.
The W value of the clip region should either get smaller or stay the same.
The H value of the clip region should either get smaller or stay the same.

This results for the X value:
if clipregion.x > nX then
Use clipregion.x
else
Use nX
if clipregion.y > nY then
Use clipregion.y
else
Use nY
if clipregion.w < nW then
Use clipregion.w
else
Use nW
if clipregion.h < nh then
Use clipregion.h
else
Use nH

Or am I missing here something?


I'll try and see if glScissor is looking from the lower left instead of the (by me) expected upper left.
0

Share this post


Link to post
Share on other sites
I use the top left corner as my origin, and I use glScissor to clip my gui to good effect.

I start work in 2d from that origin with:

void OpenGL::_orthoStart( void )
{
glDisable(GL_DEPTH_TEST); // Disables Depth Testing
glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
glPushMatrix(); // Store The Projection Matrix
glLoadIdentity(); // Reset The Projection Matrix

int vPort[4];
glGetIntegerv(GL_VIEWPORT, vPort);
glOrtho(0, vPort[2], vPort[3], 0, -1, 1);

glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
glPushMatrix(); // Store The Modelview Matrix
glLoadIdentity(); // Reset The Modelview Matrix
}



And I change back with:

void OpenGL::_orthoEnd( void )
{
glPopAttrib(); // Pops The Display List Bits
glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
glPopMatrix(); // Restore The Old Projection Matrix
glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
glPopMatrix(); // Restore The Old Projection Matrix
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
}




I set the scissor rect with:

void OpenGL::setClipRect( int x, int y, int w, int h )
{
m_dwClipX = x;
m_dwClipY = y;
m_dwClipW = w;
m_dwClipH = h;

int j = m_iHeight - y - h;
glScissor( x, j, w, h );
}



Where x, y, w, h are the position and dimension of the clip rect, relative to the top left, and m_iHeight is the height of the OpenGL window. glScissor's arguements are specified relative to the bottom left corner if you read the documentation.

I'd also like to point out that using new/delete in your source for getting the viewport/scissor rect is probably not a very good idea.

Regarding your second post about the clip rect only getting smaller, you are right, it should. I accomplish this by having a stack of rects attached to the render. It starts off each frame with a rect in it the size of the OpenGL window. Each window that is clipped adds a rect to the stack. Adding a rect to this stack automatically adjusts the rect being added to fit inside what is ever at the top. This is all done before I get to a gui windows on_paint call. The gui rendering code loops through all windows, for each one it gets the windows dimensions, pushs a rect onto the clipping stack, sets the scissor rect to what is on the top of the clipping stack, and calls the windows paint method. The windows paint method calls the windows on_paint method which actually draw the window. The paint method then loops through all the child windows of that window, getting their dimensions, pushing a clip rect etc etc.
0

Share this post


Link to post
Share on other sites
Thank you all for your help, and it is nearly correct.

There appears to be a special case where it doesn't work correctly, that is when it a child node is needs to be translated with a negative value on the y axis (the blue rectangle).

Free Image Hosting at www.ImageShack.us

Here is my current code:
void GUINode::Render()
{
// Draw current GUI
glTranslated(x,y,0);

// Render the component, doing it this way ensures us that the end user won't "forget" to do certain things
this->RenderComponent();

// Retrieve viewport and scissor size
GLint* viewport = new GLint[4];
GLint* scissor = new GLint[4];
glGetIntegerv(GL_VIEWPORT, viewport);
glGetIntegerv(GL_SCISSOR_BOX, scissor);

// Calculate new scissor size (if it would be the root node)
GLint nX,nY,nW,nH;
nX = (GLint)(scalar(viewport[2])*x)+scissor[0];
nY = (GLint)(scalar(viewport[3])*y);//+scissor[1];// The +scissor[1] isn't making any diffrence?
nW = (GLint)(scalar(viewport[2])*w);
nH = (GLint)(scalar(viewport[3])*h);

GLint nYtoUse = viewport[3] - nY - nH;
//std::cout<<nYtoUse<<":"<<scissor[1]<<std::endl;
//std::cout<<nH<<":"<<scissor[3]<<std::endl;

/*std::cout<<"Requested:"<<nX<<":"<<nY<<":"<<nW<<":"<<nH<<std::endl;
std::cout<<"Got: "<<(scissor[0] > nX ? scissor[0] : nX)<<":"<<
(scissor[1] > nY ? scissor[1] : nY)<<":"<<
(scissor[2] < nW ? scissor[2] : nW)<<":"<<
(scissor[3] < nH ? scissor[3] : nH)<<std::endl;*/


// Make the scissor size always smaller
/* This means that the X and Y values can only get bigger
* And that the W and H values can only get smaller*/

glScissor((scissor[0] > nX ? scissor[0] : nX),
(scissor[1] > nYtoUse ? scissor[1] : nYtoUse),//nY),
(scissor[2] < nW ? scissor[2] : nW),
(scissor[3] < nH ? scissor[3] : nH));

// Go through the child nodes and render them into the visible space of this node
BOOST_FOREACH(boost::shared_ptr<GUINode>& node, children)
node->Render();
// Reset translation for the siblings
glTranslated(-x,-y,0);
// Reset scissor for the siblings
glScissor(scissor[0],scissor[1],
scissor[2],scissor[3]);
delete[] viewport;
delete[] scissor;
}


There are some things I find odd, such as that when I calculate nY I can leave out the +scissor[1] if I would want to, it doesn't make a diffrence, at all.

I must have overread the part of starting at the lower left corner, or it was just late when I read it.:P

@Bezben: Now I am curious, why is it better not to use new and delete to get the values? It asks for a pointer, which I give.
I do know that arrays are also pointers, I just like to know what I allocate and deallocate and when I do it.
So are there any specific reasons to use GLint scissor[4] instead of GLint* scissor = new GLint[4]?
0

Share this post


Link to post
Share on other sites
The +scissor[1] makes no difference because it is probably zero at that point.

A cursorary glance at your code suggests this:


void GUINode::Render()
{
// Draw current GUI
glTranslated(x,y,0);

// Render the component, doing it this way ensures us that the end user won't "forget" to do certain things
this->RenderComponent();

// Retrieve viewport and scissor size
GLint viewport[4];
GLint scissor[4];
glGetIntegerv(GL_VIEWPORT, viewport);
glGetIntegerv(GL_SCISSOR_BOX, scissor);

GLint nY = viewport[3] - y - h;
//std::cout<<nYtoUse<<":"<<scissor[1]<<std::endl;
//std::cout<<nH<<":"<<scissor[3]<<std::endl;

/*std::cout<<"Requested:"<<nX<<":"<<nY<<":"<<nW<<":"<<nH<<std::endl;
std::cout<<"Got: "<<(scissor[0] > nX ? scissor[0] : nX)<<":"<<
(scissor[1] > nY ? scissor[1] : nY)<<":"<<
(scissor[2] < nW ? scissor[2] : nW)<<":"<<
(scissor[3] < nH ? scissor[3] : nH)<<std::endl;*/


// Make the scissor size always smaller
/* This means that the X and Y values can only get bigger
* And that the W and H values can only get smaller*/

glScissor((scissor[0] > x ? scissor[0] : x),
(scissor[1] > nY ? scissor[1] : nY),//nY),
(scissor[2] < w ? scissor[2] : w),
(scissor[3] < h ? scissor[3] : h));

// Go through the child nodes and render them into the visible space of this node
BOOST_FOREACH(boost::shared_ptr<GUINode>& node, children)
node->Render();
// Reset translation for the siblings
glTranslated(-x,-y,0);
// Reset scissor for the siblings
glScissor(scissor[0],scissor[1],
scissor[2],scissor[3]);
}




I wasn't really sure was the nX = (GLint)(scalar(viewport[2])*x)+scissor[0]; bits were for...


[EDIT]
Using new and delete like that will cause a performance hit as you allocate and free memory. I would imagine it'll fragment memory too. Basically, GLint scissor[4] is higher performance.
0

Share this post


Link to post
Share on other sites
Those bits are there because my coordinate system goes from [0..1] in floats, so I need to convert them to window coordinates first, that's what the scalar(viewport[3])*y is for.

scalar is a typedef for float btw, it's just there to allow me to switch to double if I would have to.


The strange thing about the +scissor[1] not making an effect is because it isn't making an effect for _every_ node.

Originally I came to the conclusion to I would have to use that to offset my clip space relative to the previous clip space since I don't store any parent information.
0

Share this post


Link to post
Share on other sites
I assume nx, ny, nw and nh are all correct values?

You made me spot a bug in my code I have to fix now :P
0

Share this post


Link to post
Share on other sites
Quote:
Original post by Bezben
I assume nx, ny, nw and nh are all correct values?

Unless there is something wrong with my logic of:
x = floating value and I multiply it with the value of viewports' width (viewport[2]) to get the screen offset of that GUI node.
Same for the others, except the vertically oriented values are mulitplied with the viewport[3].

Currently, I think it has something to do with the nH not being calculated correctly.

I'll have to do it by hand and see if this is the case.
Or I might be able to visualize the clip rectangles.

Quote:
You made me spot a bug in my code I have to fix now :P

Glad to be of help.:P


0

Share this post


Link to post
Share on other sites
The height correction looks right. I'd bet its GLint nYtoUse = viewport[3] - nY - nH; thats doing it. Maybe try GLint nYtoUse = viewport[3] - nY;
0

Share this post


Link to post
Share on other sites
What are your x and y coordinates relative to? And your widths and heights?

You know, this is going to turn out to be really obvious with hindersight, I can just tell...
0

Share this post


Link to post
Share on other sites
Quote:
Original post by Bezben
What are your x and y coordinates relative to? And your widths and heights?

The red square is 0.1:0.1 to the upper left corner of the window.
The green square is 0.1:0.1 to the upper left corner of the red square.
The blue square is -0.1:-0.1 to the upper left corner of the green square.

Widths and heights are relative to the x and y coordinates of the node.

I think I may have found something, if I disable translations, then it, sort of, renders correctly, scissor space wise.

Free Image Hosting at www.ImageShack.us

On second thought, it may even be wrong as well...

Quote:
You know, this is going to turn out to be really obvious with hindersight, I can just tell...

If there is anything as sure as 1+1=2, then your statement would be it.

0

Share this post


Link to post
Share on other sites
If thats the case then it might be the fact that you are scaling by the size of the viewport could well be the problem, you need to scale by the current scissor rect width instead.
0

Share this post


Link to post
Share on other sites
Quote:
Original post by Bezben
If thats the case then it might be the fact that you are scaling by the size of the viewport could well be the problem, you need to scale by the current scissor rect width instead.

I don't think that it would be the sollution, that would scale the UI to the scissor rect, instead of the viewport.

After a quick test, it isn't.

Strangly (to my idea anyway) it works for the green rectangle, but not the blue one. It is now too small and it now pops out on the left.


Now, please bear with me.

Before I took into account that glScissors was based from the lower left corner, the size is correct, just the position that was wrong (nY was wrong).

I don't suppose it could be something to do that nH could be wrong as well?
I don't think so, but I'm starting to think all of the possible reasons, how unlikly they might be.
0

Share this post


Link to post
Share on other sites
Right now I'd bet that is the issue. Work them out on paper. Make sure they match watch actually is there.

You definitely can't just scale by the view port if you are mapping a windows coordinates to a fixed range. I think you need to scale by the viewport for the first window, then scale by the width of that window in pixels for its children... I'd have thought that would be the previous scissor rect width though. The problem though would be when you have sibling child windows, because you'll have the previous siblings scissor rect set, not the parents. I get around this with a clipper stack. You might be able to do it with clever use of the glScissor calls...


void GUINode::Render()
{
// Render the component, doing it this way ensures us that the end user won't "forget" to do certain things
this->RenderComponent();

// Retrieve viewport and scissor size
GLint* viewport = new GLint[4];
GLint* scissor = new GLint[4];
glGetIntegerv(GL_VIEWPORT, viewport);
glGetIntegerv(GL_SCISSOR_BOX, scissor);

// Calculate new scissor size (if it would be the root node)
GLint nX,nY,nW,nH;
nX = (GLint)(scalar(viewport[2])*x)+scissor[0];
nY = (GLint)(scalar(viewport[3])*y);//+scissor[1];// The +scissor[1] isn't making any diffrence?
nW = (GLint)(scalar(viewport[2])*w);
nH = (GLint)(scalar(viewport[3])*h);

GLint nYtoUse = viewport[3] - nY - nH;
//std::cout<<nYtoUse<<":"<<scissor[1]<<std::endl;
//std::cout<<nH<<":"<<scissor[3]<<std::endl;

/*std::cout<<"Requested:"<<nX<<":"<<nY<<":"<<nW<<":"<<nH<<std::endl;
std::cout<<"Got: "<<(scissor[0] > nX ? scissor[0] : nX)<<":"<<
(scissor[1] > nY ? scissor[1] : nY)<<":"<<
(scissor[2] < nW ? scissor[2] : nW)<<":"<<
(scissor[3] < nH ? scissor[3] : nH)<<std::endl;*/


// Make the scissor size always smaller
/* This means that the X and Y values can only get bigger
* And that the W and H values can only get smaller*/

// Go through the child nodes and render them into the visible space of this node

// I don't actually know what BOOST_FOREACH does, but you'll get the idea...
BOOST_FOREACH(boost::shared_ptr<GUINode>& node, children)
{
// Draw current GUI
glTranslated(x,y,0);
glScissor((scissor[0] > nX ? scissor[0] : nX),
(scissor[1] > nYtoUse ? scissor[1] : nYtoUse),//nY),
(scissor[2] < nW ? scissor[2] : nW),
(scissor[3] < nH ? scissor[3] : nH));
node->Render();
glTranslated(-x,-y,0);
// Reset scissor for the siblings
glScissor(scissor[0],scissor[1],
scissor[2],scissor[3]);
}//end the for each here

// Reset translation for the siblings
delete[] viewport;
delete[] scissor;
}

0

Share this post


Link to post
Share on other sites
I believe the actual calculations you want are (assuming top left coordinate system, otherwise change the names appropriately):
GLint newLeft = (viewport[2] * x) + scissor[0];
GLint newTop = (viewport[3] * y) + scissor[1];
GLint newRight = left + (viewport[2] * w);
GLint newBottom = top + (viewport[3] * h);
GLint oldLeft = scissor[0];
GLint oldTop = scissor[1];
GLint oldRight = scissor[0] + scissor[2];
GLint oldBottom = scissor[1] + scissor[3];
GLint clippedLeft = std::max(newLeft, oldLeft);
GLint clippedTop = std::max(newTop, oldTop);
GLint clippedRight = std::min(newRight, oldRight);
GLint clippedLeft = std::min(newBottom, oldBottom);
glScissor(clippedLeft, clippedTop, clippedRight - clippedLeft, clippedBottom - clippedTop);

Obviously you could also achieve the end result by following your current approach, but the above is (in my opinion) much clearer (and would be even more so if new, old and clipped were encapsulated in a bounds or rectangle class). And please drop the new GLint[4]s and just use stack arrays. There's really no need to invoke dynamic memory allocation and needlessly fragment your heap and add extra exception paths to your code.

Enigma
0

Share this post


Link to post
Share on other sites
I think my current code supports siblings correctly.

It's the
glScissor(scissor[0],scissor[1], scissor[2],scissor[3]);
part at the end of the Render function that should garuantee for this.

Basicly, each node ensures that it the scissor and translations get restored at the end of it's rendering function.


I've tried to work it out several times, but I can't seem to get it right...
Must be my brains shutting down after trying to design a system for school which by it's very definition and idea on how it should work resists all logic.:P

I got this:
0x0x800x600

red:
0.1x0.1x0.5x0.5
80x60x400x300
80x60x400x300

green:
0.1x0.1x0.5x0.5
80x60x400x300
160x120x400x300

blue:
-0.15x-0.15x0.5x0.5
-120x-90x400x300
160x120x400x300

An explanation, the first line of each node is the floating point notation.
The second one are the resulting values for the offset to point 0x0 (or the parents offset point).
The third line is the result of the "stack".

Something else that I've just tried, I tried outputting the result of this part:
  // Make the scissor size always smaller
/* This means that the X and Y values can only get bigger
* And that the W and H values can only get smaller*/
glScissor((scissor[0] > nX ? scissor[0] : nX),
(scissor[1] > nYtoUse ? scissor[1] : nYtoUse),
(scissor[2] < nW ? scissor[2] : nW),
(scissor[3] < nH ? scissor[3] : nH));


The result was:
scissor1:80:240:400:300
scissor2:1:0:800:600
scissor1:160:240:400:300
scissor2:1:240:400:300
scissor1:160:240:400:300
scissor2:1:240:400:300

Which would suggest an error in my logic.


Or a flaw in my programming, since the line which outputs the scissor1 part is:
std::cout<<"scissor1:"<<(scissor[0] > nX ? scissor[0] : nX)<<":"<<
(scissor[1] > nYtoUse ? scissor[1] : nYtoUse)<<":"<<
(scissor[2] < nW ? scissor[2] : nW)<<":"<<
(scissor[3] < nH ? scissor[3] : nH)<<std::endl;
0

Share this post


Link to post
Share on other sites
Sorry for the double post, but it took me some time to type out my previous post (hence I didn't see Enigma's post).


Thanks for your help, it also explains why it would be better to use stack arrays.
I hadn't thought of the heap as of yet.

I'll edit this post ounce I get a result.


[EDIT]
Here is my current situation:
Free Image Hosting at www.ImageShack.us

I think it is an improvement, because now the problem is consistent.^_^

This is the code I'm currently using:
void GUINode::Render()
{
if(!visible)
return;
glTranslated(x,y,0);

this->RenderComponent();

GLint viewport[4];
GLint scissor[4];
glGetIntegerv(GL_VIEWPORT, viewport);
glGetIntegerv(GL_SCISSOR_BOX, scissor);

GLint newLeft = GLint(scalar(viewport[2]) * x) + scissor[0];
GLint newTop = GLint(scalar(viewport[3]) * y) + scissor[1];
GLint newRight = newLeft + GLint(scalar(viewport[2]) * w);
GLint newBottom = newTop + GLint(scalar(viewport[3]) * h);
GLint oldLeft = scissor[0];
GLint oldTop = scissor[1];
GLint oldRight = scissor[0] + scissor[2];
GLint oldBottom = scissor[1] + scissor[3];
GLint clippedLeft = std::max(newLeft, oldLeft);
GLint clippedTop = std::max(newTop, oldTop);
GLint clippedRight = std::min(newRight, oldRight);
GLint clippedBottom = std::min(newBottom, oldBottom);
glScissor(clippedLeft, clippedTop, clippedRight - clippedLeft, clippedBottom - clippedTop);

// Go through the child nodes and render them into the visible space of this node
BOOST_FOREACH(boost::shared_ptr<GUINode>& node, children)
node->Render();
// Reset translation for the siblings
glTranslated(-x,-y,0);
// Reset scissor for the siblings
glScissor(scissor[0],scissor[1],
scissor[2],scissor[3]);
}



[Edited by - mldaalder on December 15, 2005 5:22:38 PM]
0

Share this post


Link to post
Share on other sites
The problem is that your window coordinate system is top left, but OpenGL's window coordinate system is bottom left, so you have to translate between them (sorry, should have realised this earlier):
// translate from bottom left to top left coordinate system
// this is just offset from top = available height - (offset from bottom + quad height)
scissor[1] = viewport[3] - (scissor[1] + scissor[3]);

GLint newLeft = (viewport[2] * x) + scissor[0];
GLint newTop = (viewport[3] * y) + scissor[1];
GLint newRight = newLeft + (viewport[2] * w);
GLint newBottom = newTop + (viewport[3] * h);
GLint oldLeft = scissor[0];
GLint oldTop = scissor[1];
GLint oldRight = scissor[0] + scissor[2];
GLint oldBottom = scissor[1] + scissor[3];
GLint clippedLeft = std::max(newLeft, oldLeft);
GLint clippedTop = std::max(newTop, oldTop);
GLint clippedRight = std::min(newRight, oldRight);
GLint clippedBottom = std::min(newBottom, oldBottom);

// translate from top left to bottom left coordinate system
glScissor(clippedLeft, viewport[3] - clippedBottom, clippedRight - clippedLeft, clippedBottom - clippedTop);

The previous code was setting up the scissored areas mirrored vertically about your window.

Enigma
0

Share this post


Link to post
Share on other sites
Thank you, that did the trick.


I think I'll spend a couple of days figuring out why I didn't think of it...
Basic math...
0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0