• 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
    ", glewGetErrorString(err));
    		return 1;
    	}
    
    
    	SetupRC();
    
    	glutMainLoop();
    
    	ShutdownRC();
    
    	return 0;
    }


  • 相关阅读:
    .NET程序员面试小技巧
    .ashx一般处理程序
    地铁线路图的设计与实现
    BS与CS的区别
    关于sqlserver2005异地自动备份
    二问唐骏:究竟是打工好还是创业好
    再燃中国激情 “创业指南针”团队首推创业专著
    读者看《赢道:成功创业者的28条戒律》
    创业必看:中国八大草根富豪发家史
    让你快乐,是我恒久写诗的唯一目的
  • 原文地址:https://www.cnblogs.com/yxwkf/p/5283756.html
Copyright © 2020-2023  润新知