透视图/变换矩阵

发布于 2024-09-07 04:20:28 字数 714 浏览 4 评论 0原文

如何在 Java 中进行透视图转换?据我了解,我可以使用一些神奇的 4 维矩阵来确定 FOV、长宽比以及近距和远距观看距离,但我不知道如何创建该矩阵。

我能够在Java中实现“PerspectiveTransform”,但是使用以下内容时我看不到任何效果

double mat[][] = {
    {1, 0, 0, 0}, 
    {0, 1, 0, 0},
    {0, 0, 1, 0},
    {0, 0, 1, 0}};
PerspectiveTransform ps = new PerspectiveTransform(mat);
ps.transform(p1, p1);
ps.transform(p2, p2);
ps.transform(p3, p3);
ps.transform(p4, p4);

我理解最底部的“1”可能需要是1/d,其中“d”是距离,但无论如何我在那里尝试了什么数字没有效果。更改其他数字确实有效果,但在我尝试之前我不知道它们会产生什么效果(而且我不能无限猜测)。我知道并且能够使“quadToQuad”函数正常工作,但我再次必须猜测要使用哪个“quads”。

所以我需要一个资源来向我解释如何根据视场、长宽比、距离等得出我需要的矩阵。我已经阅读了“交互式计算机图形学”第五版的相关部分。爱德华·天使的作品,但我不明白。

我想做的是将鸟瞰图像转换为人眼视图图像。使用 Google Earth 时可以看到这样的一个例子..

谢谢

How do I do a perspective view transformation in Java? As I understand it there is some magical 4 dimensional matrix I can use which will determine the FOV, Aspect Ratio, and Near and Far viewing distances, but I don't know how to create that matrix.

I'm able to implement a "PerspectiveTransform" in Java, but I see no effect when using the following

double mat[][] = {
    {1, 0, 0, 0}, 
    {0, 1, 0, 0},
    {0, 0, 1, 0},
    {0, 0, 1, 0}};
PerspectiveTransform ps = new PerspectiveTransform(mat);
ps.transform(p1, p1);
ps.transform(p2, p2);
ps.transform(p3, p3);
ps.transform(p4, p4);

I understand the the bottom-most "1" may need to be 1/d where "d" is the distance, but no matter what number I try there I get no effect. Changing the other numbers does have an effect, but I don't know what effect they will have until I try it (and I can't just guess infinitely). I am aware of and was able to get the "quadToQuad" function to work, but again I would have to guess at which "quads" to use.

So I need a resource to explain to me how to come up with the matrix I need based on a FOV, aspect ratio, distance, etc. I've read the pertinent portion of "Interactive Computer Graphics" 5th Ed. by Edward Angel and don't understand it.

What I'm trying to do is convert a bird's-eye-view image into a human-eye-view image. An example of this can be seen when using Google Earth..

thanks

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

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

发布评论

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

评论(1

妄想挽回 2024-09-14 04:20:28

当您执行 ps.transform(p2, p2) 时,您可能会取消以 p1 作为参数的同一指令的效果,但无论如何,该矩阵位置的典型含义如下:

替代文本
(来源:google.com

此链接也许可以为您提供一些帮助。
同样在这里,您可以在“设置投影”部分查看如何计算视野变换”

在你的情况下,我相信你的矩阵应该将最后一行设置为 0 0 0 1 而不是它的样子。
此外,可以通过同一链接中描述的表达式来计算视野:

void VerticalFieldOfView(float degrees, float aspectRatio, 
                         float near, float far)
{
   float top = near * std::tan(degrees * Pi / 360.0f);
   float bottom = -top;
   float left = bottom * aspectRatio;
   float right = top * aspectRatio;

   glFrustum(left, right, bottom, top, near, far);
}

其中“glFrustum(...)”是

void ApplyFrustum(float left, float right, float bottom, 
                  float top, float near, float far)
{
    float a = 2 * near / (right - left);
    float b = 2 * near / (top - bottom);
    float c = (right + left) / (right - left);
    float d = (top + bottom) / (top - bottom);
    float e = - (far + near) / (far - near);
    float f = -2 * far * near / (far - near);

    mat4 m;
    m.x.x = a; m.x.y = 0; m.x.z = 0; m.x.w = 0;
    m.y.x = 0; m.y.y = b; m.y.z = 0; m.y.w = 0;
    m.z.x = c; m.z.y = d; m.z.z = e; m.z.w = -1;
    m.w.x = 0; m.w.y = 0; m.w.z = f; m.w.w = 1;

    glUniformMatrix4fv(projectionUniform, 1, 0, m.Pointer());
}

该示例是 C++ 语言,但您所要做的就是将其转换为两个 Java 函数,并且最后使用相应的方法使矩阵均匀。

There is the possibility that when you do ps.transform(p2, p2) you are canceling the effect of the same instruction with the p1 as argument, but regardless that, the typical meaning of the positions of that matrix are as follows:

alt text
(source: google.com)

This link might be able to give you a little hand with this.
Also in here, you can check how to calculate the field of view, on section "Setting the Projection Tranform"

In your case, I believe your matrix should have the last line set as 0 0 0 1 instead of how it is like.
Also, the field of view can be calculated through the expression described in that same link:

void VerticalFieldOfView(float degrees, float aspectRatio, 
                         float near, float far)
{
   float top = near * std::tan(degrees * Pi / 360.0f);
   float bottom = -top;
   float left = bottom * aspectRatio;
   float right = top * aspectRatio;

   glFrustum(left, right, bottom, top, near, far);
}

Where the "glFrustum(...)" is

void ApplyFrustum(float left, float right, float bottom, 
                  float top, float near, float far)
{
    float a = 2 * near / (right - left);
    float b = 2 * near / (top - bottom);
    float c = (right + left) / (right - left);
    float d = (top + bottom) / (top - bottom);
    float e = - (far + near) / (far - near);
    float f = -2 * far * near / (far - near);

    mat4 m;
    m.x.x = a; m.x.y = 0; m.x.z = 0; m.x.w = 0;
    m.y.x = 0; m.y.y = b; m.y.z = 0; m.y.w = 0;
    m.z.x = c; m.z.y = d; m.z.z = e; m.z.w = -1;
    m.w.x = 0; m.w.y = 0; m.w.z = f; m.w.w = 1;

    glUniformMatrix4fv(projectionUniform, 1, 0, m.Pointer());
}

The example is in C++ but all you have to do is translate it into two Java functions, and also use the correspondant methods for making your matrix uniform at the end.

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