在 openGL 中放大/缩小和绘画

发布于 2024-10-01 08:36:51 字数 1171 浏览 0 评论 0原文

最近,我在绘画应用程序中实现缩放功能时遇到了一些问题。请允许我首先向您提供一些背景信息。

首先,我首先修改 Apple 的 glPaint 演示应用程序。我认为这是一个很好的来源,因为它向您展示了如何设置 EAGLView 等...

现在,我下一步想做的是实现缩放功能。经过一些研究后,我尝试了两种不同的方法。

1) 使用 glOrthof

2) 更改 EAGLView 的帧大小。

虽然这两种方法都允许我完美地放大/缩小,但当我实际在放大时进行绘画时,我会遇到不同的问题。

当我使用(1)时,我必须像这样渲染视图:

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrthof(left, right, bottom, top, -1.0f, 1.0f); //those values have been previously calculated
glDisable(GL_BLEND);
//I'm using Apple's Texture2D class here to render an image
[_textures[kTexture_MyImage] drawInRect:[self bounds]];
glEnable(GL_BLEND);
[self swapBuffers];

现在,让我们假设我放大了一点点,然后我画画,之后,我想再次缩小。为了使其正常工作,我需要确保“kTexture_MyImage”始终包含最新更改。为此,我需要在更改后捕获屏幕内容并将其与原始图像合并。这里的问题是,当我放大时,我的屏幕只显示图像的一部分(放大),而且我还没有找到正确的方法来处理这个问题。

我试图计算屏幕的哪一部分被放大,然后进行捕获。之后,我将该部分的大小调整为原始大小,并使用另一种方法将其粘贴到原始图像的正确位置。

现在,我可以更详细地说明我是如何实现这一目标的,但这确实很复杂,我想,必须有一种更简单的方法。已经有几个应用程序完美地实现了我想要实现的目标,所以它一定是可能的。

就方法 (2) 而言,我可以避免上述大部分内容,因为我只更改 EAGLView 窗口的大小。然而,在绘画时,笔画却偏离了预期的位置。我可能需要在绘画时考虑缩放级别并以不同的方式重新计算 CGPoints。

但是,如果您过去做过类似的事情或者可以给我一个提示,我如何在我的绘画应用程序中实现缩放,我将非常感激。

提前致谢。

I've recently had some issues implementing a zooming feature into a painting application. Please let me start off by giving you some background information.

First, I started off by modifying Apple's glPaint demo app. I think it's a great source, since it shows you how to set up the EAGLView, etc...

Now, what I wanted to do next, was to implement zooming functionality. After doing some research, I tried two different approaches.

1) use glOrthof

2) change the frame size of my EAGLView.

While both ways allow me to perfectly zoom in / out, I experience different problems, when it actually comes to painting while zoomed in.

When I use (1), I have to render the view like this:

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrthof(left, right, bottom, top, -1.0f, 1.0f); //those values have been previously calculated
glDisable(GL_BLEND);
//I'm using Apple's Texture2D class here to render an image
[_textures[kTexture_MyImage] drawInRect:[self bounds]];
glEnable(GL_BLEND);
[self swapBuffers];

Now, let's assume I zoom in a little, THEN I paint and after that, I want to zoom out again. In order to get this to work, I need to make sure that "kTexture_MyImage" always contains the latest changes. In order to do that, I need to capture the screen contents after changes have been made and merge them with the original image. The problem here is, that when I zoom in, my screen only shows part of the image (enlarged) and I haven't found a proper way to deal with this yet.

I tried to calculate which part of the screen was enlarged, then do the capturing. After that I'd resize this part to its original size and use yet another method to paste it into the original image at the correct position.

Now, I could go more into detail on how I achieved this, but it's really complicated and I figured, there has to be an easier way. There are already several apps out there, that perfectly do, what I'm trying to achieve, so it must be possible.

As far as approach (2) goes, I can avoid most of the above, since I only change the size of my EAGLView window. However, when painting, the strokes are way off their expected position. I probably need take the zoom level into account when painting and re-calculate the CGPoints in a different way.

However, if you have done similar things in the past or can give me a hint, how I could implement zooming into my painting app, I'd really appreciate it.

Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

Spring初心 2024-10-08 08:36:51

是的,这绝对是可能的。

当涉及到绘画程序时,您应该保留要绘制的对象的链接列表或树,以便于插入/删除。当用户停止绘画(即touchesEnded)时,您将对象添加到包含场景的数据结构中。

当用户缩放时,您需要根据当前视口、投影和模型视图变换来调整正在绘制的对象的坐标。在您的情况下,您不会更改视口或模型视图变换,因此您只需要考虑投影变换。您还可以使用模型视图矩阵上的平移和缩放来实现缩放,但为了简单起见,我将忽略这种情况,因为它涉及反转变换。

好消息是,您正在使用正交投影,因此当没有缩放生效时,世界坐标对应于窗口坐标。您的情况中的“世界”是一个简单的画布,可能对应于窗口坐标中的设备大小。

在将对象添加到场景数据结构之前,使用当前投影变换(即 glOrthof() 调用的参数)将所有坐标转换为世界坐标(即全画布坐标)。只有将模型中的所有内容保持在同一坐标空间中,您才能保持理智。

要转换坐标,假设您永远无法在 glOrtho() 调用中缩小到超过完整设备尺寸,则必须将它们按比例缩小到缩放正交尺寸与未缩放正交尺寸的比率,然后按差值对它们进行偏置缩放后的正交底部值、左值与原始未缩放的正交值之间的值。

Yes, it is definitely possible.

When it comes to paint programs, you should be keeping a linked list or tree of objects to draw for easy insertion / removal. When the user stops painting, (i.e. touchesEnded), you add objects to the data structure containing your scene.

When your user zooms you need to modulate the coordinates of the objects you are drawing with respect to the current viewport, projection, and modelview transforms. In your case, you're not changing the viewport or the modelview transforms so you need only account for the projection transform. You could also implement your zoom using a translation and scale on the modelview matrix but I'll ignore that case for simplicity because it involves inverting the transforms.

The good news is that you are using an orthographic projection so world coordinates correspond to window coordinates when no zooming is in effect. The "world" in your case is a simple canvas that probably corresponds to the size of the device in window coordinates.

Before you add an object to your scene data structure, convert all of the coordinates, using the current projection transform (i.e. the parameters to the glOrthof() call) to world coordinates (i.e. full canvas coordinates). You'll only remain sane if you keep all things in your model in the same coordinate space.

To convert the coordinates, assuming you can never zoom out past full device dimensions in your glOrtho() call, you'll have to scale them down proportional to the ratios of your zoomed ortho dimensions to your unzoomed ortho dimensions then bias them by the difference between your zoomed ortho bottom, left values and those of the original unzoomed ortho values.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文