OpenGL蓝宝书第五章代码勘误以及惯性坐标系去解释模型变换:Pyramid.cpp
假设你也发现依照教程代码完毕贴图时,你会底面的坐标和寻常顶点坐标正负相反,比方-1.0f, -1.0f, -1.0f这个顶点相应的却是世界坐标中1.0f,-1.0f,1.0f
问题到底出如今哪里?
原来是:objectFrame.GetCameraMatrix(mObjectFrame); //原书中的代码为GetMatrix。获取了objectFrame的朝向。导致顶点和纹理的对象关系出现了相反内容
objectFrame中的朝向和OpenGL的默认朝向相反,getMatrix的操作会导致modelViewMatrix在无形中运行了一次180°旋转。鉴于此,我们应该仅仅须要获得其camera矩阵就可以。这个camera矩阵记录了当前模型的旋转、缩放和位移。
modelViewMatrix乘上这个矩阵的结果就是世界原点到模型各顶点的作用矩阵。
这里引出一个我差点忘记的概念:惯性坐标。
世界坐标系的原点通过变换矩阵,可定位了模型的位移、旋转(包括朝向和定义惯性正方向)、缩放状态(这个事实上对世界顶点变换影响不大。仅仅是模型对于自身的惯性相对点影响比較大)。
实际渲染绘制流程是:世界原点,移动画刷(这个概念非常重要),旋转画刷,依据缩放绘制模型各顶点。模型各顶点的位置是相对于画刷的。画刷事实上在很多其它情况下命名为模型的惯性坐标系。从世界坐标系到画刷(模型惯性坐标系)则是模型变换矩阵。模型顶点的绘制则由模型编辑器或绘制算法定义。
摄像机则影响了终于可视区域。
(有些情况下取用了相机的变换矩阵,模型惯性坐标系的原点是摄像机的当前所在位置)。
假设代码中使用了
//modelViewMatrix.Translate(0.0f, -1.0f, -7.0f);
这样类似的操作。而不是从camera中获取相对位移矩阵。那么这个模型的惯性坐标系的原点和世界坐标空间的原点,只是是运行了移动是以于自身的为原点。关注点之中的一个:惯性坐标系(画刷)的默认朝向正方向是和OpenGL的世界坐标系一样使用的是右手坐标系。
所以,-7也是向屏幕里面移动。
由此,纹理贴图的st相应关系围绕就清楚的和2D像素点操作明显差别开来。
OpenGL的st从左下角为原点,而内存中的像素操作是从左上角为原点。
此外还遇到一个问题,使用了release的模式库,导致无法正常调试。比方代码优化导致无法断点和查看到正确的数据。仅仅能切换回debug模式。
M3DMatrix44f mCamera;
cameraFrame.GetCameraMatrix(mCamera);
modelViewMatrix.MultMatrix(mCamera);//仅仅是获取cameraFrame中记录的位移。没有获得朝向和旋转
#include <GLTools.h>
#include <GLMatrixStack.h>
#include <GLGeometryTransform.h>
#include <GLFrustum.h>
#include <GLFrame.h>
#include <GLShaderManager.h>
#include <iostream> #include <math.h> #ifdef __APPLE__
#include <glut/glut.h>
#else
#define FREEGLUT_STATIC
#include <GL/glut.h>
#endif GLMatrixStack mvpMatrix;
GLMatrixStack projectionMatrix;
GLMatrixStack modelViewMatrix; GLFrustum viewFrustum;
GLGeometryTransform transformPipeLine; GLFrame cameraFrame;
GLFrame objectFrame; GLBatch pyramidBatch;
GLuint textureID;
GLShaderManager shaderManager; void ChangeSize(int w, int h)
{
if (h <= 0)
{
h = 1;
} glViewport(0, 0, w, h);
viewFrustum.SetPerspective(35, float(w) / float(h), 1.0f, 1000.0f);
projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
transformPipeLine.SetMatrixStacks(modelViewMatrix, projectionMatrix);
} // Load a TGA as a 2D Texture. Completely initialize the state
bool LoadTGATexture(const char *szFileName, GLenum minFilter, GLenum magFilter, GLenum wrapMode)
{
GLbyte *pBits;
int nWidth, nHeight, nComponents;
GLenum eFormat; // Read the texture bits
pBits = gltReadTGABits(szFileName, &nWidth, &nHeight, &nComponents, &eFormat);
if (pBits == NULL)
return false; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapMode);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapMode); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter); glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, nComponents, nWidth, nHeight, 0,
eFormat, GL_UNSIGNED_BYTE, pBits); free(pBits); if (minFilter == GL_LINEAR_MIPMAP_LINEAR ||
minFilter == GL_LINEAR_MIPMAP_NEAREST ||
minFilter == GL_NEAREST_MIPMAP_LINEAR ||
minFilter == GL_NEAREST_MIPMAP_NEAREST)
glGenerateMipmap(GL_TEXTURE_2D); return true;
} void MakePyramid(GLBatch & pyramidBatch)
{
//每三个点画一个三角形
pyramidBatch.Begin(GL_TRIANGLES, 18, 1); //原点在金字塔的几何中心(总之就是非重点。比中心高的的位置。高度的1/2) //底部,初始法线是向下,纹理映射的顶点须要查看原始纹理对比一下?? //todo
//逆着法线看的话。以下三个点的围绕是逆时针的
pyramidBatch.Normal3f(0.0f, -1.0f, 0.0f);
pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
pyramidBatch.Vertex3f(-1.0f, -1.0f, -1.0f); pyramidBatch.Normal3f(0.0f, -1.0f, 0.0f);
pyramidBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
pyramidBatch.Vertex3f(1.0f, -1.0f, -1.0f); pyramidBatch.Normal3f(0.0f, -1.0f, 0.0f);
pyramidBatch.MultiTexCoord2f(0, 1.0f, 1.0f);
pyramidBatch.Vertex3f(1.0f, -1.0f, 1.0f); //逆着法线看的话,以下三个点的围绕是逆时针的
pyramidBatch.Normal3f(0.0f, -1.0f, 0.0f);
pyramidBatch.MultiTexCoord2f(0, 0.0f, 1.0f);
pyramidBatch.Vertex3f(-1.0f, -1.0f, 1.0f); pyramidBatch.Normal3f(0.0f, -1.0f, 0.0f);
pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
pyramidBatch.Vertex3f(-1.0f, -1.0f, -1.0f); pyramidBatch.Normal3f(0.0f, -1.0f, 0.0f);
pyramidBatch.MultiTexCoord2f(0, 1.0f, 1.0f);
pyramidBatch.Vertex3f(1.0f, -1.0f, 1.0f); //原先作者代码中的front和back的方向不是相对于观察者所得到的视野
//“前”这个面居然是金字塔的背对着我们的面,即第一视角看不到这个面
//感觉这坐标居然是 M3DVector3f vApex = { 0.0f, 1.0f, 0.0f };
M3DVector3f vFrontLeft = { -1.0f, -1.0f, 1.0f };
M3DVector3f vFrontRight = { 1.0f, -1.0f, 1.0f };
M3DVector3f vBackLeft = { -1.0f, -1.0f, -1.0f };
M3DVector3f vBackRight = { 1.0f, -1.0f, -1.0f }; M3DVector3f n; //求法线,前
m3dFindNormal(n, vApex, vFrontLeft, vFrontRight);
pyramidBatch.Normal3fv(n);
pyramidBatch.MultiTexCoord2f(0, 0.5f, 1.0f);
pyramidBatch.Vertex3fv(vApex); pyramidBatch.Normal3fv(n);
pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
pyramidBatch.Vertex3fv(vFrontLeft); pyramidBatch.Normal3fv(n);
pyramidBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
pyramidBatch.Vertex3fv(vFrontRight); ////求法线。左
//m3dFindNormal(n, vApex, vBackLeft, vFrontLeft);
//pyramidBatch.Normal3fv(n);
//pyramidBatch.MultiTexCoord2f(0, 0.5f, 1.0f);
//pyramidBatch.Vertex3fv(vApex); //pyramidBatch.Normal3fv(n);
//pyramidBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
//pyramidBatch.Vertex3fv(vBackLeft); //pyramidBatch.Normal3fv(n);
//pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
//pyramidBatch.Vertex3fv(vFrontLeft); ////求法线,右
//m3dFindNormal(n, vApex, vFrontRight, vBackRight);
//pyramidBatch.Normal3fv(n);
//pyramidBatch.MultiTexCoord2f(0, 0.5f, 1.0f);
//pyramidBatch.Vertex3fv(vApex); //pyramidBatch.Normal3fv(n);
//pyramidBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
//pyramidBatch.Vertex3fv(vFrontRight); //pyramidBatch.Normal3fv(n);
//pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
//pyramidBatch.Vertex3fv(vBackRight); ////求法线。后
//m3dFindNormal(n, vApex, vBackRight, vBackLeft);
//pyramidBatch.Normal3fv(n);
//pyramidBatch.MultiTexCoord2f(0, 0.5f, 1.0f);
//pyramidBatch.Vertex3fv(vApex); //pyramidBatch.Normal3fv(n);
//pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
//pyramidBatch.Vertex3fv(vBackRight); //pyramidBatch.Normal3fv(n);
//pyramidBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
//pyramidBatch.Vertex3fv(vBackLeft); pyramidBatch.End();
} void SetupRC(void)
{
glClearColor(0.7f, 0.7f, 0.7f, 1.0f); shaderManager.InitializeStockShaders(); glEnable(GL_DEPTH_TEST); glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
LoadTGATexture("stone.tga", GL_LINEAR, GL_LINEAR, GL_CLAMP_TO_EDGE);
MakePyramid(pyramidBatch); cameraFrame.MoveForward(-7.0f);//??什么用意??
} void RenderScene(void)
{
static GLfloat vLightPos[] = { 1.0f, 1.0f, 0.f };
static GLfloat vWhite[] = { 1.0f, 1.0f, 1.0f, 1.0f }; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); modelViewMatrix.PushMatrix();
//{
//处理画笔位置相关,即模型相对于摄像机的位置 M3DMatrix44f mCamera;
cameraFrame.GetCameraMatrix(mCamera);
modelViewMatrix.MultMatrix(mCamera);//仅仅是获取cameraFrame中记录的位移,没有获得朝向和旋转
//modelViewMatrix.Translate(0.0f, -1.0f, -7.0f); //处理模型自身的旋转或缩放
M3DMatrix44f mObjectFrame;
objectFrame.GetCameraMatrix(mObjectFrame); //原书中的代码为GetMatrix,获取了objectFrame的朝向,导致顶点和纹理的对象关系出现了相反内容
modelViewMatrix.MultMatrix(mObjectFrame); glBindTexture(GL_TEXTURE_2D, textureID);
shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF,
transformPipeLine.GetModelViewMatrix(),
transformPipeLine.GetProjectionMatrix(),
vLightPos, vWhite, 0);
pyramidBatch.Draw();
//}
modelViewMatrix.PopMatrix(); glutSwapBuffers();
} void ShutdownRC(void)
{
glDeleteTextures(1, &textureID);
} void SpecialKeys(int key, int x, int y)
{
if (key == GLUT_KEY_UP)
{
objectFrame.RotateWorld(m3dDegToRad(5.0f),1.0f,0.0f,0.0f);//模型和摄像机的操作是相反的,模型向上旋转5.0f
} if (key == GLUT_KEY_DOWN)
{
objectFrame.RotateWorld(m3dDegToRad(-5.0f), 1.0f, 0.0f, 0.0f);
} if (key == GLUT_KEY_LEFT)
{
objectFrame.RotateWorld(m3dDegToRad(5.0f), 0.0f, 1.0f, 0.0f);
} if (key == GLUT_KEY_RIGHT)
{
objectFrame.RotateWorld(m3dDegToRad(-5.0f), 0.0f, 1.0f, 0.0f);
} glutPostRedisplay();
} int main(int argc, char * argv[])
{
gltSetWorkingDirectory(argv[0]); glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
glutInitWindowSize(800, 600);
glutCreateWindow("Pyramid");
glutReshapeFunc(ChangeSize);
glutSpecialFunc(SpecialKeys);
glutDisplayFunc(RenderScene); GLenum err = glewInit();
if (GLEW_OK != err) {
fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
return 1;
} SetupRC(); glutMainLoop(); ShutdownRC(); return 0;
}
OpenGL蓝宝书第五章代码勘误以及惯性坐标系去解释模型变换:Pyramid.cpp的更多相关文章
- OpenGL蓝宝书第七章:立体天空和纹理折射、双纹理(下)
对照了蓝宝书,才知道红宝书的长处. reflect函数的原理在红宝书中有说明,仅仅有对照了红宝书,才知道红宝书的定位:高级工具书. 蓝宝书作为入门级书籍,以较快的速度让读者敲到代码去思考,总遗留了须要 ...
- 小红书第五章——引用类型之function类型
有趣的函数——function类型 函数实际上是对象,每个函数都是function类型的实例,具有属性和方法. 1.函数的定义方法 1)函数声明语法 function sum(num1,num2){/ ...
- 紫书第五章训练3 D - Throwing cards away I
D - Throwing cards away I Given is an ordered deck of n cards numbered 1 to n with card 1 at the top ...
- 紫书第五章训练2 F - Compound Words
F - Compound Words You are to find all the two-word compound words in a dictionary. A two-word compo ...
- 《汇编语言 基于x86处理器》前五章的小程序
▶ 书中前五章的几个小程序,基本的运算操作,使用了作者的库 Irvine32 和 Irvine64(一开始以为作者网站过期了,各网站上找到的文件大小都不一样,最后发现是要搭梯子 Orz,顺利下载).注 ...
- ROS机器人程序设计(原书第2版)补充资料 (伍) 第五章 计算机视觉
ROS机器人程序设计(原书第2版)补充资料 (伍) 第五章 计算机视觉 书中,大部分出现hydro的地方,直接替换为indigo或jade或kinetic,即可在对应版本中使用. 计算机视觉这章分为两 ...
- OpenGL ES着色器语言之操作数(官方文档第五章)
OpenGL ES着色器语言之操作数(官方文档第五章) 5.1操作数 OpenGL ES着色器语言包含如下操作符. 5.2数组下标 数组元素通过数组下标操作符([ ])进行访问.这是操作数组的唯一操作 ...
- <自动化测试方案_5>第五章、代码单元自动化测试
第五章.代码单元自动化测试 代码单元测试需要根据编程语言,选择单元测试框架,然后访问类方法,函数.代码单元测试做自动化,相比API.UI自动化做起来更加麻烦,建议放到待API自动化测试.UI自动化测试 ...
- “全栈2019”Java异常第五章:一定会被执行的finally代码块
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java异 ...
随机推荐
- phpcms(4) V9 栏目管理
phpcms V9框架系统后台管理之栏目管理,请参见下文的源码分析(添加栏目和修改栏目): 参照添加栏目的界面图示,便于对源代码的理解: <?php // 文件路径:phpcms/modul ...
- 从windows到Linux-ubuntu新手
版本选择: 经多次实验,Ubuntu个人认为长期支持(LTS)版才值得装. VMware9中测试:Ubuntu10.04开机内存170M,Ubuntu12.04开机内存340M. 个人感觉Ubuntu ...
- underscorejs-size学习
2.24 size 2.24.1 语法: _.size(list) 2.24.2 说明: 返回列表的长度. 示例一:返回数组.对象.字符串的长度 //取数组的长度 var length length ...
- PHP对象类型在内存中的分配
对象类型和整型.字符串等类型一样,也是PHP中的一种数据类型.都是在程序中用于存储不同类型数据使用的,在程序运行时它的每部分内容都要先加载到内存中再被使用.那么对象类型的数据在内存中是如何分配的呢?先 ...
- Session和Cookie的学习笔记2
<?php /* Cookie在计算机中保存的格式 用户名@网站地址[数字].txt Cookie在文件夹下,每个Cookie文件都是一个简单而又普通的文件件而不是程序,Cookie中的内容大多 ...
- Windows系统下的TCP参数优化
1. TCP连接的状态 首先介绍一下TCP连接建立与关闭过程中的状态.TCP连接过程是状态的转换,促使状态发生转换的因素包括用户调用.特定数据包以及超时等,具体状态如下所示: CLOSED:初始状态, ...
- BZOJ 1019 汉诺塔
Description 汉诺塔由三根柱子(分别用A B C表示)和n个大小互不相同的空心盘子组成.一开始n个盘子都摞在柱子A上,大的在下面,小的在上面,形成了一个塔状的锥形体. 对汉诺塔的一次合法的操 ...
- 【Java】在Eclipse中使用JUnit4进行单元测试(初级篇)
本文绝大部分内容引自这篇文章: http://www.devx.com/Java/Article/31983/0/page/1 我们在编写大型程序的时候,需要写成千上万个方法或函数,这些函数的功能可能 ...
- cf C On Number of Decompositions into Multipliers
题意:给你n个数,然后把这个n个数的乘积化成n个数相乘,可以化成多少个. 思路:分解质因数,求出每一个质因子的个数,然后用组合数学中隔板法把这些质因子分成n分,答案就是所有质因子划分成n份的情况的乘积 ...
- 比较全面的gdb调试命令 (转载)
转自http://blog.csdn.net/dadalan/article/details/3758025 用GDB调试程序 GDB是一个强大的命令行调试工具.大家知道命令行的强大就是在于,其可以形 ...