问题描述
我有一组点,每一个都有一个影响力或基本上是一个半径的区域。我希望能够将所有点的这些影响圈中的每一个画成简单的圆形线。
它们会重叠,但我希望画出形成的外形。我知道这可能需要我确定它们相交的地方,并以某种方式形成一个完整的形状来绘制。问题是有些点甚至可能不会触及别人!所以我需要能够解决这个问题。
我试图说明我的意思:
请注意,我希望简单地画黑线,不填。这是因为我希望背景图像和其他几何图形能够透过。
我会在openGL中这样做,所以圆形可能会使用GL_LINES或其他类似的顶点形成的曲线,但我真的不知道我会如何解决这个问题。
如果有人有任何建议,或者可以指示我如何去解决这个问题,那将不胜感激!
这可能更像是一个数学问题,我不是在寻找一些代码,而是实际上如何去设计出这些形状。我只是想不出如何去做!
*****编辑:用我提出的解决方案,希望可以帮助别人!
所以我使用了建议的想法,基本上决定了最好的方法是使用模板缓冲区。这现在意味着我循环了3次我的观点,但我需要对它们进行一些仔细的分类,以便只找到可见的分类。
所以代码明智我现在有这个:
pre $私有无效stencilCircleAroundStars ()
{
//让我们试着在这里使用模板
glColorMask(false,false,false,false); //禁用颜色遮罩
glEnable(GL_STENCIL_TEST); //启用模板缓冲区对于标记外部圆圈
glDisable(GL_DEPTH_TEST); //禁用深度测试
for(Object value:stars.values())
{
Star star =(Star)值;
glStencilFunc(GL_ALWAYS,1,1); //总是通过,1位平面,1作为掩码
glStencilOp(GL_KEEP,GL_KEEP,GL_REPLACE); //我们将模板缓冲区设置为1我们绘制任意多边形的位置
//绘制大圆圈
starOb.location.copy(star.location);
starOb.setScale(2000);
starOb.draw();
(对象值:stars.values())
{
星型星号=(Star)值;
//现在我们改变函数并从缓冲区移除一个稍小的圆。
glStencilFunc(GL_ALWAYS,0,0); //总是通过0位平面,0作为掩码;
glStencilOp(GL_KEEP,GL_KEEP,GL_REPLACE); //我们将模板缓冲区设置为0我们绘制任何多边形的位置
starOb.location.copy(star.location);
starOb.setScale(1900);
starOb.draw();
}
//现在我们启用颜色
glColorMask(true,true,true,true);
glStencilFunc(GL_EQUAL,1,1); //我们只绘制模板为1
glStencilOp(GL_KEEP,GL_KEEP,GL_KEEP); //不要更改模板缓冲区
glColor4f(0.5f,1.0f,0.5f,0.5f);
for(Object value:stars.values())
{
Star star =(Star)value;
starOb.location.copy(star.location);
starOb.setScale(2000);
starOb.draw();
}
//现在我们完成了..禁用
glDisable(GL_STENCIL_TEST);
}
我的观点在本质上就是我称之为星星的实体StarOb是我从一个文件中加载的四边形的集合,形成一个很好的平滑圆。
我禁用颜色遮罩,然后循环一次,将最大的圆圈插入模板缓冲区并将值设为1.然后再循环绘制较小缩放到模板缓冲区的圆圈,但是这次设置的值为0.这应该在任何未接触其他星星的星形周围留下边界,并且将有效地移除它们重叠的地方。
我终于重新启用了颜色遮罩,并实际绘制了彩色圆圈。模板缓冲区停止渲染内部,我得到我想要的!然后我禁用了模板缓冲区。
如果你真的想看到它,下面是一个生成几个不断增加的点的视频:
这是一个低质量的它出来了(背景没有绘制,而测试):
首先,想象背景不在那里。我很肯定你会知道该怎么做,绘制每个圆圈然后画出它们的内侧(如实心圆圈),以去除里面的圆弧。
现在要对图像做同样的事情,你可以做这些事情。你可以做的一件事是禁止在颜色缓冲区上写入,执行该过程并更改模板缓冲区。然后在颜色缓冲区中启用写入,然后绘制一个完整的屏幕矩形,从而填充您在模板缓冲区中标记的像素。
模板缓冲区可能对您不可用但是有几个原因,比如你正在使用它来做其他事情。在这种情况下,替代方法是做同样的事情,但不是在模具缓冲区中渲染,而是渲染纹理。然后绑定该纹理,并在屏幕上绘制一个矩形。
我很确定您可以使用累积缓冲区来实现这一点,但我从未使用过,所以我真的不知道(如果有人知道这一点,请编辑我的答案,告诉我们如何)
I have a set of points and each one has an area of "influence" or essentially a radius. I would like to be able to draw each one of these influence circles for all the points as a simple circular line.
They will overlap however I wish to draw the outside of the shape formed. I know this would probably require me working out where they intersect and somehow forming a total shape to draw. The problem is that some points might not even touch others! So I need to be able to work that out too.
I have attempted to illustrate what I mean simply:
Note that I wish to draw simply the black line, no fill. This is because I wish background images and other geometry to show through.
I would be doing this in openGL so the circle would be probably made using GL_LINES or some such with various vertices forming the curves but I really just don't have any idea about how I would work out this perimeter.
If anyone has any advice or could point me at how I might go about working this out it would be greatly appreciated!
This might be more of a maths question, I am not looking for bits of code but actually how to go about working out these shapes. I just can't think about how to do it!
*****Edit: with the solution I came up with, hopefully might help someone else!
So I used the suggested ideas and basically decided the best way would be to draw using the stencil buffer. This now means that I loop through my points 3 times but I need to do some careful sorting of them to find only visible ones anyway.
So code wise I now have this:
private void stencilCircleAroundStars()
{
//Lets try and draw something here using stencil
glColorMask(false, false, false, false); //Disable colour mask
glEnable(GL_STENCIL_TEST); // Enable Stencil Buffer For "marking" the outer circle
glDisable(GL_DEPTH_TEST);// Disable Depth Testing
for (Object value : stars.values())
{
Star star = (Star)value;
glStencilFunc(GL_ALWAYS, 1, 1); // Always Passes, 1 Bit Plane, 1 As Mask
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); // We Set The Stencil Buffer To 1 Where We Draw Any Polygon
//Draw the large circle
starOb.location.copy(star.location);
starOb.setScale(2000);
starOb.draw();
}
for (Object value : stars.values())
{
Star star = (Star)value;
//Now we change the functions and remove a slightly smaller circle from buffer.
glStencilFunc(GL_ALWAYS, 0, 0); // Always passes, 0 bit plane, 0 as mask;
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); // We Set The Stencil Buffer To 0 Where We Draw Any Polygon
starOb.location.copy(star.location);
starOb.setScale(1900);
starOb.draw();
}
//Now we enable the colour
glColorMask(true, true, true, true);
glStencilFunc(GL_EQUAL, 1, 1); // We Draw Only Where The Stencil Is 1
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // Don't Change The Stencil Buffer
glColor4f(0.5f, 1.0f, 0.5f, 0.5f);
for (Object value : stars.values())
{
Star star = (Star)value;
starOb.location.copy(star.location);
starOb.setScale(2000);
starOb.draw();
}
//Now we are done .. disable
glDisable(GL_STENCIL_TEST);
}
My points are in essence entities called "stars" for the purpose of my program and StarOb is a collection of quads I have loaded from a file which form a nice smooth circle.
I disable colour mask and I loop through once, drawing the largest circle I can into the stencil buffer and setting a value of 1. I then loop around again drawing the smaller scaled circle into the stencil buffer but this time setting a value of 0. This should leave a border around any star that is not touching other stars and will effectively remove where they overlap.
I finally re-enable the colour mask and actually draw the coloured circles. the stencil buffer stops the insides from being rendered and I get what I wanted! I then disable the stencil buffer.
If you really wanted to see it, here's a video of generating several increasing amounts of points: Video of it running
Here is a low quality version of how it came out (background was not drawn while testing):
First, imagine the background was not there. I'm pretty sure you'd know how to do it, draw each circle then draw their insides (as in a filled circle) to remove the arcs that are inside.
Now to do the same over an image, you could do either of these things. One thing you can do is to disable writing on the color buffer, do that procedure and change the stencil buffer. Then enable writing on the color buffer and draw a whole screen rectangle which consequently fills the pixels you have marked in the stencil buffer.
The stencil buffer may not be usable to you however for a couple of reasons, such as you are using it for something else. In this case, an alternative would be to do the same thing, but instead of rendering in the stencil buffer, you render in a texture. Then bind that texture and draw a rectangle on the screen.
I'm quite certain you could achieve this with the accumulation buffer too, but I have never used it so I can't really tell (if anyone knows about that, please edit my answer and tell us how)
这篇关于相交圆的绘制轮廓的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!