首页 > 其他分享 >进入三维

进入三维

时间:2024-02-03 23:27:20浏览次数:35  
标签:temp 矩阵 0.5 三维 0.7 0f 进入 1f

一.前言

  想象一下,你在游戏厅和朋友玩空气曲棍球游戏,从你的视角看,空气曲棍球桌是什么样的?你的那一端桌子会显得较大,因为你是从一个角度向下看桌子的,而不是俯视桌子,我们在上一篇文章中所写的程序就是俯视视角下的,在这片文章中,我们将走进三维,让绘制的桌子更符合实际的视角。

二.透视除法

  在一个顶点坐标成为归一化设备坐标之前,其实还进行了一个额外的步骤,它被称为透视除法。还记得我们在之前的文章中提过一下顶点坐标的w分量吧,它就是用于作透视除法用的。为了在屏幕上创建三维的幻象,OpenGL会把每个gl_Position的x,y,z分量除以w分量,当w分量表示距离的时候,就使得较远处的物体被移动到离渲染区域中心更近的地方,这个中心的作用就相当于一个消失点。

  举个例子,有两个坐标(1,1,1,1),(1,1,1,2),在OpenGL将他们转化为归一化坐标之前,会先进行透视除法,每个分量都除以w分量,这两个坐标整除后变为(1/1,1/1,1/1)和(1/2,1/2,1/2),这个除法之后,归一化设备坐标就是(1,1,1)和(0.5,0.5,0.5)。有较大的w值的坐标被移动到离(0,0,0)更近的位置,(0,0,0)就是归一化设备坐标里渲染区域的中心。

三.添加w分量创建三维图

  如果我们实际添加一下w分量,可以更直观的发现它所产生的影响。因为我们现在要指定一个位置的x,y,z和w分量,所以我们先要更新一下代码中的POSITION_COMPONENT_COUNT变量,将值改为4。下一步,我们需要更新顶点数组,修改后的值如下:

val tableVertices=floatArrayOf(
            //Triangle fan
            0f,0f,0f,1.5f,1f,1f,1f,
            -0.5f,-0.8f,0f,1f,0.7f,0.7f,0.7f,
            0.5f,-0.8f,0f,1f,0.7f,0.7f,0.7f,
            0.5f,0.8f,0f,2f,0.7f,0.7f,0.7f,
            -0.5f,0.8f,0f,2f,0.7f,0.7f,0.7f,
            -0.5f,-0.8f,0f,1f,0.7f,0.7f,0.7f,
            //Mid Line
            -0.5f,0f,0f,1.5f,1f,0f,0f,
            0.5f,0f,0f,1.5f,1f,0f,0f,
            //Mallets
            0f,-0.4f,0f,1.25f,0f,0f,1f,
            0f,0.4f,0f,1.75f,1f,0f,0f
        )

  我们给每个顶点都加入了w分量,靠近屏幕底部的w的值为1,而靠近屏幕顶部的w的值为2,其他的顶点的w的值也从底部到顶部逐渐增加。而对于z值,我们全部设为零即可,产生的效果应该是桌子的底部看起来更宽些,桌子的顶部看起来更窄些,就像我们从远处观看一样。可以运行程序看看效果,是否和我们所预想的那样。

四.使用透视投影

  我们加入w分量后,桌子看上去更像三维了。然而,如果我们希望这些物体更加动态,比如改变桌子的角度,放大或缩小,该怎么办呢?那么我们就不能指定w的值,我们要用矩阵来生成这些值。把我们刚刚做的改动都去掉,接下来我们将用矩阵来生成同样的效果。

  现在我们可以将onSurfaceChanged函数中glViewport()后的代码全部删除,然后使用Matrix类当中的perspectiveM()函数生成一个透视投影矩阵,这个函数的定义如下:

public static void perspectiveM(
float[] m,//存储透视投影矩阵
int offset,//数组开始存储投影矩阵的偏移值
float fovy, //视场垂直角度
float aspect, //宽高比
float zNear,//近裁剪面距离
float zFar//远裁剪面距离
)

  我们需要加入的代码如下:Matrix.perspectiveM(projectionMatrix,0,45f,width.toFloat()/height.toFloat(),1f,10f)

  此时运行程序时,我们什么也看不到,因为我们没有指定z值,那么z值就默认为0,而我们刚刚通过perspectiveM函数将z值的范围指定为了[-10,-1],所以什么也看不到。此时,我们可以利用模型矩阵将桌子移动到这个范围内,首先我们得在MyRenderer内中定义一个变量用于存储模型矩阵:private val modelMatrix:FloatArray=FloatArray(16)//存储模型矩阵

  然后,加入如下代码:

//生成模型矩阵
        Matrix.setIdentityM(modelMatrix,0)//设置为单位矩阵
        Matrix.translateM(modelMatrix,0,0f,0f,-2f)//将z值平移到可见范围内
        val temp:FloatArray=FloatArray(16)//存储矩阵相乘的结果
        Matrix.multiplyMM(temp,0,projectionMatrix,0,modelMatrix,0)
        System.arraycopy(temp,0,projectionMatrix,0,temp.size)//将temp复制到projectionMatrix

  现在,我们运行这个应用程序,可以看到桌子了,但是是以俯视的视角看的,我们需要旋转一下桌子,从而以正常的视角看向桌子,并且因为旋转之后,桌子的底部会离我们更近,我们可以让桌子离我们稍微远一些,这样的效果更好,修改之后的代码如下:

//生成模型矩阵
        Matrix.setIdentityM(modelMatrix,0)//设置为单位矩阵
        Matrix.translateM(modelMatrix,0,0f,0f,-3.5f)//将z值偏移-3.5
        Matrix.rotateM(modelMatrix,0,-60f,1f,0f,0f)//绕x轴旋转-60度
        val temp:FloatArray=FloatArray(16)//存储矩阵相乘的结果
        Matrix.multiplyMM(temp,0,projectionMatrix,0,modelMatrix,0)
        System.arraycopy(temp,0,projectionMatrix,0,temp.size)//将temp复制到projectionMatrix

  现在,运行程序,就可以看到三维场景下的空气曲棍球桌子了。

 

标签:temp,矩阵,0.5,三维,0.7,0f,进入,1f
From: https://www.cnblogs.com/luqman/p/18005229

相关文章

  • hdu1240 Asteroids! (三维BFS)
    Problem-1240(hdu.edu.cn)三维的BFS,存在一个坐标点的变换,即输入的是(y,z,x),进行转换即可#include<iostream>#include<queue>#include<cstring>usingnamespacestd;intn,x1,y1,z1,x2,y2,z2,flag,vis[20][20][20];charroom[20][20][20];structnode{int......
  • Microsoft 365 无法进入网页版outlook--循环重定向问题
    最近有个Microsoft365客户遇到管理员账户无法进入网页版outlook的问题,在登录Microsoft365网页版outlook时,输入完用户名和密码之后,网页不断的重复跳转,无法进入到网页版邮箱。多次跳转之后报错如下图经检查发现导致该问题的原因是该账户被分配了过多的角色。如果为用户分配了过多的......
  • 三维动态规划
    三维动态规划474.一和零多维费用背包intzeros;intones;intlen;voidcount(char*s){zeros=0;ones=0;intl=strlen(s);for(inti=0;i<l;++i){if(s[i]=='0')zeros++;if(s[i]=='1')ones++;......
  • 02 三维世界与模型
    了解三维世界物体的位置是使用某个坐标轴下的坐标(x,y,z)进行描述。 坐标系分为两种:左手坐标系、右手坐标系。z轴坐标系是这两种坐标系的区别点。OpenGL使用的是右手坐标系。OpenGL做了什么?先确定坐标系(原点、x,y,z得指向),再确定摄像机(观察者)的位置和方向。这样就能渲染出图......
  • [word] word打印窗口也可以进行页面设置,无需重新进入Word中设置
    在打印Word文档的过程中,我们一般要预览一下。在预览的过程中,如果发现了问题,一般要重新回到word文档中修改。实际上不需要,在打印窗口中可以直接修改。1.点击【文件】2.点击【打印】......
  • Python下的三维建模和可视化
    本文介绍基于AnyCADRapidPy三维图形平台开发Python的三维应用1准备工作1.1安装vc_resit2022在Windows下,AnyCADRapidSDK依赖VistualC++运行时库,64位版本需要在客户机上安装vc_redist.x64.exe微软官方下载地址:x64:vc_redist.x64.exe1.2安装Python3.12:::w......
  • 制作Windows系统的OOBE 开机自动进入OOBE界面 避免网内计算机名一样而冲突
    这里,有时将会发生一些问题,就是制作好的Ghost镜像往往是带计算机名等信息的,因为安装过程中,已经输入了一次计算机名。而当测试是在一个局域网内多台同型号计算机,使用同一个系统镜像时,则会发生网内计算机名一样导致冲突。此时,我们就应该制作一个在恢复系统后自动进入OOBE界面重新输......
  • 【如何更新自定义IP】自定义IP 的.V文件修改以后,一定要先进入platform Designer更新IP
    最近自定义了一个IP,添加到qsys以后,generateHDL....。再后来再有改动IP的.v文件时,我直接点generateHDL...发现电路最终没有更新。 需要如下操作:先进入platformDesigner更新IP,右击选择IP选择Edit: 点击分析和综合IP文件:  以后再generateQsy文件: 这样工程的......
  • WebGL之三维正射投影(高级)
    一,前言1,绘制一个正方体的数据,我们以前,上,右逆时针绘制,对面的用顺时针绘制。  2,数据准备cubeModel.js/***获得正方体所有顶点位置*@paramsideLength边长*/window.getCubeVertexesPosition=(sideLength)=>{//前constFRONT=[0.0,0.0,0.0......
  • 微信小程序进入场景枚举类
    微信开放文档-场景值列表///<summary>///小程序打开的具体场景值,1058-公众号文章等///</summary>publicenumEnterScene{///<summary>///其他///</summary>[Display(Name="其他")]Other=1000,///<summary>//......