到tp那块就死机然后腾讯tp蓝屏修复是怎么回事

I've got an iphone project that draws a 3D model using OpenGL-ES for a given model view matrix and given projection matrix. I needed to replace 3D model with CALayer, so I put values of model view matrix into CATransform3D structure and assigned it to layer.transform. It worked well, layer was visible and moved on the screen as expected, but after some time I realized that my layers behavior is not precise enough and I should take projection matrix into account. And then a problem appeared: when I simply concatenate two matrices my layer looks odd (it is very small, about 2 pixels, while it is supposed to be about 300, as it is far far away) or is not visible at all. How can I solve it?
Here is the piece of code:
- (void)adjustImageObjectWithUserInfo:(NSDictionary *)userInfo
NSNumber *objectID = [userInfo objectForKey:kObjectIDKey];
CALayer *layer = [self.imageLayers objectForKey:objectID];
if (!layer) { }
CATransform3D transform = CATransform3DI
NSArray *modelViewMatrix = [userInfo objectForKey:kModelViewMatrixKey];
CGFloat *p = (CGFloat *)&
for (int i = 0; i & 16; ++i)
*p = [[modelViewMatrix objectAtIndex:i] floatValue];
// Rotate around +z for Pi/2
transform = CATransform3DConcat(transform, CATransform3DMakeRotation(M_PI_2, 0, 0, 1));
// Project with projection matrix
transform = CATransform3DConcat(transform, _projectionMatrix);
layer.transform =
Any help will be appreciated.
解决方案 I recently ran into this exact problem (I was using ARToolKit as well) and I was very disappointed to see that you hadn't figured out the answer.
I imagine you have moved on now but I figured it out and I am posting it for any other lost soul who might come through with this same problem.
The most confusing thing for me was that everyone talks about making a CALayer perspective transform by setting the m34 variable to a small negative number.
Although that does work it is not very informative at all.
What I eventually realized is that the transform works exactly like every other transform, it is a column major transformation matrix for homogenous coordinates.
The only special case is that it must combine the model view and projection matrices, and then scale to the size of the openGL viewport all in one matrix.
I started by trying to use a matrix in the style where m34 is a small negative number as explained in much greater detail
but eventually switched to open GL style perspective transforms as explained .
They are in fact
to one another they just represent different ways of thinking about the transform.
In our case we are trying to make the CALayer transform exactly replicate an open GL transform.
All that requires is multiplying together the modelview,projection,and scaling matrices and flipping the y axis to account for the fact that the device screen origin is top left and open GL is bottom left.
As long as the layer anchor is at (.5,.5) and its position is exactly in the center of the screen the result will be identical to the open GL's transform
void attach_CALayer_to_marker(CATransform3D* transform, Matrix4 modelView, Matrix4 openGL_projection, Vector2 GLViewportSize)
//Important: This function assumes that the CA layer has its origin in the
//exact center of the screen.
Matrix4 flipY = {
0, 0,0,1};
//instead of -1 to 1 we want our result to go from -width/2 to width/2, same
//for height
CGFloat ScreenScale = [[UIScreen mainScreen] scale];
float xscl = GLViewportSize.x/ScreenScale/2;
float yscl = GLViewportSize.y/ScreenScale/2;
//The open GL perspective matrix projects onto a 2x2x2 cube.
To get it onto the
//device screen it needs to be scaled to the correct size but
//maintaining the aspect ratio specified by the open GL window.
Matrix4 scalingMatrix = {xscl,0
//Open GL measures y from the bottom and CALayers measure from the top so at the
//end the entire projection must be flipped over the xz plane.
//When that happens the contents of the CALayer will get flipped upside down.
//To correct for that they are flipped updside down at the very beginning,
//they will then be flipped right side up at the end.
Matrix flipped = MatrixMakeFromProduct(modelView, flipY);
Matrix unscaled = MatrixMakeFromProduct(openGL_projection, flipped);
Matrix scaled = MatrixMakeFromProduct(scalingMatrix, unscaled);
//flip over xz plane to move origin to bottom instead of top
Matrix Final = SiMatrix4MakeFromProduct(flipY, scaled);
*transform = convert_your_matrix_object_to_CATransform3D(Final);
This function takes the open GLprojection, and openGL view size and uses them to generate the correct transform for the CALayer. The CALayer size should be specified in the units of the open GL scene.
The OpenGL viewport actually contains 4 variables, [xoffset,yoffset,x,y] but the first two are not relevant because the Origin of the CALayer is put in the center of the screen to correspond to the OpenGL 3d Origin.
Just replace Matrix with whatever generic 4x4 column major matrix class you have access to.
Anything will work just make sure you multiply your matrices in the right order. All this is essentially doing is replicating the OpenGL pipeline (minus clipping).
本文地址: &
我有一个iphone的项目,吸引了使用OpenGL-ES对于给定的模型视图矩阵,给投影矩阵的3D模型。我需要更换3D模型CALayer的,所以我把模型视图矩阵的值转换成CATransform3D结构,并将其分配给 layer.transform 。它运作良好,层是可见和感动如预期在屏幕上,但一段时间后,我意识到,我的层行为并不是precise够了,我应该采取的投影矩阵考虑。再一个问题出现了:当我只是连接两个矩阵我的层看起来很奇怪(这是非常小的,大约2个像素,而它应该是300,因为它是很远很远),或者是不可见的。我该如何解决呢?
下面是一张code:
- (无效)adjustImageObjectWithUserInfo:(NSDictionary中*)用户信息
的NSNumber * OBJECTID = [USERINFO objectForKey:kObjectIDKey]。
CALayer的*层= [self.imageLayers objectForKey:OBJECTID]。
如果(层!){返回; }
CATransform3D变换= CATransform3DI
NSArray的* modelViewMatrix = [USERINFO objectForKey:kModelViewMatrixKey]。
//获取原始模型视图矩阵;
CGFloat的* p值=(CGFloat的*)及变换;
的for(int i = 0; I< 16; ++ I)
* p = [[modelViewMatrix objectAtIndex:我]的floatValue]。
//左右旋转+ Z为π/ 2
变换= CATransform3DConcat(变换,CATransform3DMakeRotation(M_PI_2,0,0,1));
//项目与投影矩阵
变换= CATransform3DConcat(变换,_projectionMatrix);
layer.transform =变换;
任何帮助将AP preciated。
解决方案 我最近就遇到了这个确切的问题(我是用ARToolKit为好),我很失望地看到,你有没有想出答案。我想现在你已经移动了,但我想通了,我张贴任何其他丢失的灵魂谁可能来通过与此相同的问题。
最令人困惑的事情对我来说是,每个人都在谈论作出的CALayer透视变换的M34变量设置为较小的负数。虽然,它的工作是不是非常丰富的。我最终意识到的是,改造工程完全如隔变换,它是齐次坐标列重大的转换矩阵。唯一的特例是,它必须结合模型视图和投影矩阵,然后再扩展到了OpenGL的大小视口都在一个矩阵。我开始试图用一个矩阵的风格,M34是在更为详细的但最终切换到OPEN GL风格角度变换为这里解释彼此,他们只是重新present想着不同的方法变换。
在我们的例子中,我们正在努力让CALayer的变换完全复制一个开放的GL变换。所有需要的是模型观察,突起一起相乘,和缩放矩阵和翻转y轴以考虑的事实,即设备屏幕原点是左上角和开放的GL是左下角。只要层锚是在(0.5,0.5),它的位置是正好在屏幕中央的结果将是相同的开放GL的变换
无效attach_CALayer_to_marker(CATransform3D *变换,Matrix4模型观察,Matrix4 openGL_projection,Vector2 GLViewportSize)
//重要说明:此函数假定CA层起源于
//屏幕的正中央。
Matrix4 flipY = {1,0,0,0,
0,-1,0,0,
0,0,1,0,
0,0,0,1};
//而不是-1到1之间,我们希望我们的结果从-width / 2到宽/ 2,同
CGFloat的ScreenScale = [[UIScreen mainScreen]缩放]。
浮XSCL = GLViewportSize.x / ScreenScale / 2;
浮YSCL = GLViewportSize.y / ScreenScale / 2;
//开放GL投影矩阵项目到一个2x2x2的立方体。为了得到它到
//它需要设备屏幕缩放到正确的尺寸,但
//维持由开放GL窗口中指定的高宽比。
Matrix4 scalingMatrix = {XSCL,0,0,0,
0,YSCL,0,0,
0,0,1,0,
0,0,0,1};
// Open GL的测量从底部和CALayers量度Y均从顶部,这样在
//结束整个投影必须翻转xz平面。
//当发生这种情况的CALayer的内容将得到翻转倒置。
//为了校正它们翻转updside下来在开始的时候,
//便会被翻转右侧上在末端。
矩阵翻转= MatrixMakeFromProduct(模型观察,flipY);
矩阵非标度= MatrixMakeFromProduct(openGL_projection,翻转);
矩阵缩放= MatrixMakeFromProduct(scalingMatrix,无标度);
//空翻多XZ平面移动原点底部,而不是顶部
矩阵最终= SiMatrix4MakeFromProduct(flipY,缩放);
*变换= convert_your_matrix_object_to_CATransform3D(决赛);
此功能需要开启GLprojection,和OpenGL视图的大小,并用它们来生成正确的转换为CALayer的。该CALayer的大小应在开放GL场景的单位指定。 OpenGL的视口实际上包含4个变量,[xoffset,yoffset,X,Y],但前两个是不相关的,因为CALayer的起源放在屏幕的中心,对应OpenGL的3D起源。
刚刚与任何普通的4×4列主要矩阵类,你可以使用,以取代矩阵。任何将工作只是确保你在正确的顺序乘以你的矩阵。所有这一切基本上做的是复制的OpenGL管道(减削波)。
本文地址: &
扫一扫关注官方微信OpenGL学习笔记3:变换,矩阵,更多对象
进行图形开发,3D图形数学基础是必不可少,限于其专业性,OpenGL笔记里不做详细赘述。但是对相关术语及其在OpenGL对应的内容还是需要一定的了解。
两个(三分量)单位向量之间的点乘运算将得到一个标量(只有一个值),它表示两个向量之间的夹角。要进行这种运算,这两个向量必须为单位长度,而返回的结果将在-1.0到1.0之间。这个数字实际上就是这两个向量之间夹角的余弦值。
我们可以使用m3dDotProduct3函数来实际获得两个向量之间的点乘结果。
float m3dDotProduct3(const M3DVector3f u,const M3DVector3f v);
m3dGetAngleBetweenVectors3返回这个角的弧度制。
float m3dGetAngleBetweenVectors3 (const M3DVector3f u,const M3DVector3f v);
要进行叉乘,两个向量都不必为单位向量。
两个向量之间叉乘所得的结果是另外一个向量,这个新向量与原来两个向量定义的平面垂直。
m3dCrossProduct3对两个向量进行叉乘并返回运算得到的结果向量。
void m3dCrossproduct3(M3DVector3f result,const M3DVector3f u,const M3DVector3f v);
矩阵是一个二维数组,一个矩阵只有一行或者一列也是合法的。
在我们进行3D程序设计工作时,我们将使用的几乎全部是3X3和4X4矩阵。math3d库中有这两种矩阵数据类型:
typedef float M3DMatrix33f[9];
typedef float M3DMatrix44f[16];
OpenGL变换数据概览
制定观察者或照相机的位置
在场景中移动物体
描述视图和模型变换的二元性
改变视窗体 的大小或重新设置它的形状
这是一种伪变换,只是对窗口上的最终输出进行缩放
视图 制定观察者或照相机的位置
模型 在场景中移动物体
模型视图 描述视图和模型变换的二元性
投影 改变视窗体 的大小或重新设置它的形状
视口 这是一种伪变换,只是对窗口上的最终输出进行缩放
笛卡尔坐标系:从观察者的角度来看,x轴和y轴的正方向分别指向右方和上方。z轴的正方向从原点指向使用者,而z轴的负方向则从观察者指向屏幕内部。
当我们利用OpenGL进行3D绘制时,就会使用笛卡尔坐标系。如果不进行任何变换,那么使用的坐标系将与刚刚描述的视觉坐标系相同。
视图变换允许我们把观察点放在所希望的任何位置,并允许在任何方向上观察场景。确定视图变换就像在场景中放置照相机并让它指向某个方向。
模型变换用于操纵模型和其中的特定对象。这些变换将对象移动到需要的位置,然后再对它们进行旋转和缩放。
投影变换将在模型视图变换之后应用到顶点上,它将指定一个完成的场景(所有模型变换都已完成)是如何投影到屏幕上的最终图像。
正投影:所有多边形都是精确地按照指定的相对大小来在屏幕上绘制的。
透视投影:透视投影的特点是透视缩短,这种特性使得远处的物体看起来比进出同样大小的物体更小一些。
当所有变换完成后,就得到了一个场景的二维投影,它将被映射到屏幕上某处的窗口上。这种到物理创口标的映射是我们最后要做的变换,称为视口变换。
模型视图矩阵
模型视图矩阵是一个4X4矩阵,它表示一个变换后的坐标系,我们可以用来放置对象和确定对象的方向。一个包含单个顶点数据的矩阵乘以模型视图矩阵后得到新的视觉坐标。
OpenGL并不是将一个4X4矩阵表示为一个浮点值的二维数组,而是将它表示为一个由16个浮点值组成的单个数组。
前三纵列分别对应x轴,y轴,z轴上的方向。
如果有一个包含一个不同坐标系的位置和方向的4X4矩阵,然后用一个表示原来坐标系的向量(表示为一个列矩阵或向量)乘以这个矩阵,得到的结果是一个转换到新坐标系下的新向量。这就意味着,空间中任意位置和任何想要的方向都可以由一个4X4矩阵唯一确定,并且如果用一个对象的所有向量乘以这个矩阵,那么我们就将整个对象变换到了空间中的给定位置和方向。
单位矩阵中除了对角线上的一组元素之外,其他元素均为0。将一个向量乘以一个单位矩阵,就相当于用这个向量乘以1,不会发生任何改变。
平移vc3Ryb25nPjxiciAvPg0KztLDx7/J0tS199PDbWF0aDNkv+LW0LXEbTNkVHJhbnNsYXRpb25NYXRyaXg0NLqvyv3AtMq508Ox5Lu7vtjV86GjPC9wPg0KPHByZSBjbGFzcz0="brush:">
void m3dTranslationMatrix44(M3DMatrix44f m,float x,float y,float z);
m3dRotationMatrix44(M3DMatrix44f m,float angle,float x,float y,float z);
这个函数让我们围绕一个由x、y和z变量指定的向量来进行旋转。旋转的角度沿逆时针方向按照弧度计算,由变量angle指定。
下面的代码创建一个旋转矩阵,可以使顶点沿着任意由(1,1,1)指定的轴旋转45度:
m3dRotationMatrix(m3dDegToRad(45.0),1.0f,1.0f,1.0f);
宏m3dDegToRad将角度值转换为弧度制。
void m3dScaleMatrix44(M3DMatrix44f m,float xScale,float yScale,float zScale);
math3d库函数m3dMatrixMultiply44用来将两个矩阵相乘并返回运算结果。
void m3dMatrixMultiply44(M3DMatrix44f product,const M3DMatrix44f a,const M3DMatrix44f b);
运用模型视图矩阵
// Called to draw scene
void RenderScene(void)
// Clear the window with current clearing color
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
GLfloat vRed[] = { 1.0f, 0.0f, 0.0f, 1.0f };
M3DMatrix44f mFinalTransform, mTranslationMatrix, mRotationM
// 平移操作
m3dTranslationMatrix44(mTranslationMatrix, xPos, yPos, 0.0f);
// 每次绘制旋转5度
static float yRot = 0.0f;
yRot += 5.0f;
m3dRotationMatrix44(mRotationMatrix, m3dDegToRad(yRot), 0.0f, 0.0f, 1.0f);
//连接平移和旋转的结果到最终矩阵
m3dMatrixMultiply44(mFinalTransform, mTranslationMatrix, mRotationMatrix);
//使用矩阵将坐标存储到平面着色器中
shaderManager.UseStockShader(GLT_SHADER_FLAT, mFinalTransform, vRed);
squareBatch.Draw();
// Perform the buffer swap
glutSwapBuffers();
Orthographic(正交)和Perspective(透视)
我们可以使用math3d库或GLFrustum类来创建一个正投影矩阵
GLFrustum::SetOrthographic(GLfloat xMin,GLfloat xMax,GLfloat yMin,GLfloat yMax,GLfloat zMin,GLfloat zMax);
GLFrustum::SetPerspective(float fFov,float fAspect,float fNear,float fFar);
使用矩阵堆栈
GLMatrixStack类的构造函数允许指定堆栈的最大深度,默认的堆栈深度为64.这个矩阵堆栈在初始化时已经在堆栈中包含了单位矩阵。
GLMatrixStack::GLMatrixStack(int iStackDepth=64);
我们可以通过调用在顶部载入这个单位矩阵。
void GLMatrixStack::LoadIdentity(void);
或者可以在堆栈顶部载入任何矩阵。
void GLMatrixStack::LoadMatrix(const M3DMatrix44f m);
此外,我们可以用一个矩阵乘以矩阵堆栈的顶部矩阵,相乘得到的结果随后将存储在堆栈的顶部。
void GLMatrixStack::MultMatrix(const M3DMatrix44f);
最后,只要用GetMatrix函数就可以获得矩阵堆栈顶部的值,这个函数可以进行两次重载,以适应GLShaderManager的使用,或者仅仅是获得顶部矩阵的副本。
const M3DMatrix44f& GLMatrixStack::GetMatrix(void);
void GLMatrixStack::GetMatrix(M3DMatrix44f mMatrix);
压栈与出栈
void GLMatrixStack::PushMatrix(void);
void PushMatrix(const M3DMatrix44f mMatrix);
void PushMatrix(GLFrame& frame);
void GLMatrixStack::PopMatrix(void);
GLMatrixStack类也内建了对创建旋转、平移和缩放矩阵的支持。相应的函数列出如下:
void MatrixStack::Rotate(GLfloat angle,GLfloat x,GLfloat y,GLfloat z);
void MatrixStack::Translate(GLfloat x,GLfloat y,GLfloat z);
void MatrixStack::Scale(GLfloat x,GLfloat y,GLfloat z);
void ChangeSize(int nWidth, int nHeight)
glViewport(0, 0, nWidth, nHeight);
// 创建投影矩阵,并将它载入到投影矩阵堆栈中
viewFrustum.SetPerspective(35.0f, float(nWidth)/float(nHeight), 1.0f, 100.0f);
projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
// 设置变换管线以使用两个矩阵堆栈
transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
// Called to draw scene
void RenderScene(void)
static GLfloat vFloorColor[] = { 0.0f, 1.0f, 0.0f, 1.0f};
static GLfloat vTorusColor[] = { 1.0f, 0.0f, 0.0f, 1.0f };
// 基于时间的动画
static CStopWatch
float yRot = rotTimer.GetElapsedSeconds() * 60.0f;
// 清除颜色缓冲区和深度缓冲区
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 保存当前的模型视图矩阵 (单位矩阵)
modelViewMatrix.PushMatrix();
// 绘制背景
shaderManager.UseStockShader(GLT_SHADER_FLAT,
transformPipeline.GetModelViewProjectionMatrix(),
vFloorColor);
floorBatch.Draw();
// 绘制旋转的花托
modelViewMatrix.Translate(0.0f, 0.0f, -2.5f);
modelViewMatrix.Rotate(yRot, 0.0f, 1.0f, 0.0f);
shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(),
vTorusColor);
torusBatch.Draw();
// 保存以前的模型视图矩阵 (单位矩阵)
modelViewMatrix.PopMatrix();
// 进行缓冲区交换
glutSwapBuffers();
// 通知GLUT再进行一次同样操作
glutPostRedisplay();
使用照相机和角色进行移动
照相机管理
3D环境中典型的渲染循环流程
保存单位矩阵
应用照相机变换
绘制不会移动的物体
绘制移动的物体(角色)
绘制角色几何图形
应用角色变换
应用照相机变换
恢复照相机变换
恢复单位矩阵
GLFrame函数用来检索条件适合的照相机矩阵:
void GetCameraMatrix(M3DMatrix44f m,bool bRotationOnly=false);
将一个固定光源位置变换到视觉坐标在每个成精中只需进行一次:
M3DVector4f vLightPos={0.0f,10.0f,5.0f,1.0f};
M3DVector4f VLightEyeP
m3dTransformVector4(vLightEyePos,vLightPos,mCamera);
例如要渲染一个蓝色球体:
shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF,transformPipeline.GetModelViewMatrix(),transformPipeline,GetProjectionMatrix(),vLightEyePos,vSphereColor);
三角形批次类
首先,我们需要为对象创建一个事件。
GLTriangleBatch myCoolO
然后通知容器最多打算使用的顶点数,开始创建网格。
myCoolObject.BeginMesh(200);
接着来添加三角形,AddTriangle成员函数接受一个包含3个顶点的数组,一个包含3个法线的数组,以及一个包含3个纹理坐标的数组。
void GLTriangleBatch::AddTrangle(M3DVector3f verts[3],M3DVector3f vNorms[3],M3DVector2f vTexCoords[3]);
当我们添加完三角形时,调用End。
myCoolObject.End();
最后,调用Draw函数。
myCoolObject.Draw();
gltMakeSphere函数引用一个三角形批次、求的半径和组成球体的片段及其堆叠数量:
void gltMakeSphere(GLTriangleBatch& sphereBatch,GLfloat fRadius,Glint iSlices,Glint iStacks);
void gltMakeTorus(GLTriangleBatch& torusBatch,GLfloat majorRadius,GLfloat minorRadius,Glint numMajor,Glint numMinor);
圆柱或圆锥
void gltMakeCylinder(GLTriangleBatch& cylinderBatch,GLfloat baseRadius,GLfloat topRadius,GLfloat fLength,Glint numSlices,Glint numStacks);
void gltMakeDisk(GLTriangleBatch& diskBatch,GLfloat innerRadius,GLfloat outerRadius,Glint nSlices,Glint nStacks);
转载请注明出处:
#include &stdafx.h&
#define GLUT_DISABLE_ATEXIT_HACK
* 当libjpeg-turbo为vs2010编译时,vs2015下静态链接libjpeg-turbo会链接出错:找不到__iob_func,
* 增加__iob_func到__acrt_iob_func的转换函数解决此问题,
* 当libjpeg-turbo用vs2015编译时,不需要此补丁文件
#if _MSC_VER&=1900
#include &stdio.h&
_ACRTIMP_ALT FILE* __cdecl __acrt_iob_func(unsigned);
#ifdef __cplusplus
extern &C&
FILE* __cdecl __iob_func(unsigned i) {
return __acrt_iob_func(i);
#endif /* _MSC_VER&=1900 */
#define NUM_SPHERES 50
GLFrame disk[NUM_SPHERES/2];
GLFrame cylinder[NUM_SPHERES/2];
GLShaderManager
// Shader Manager
GLMatrixStack
modelViewM
// Modelview Matrix
GLMatrixStack
projectionM
// Projection Matrix
// View Frustum
GLGeometryTransform transformP
// Geometry Transform Pipeline
GLTriangleBatch
GLTriangleBatch
GLTriangleBatch
GLTriangleBatch
GLTriangleBatch
//////////////////////////////////////////////////////////////////
// This function does any needed initialization on the rendering
// context.
void SetupRC()
// Initialze Shader Manager
shaderManager.InitializeStockShaders();
glEnable(GL_DEPTH_TEST);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
// 制造花圈
gltMakeTorus(torusBatch, 0.4f, 0.15f, 30, 30);
// 制造小球
gltMakeSphere(sphereBatch, 0.3f, 26, 13);
//制造圆柱
gltMakeCylinder(cylinderBatch, 0.2f, 0.2f, 0.5f, 13, 2);
//制造圆盘
gltMakeDisk(diskBatch, 0.2f, 0.4f, 13, 3);
floorBatch.Begin(GL_LINES, 324);
for (GLfloat x = -20.0; x &= 20.0f; x += 0.5) {
floorBatch.Vertex3f(x, -0.55f, 20.0f);
floorBatch.Vertex3f(x, -0.55f, -20.0f);
floorBatch.Vertex3f(20.0f, -0.55f, x);
floorBatch.Vertex3f(-20.0f, -0.55f, x);
floorBatch.End();
// Randomly place the spheres
for (int i = 0; i & NUM_SPHERES; i++) {
GLfloat x = ((GLfloat)((rand() % 400) - 200) * 0.1f);
GLfloat z = ((GLfloat)((rand() % 400) - 200) * 0.1f);
if(i%2==0)
disk[i/2].SetOrigin(x, 0.0f, z);
cylinder[(i-1)/2].SetOrigin(x, 0.0f, z);
GLfloat vetts[3][3];
GLfloat vNorms[3][3];
GLfloat vTexCoords[3][2];
GLfloat angle = 0;
for (int i = 0; i & 3; i++) {
angle += M3D_2PI / 6.0f;
vetts[i][0] = float(-5 + i*0.2);
vetts[i][1] = float(sin(float(angle)));
vetts[i][2] = float(cos(float(angle)));
vNorms[i][0] = float(-5 + i*0.2);
vNorms[i][1] = float(cos(float(angle)));
vNorms[i][2] = float(sin(float(angle)));
vTexCoords[i][0] = float(-5 + i*0.2);
vTexCoords[i][1] = float(sin(float(angle)));
triangleBatch.BeginMesh(3);
triangleBatch.AddTriangle(vetts, vNorms, vTexCoords);
triangleBatch.End();
///////////////////////////////////////////////////
// Screen changes size or is initialized
void ChangeSize(int nWidth, int nHeight)
glViewport(0, 0, nWidth, nHeight);
// 创建投影矩阵,并将它载入到投影矩阵堆栈中
viewFrustum.SetPerspective(35.0f, float(nWidth) / float(nHeight), 1.0f, 100.0f);
projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
// 设置变换管线以使用两个矩阵堆栈
transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
// Called to draw scene
void RenderScene(void)
static GLfloat vFloorColor[] = { 0.0f, 1.0f, 0.0f, 1.0f };
static GLfloat vTorusColor[] = { 1.0f, 0.0f, 0.0f, 1.0f };
static GLfloat vSphereColor[] = { 0.0f, 0.0f, 1.0f, 1.0f };
static GLfloat vdiskColor[] = { 0.0f, 0.5f, 0.5f, 1.0f };
static GLfloat vcylinderColor[] = { 0.5f, 0.0f, 0.5f, 1.0f };
// 基于时间的动画
static CStopWatch
float yRot = rotTimer.GetElapsedSeconds() * 60.0f;
// 清除颜色缓冲区和深度缓冲区
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 保存当前模型视图矩阵 (单位矩阵)
modelViewMatrix.PushMatrix();
M3DMatrix44f mC
cameraFrame.GetCameraMatrix(mCamera);
modelViewMatrix.PushMatrix(mCamera);
// 将光源位置变换到视觉坐标系
M3DVector4f vLightPos = { 0.0f, 10.0f, 5.0f, 1.0f };
M3DVector4f vLightEyeP
m3dTransformVector4(vLightEyePos, vLightPos, mCamera);
// 绘制背景
shaderManager.UseStockShader(GLT_SHADER_FLAT,
transformPipeline.GetModelViewProjectionMatrix(),
vFloorColor);
floorBatch.Draw();
//绘制圆柱和圆盘
for (int i = 0; i & NUM_SPHERES; i++) {
modelViewMatrix.PushMatrix();
if (i % 2 == 0) {
modelViewMatrix.MultMatrix(disk[i / 2]);
shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF, transformPipeline.GetModelViewMatrix(),
transformPipeline.GetProjectionMatrix(), vLightEyePos, vdiskColor);
diskBatch.Draw();
modelViewMatrix.MultMatrix(cylinder[(i - 1) / 2]);
shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF, transformPipeline.GetModelViewMatrix(),
transformPipeline.GetProjectionMatrix(), vLightEyePos, vcylinderColor);
cylinderBatch.Draw();
modelViewMatrix.PopMatrix();
// 绘制旋转花托
modelViewMatrix.Translate(0.0f, 0.0f, -2.5f);
// 保存平移矩阵
modelViewMatrix.PushMatrix();
// 应用旋转并绘制花托
modelViewMatrix.Rotate(yRot, 0.0f, 1.0f, 0.0f);
shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF, transformPipeline.GetModelViewMatrix(),
transformPipeline.GetProjectionMatrix(), vLightEyePos, vTorusColor);
torusBatch.Draw();
modelViewMatrix.PopMatrix(); // &清除& 以前的旋转
//绘制三角形
//modelViewMatrix.PushMatrix();
modelViewMatrix.Rotate(yRot, 0.0f, 1.0f, 0.0f);
shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF, transformPipeline.GetModelViewMatrix(),
transformPipeline.GetProjectionMatrix(), vLightEyePos, vTorusColor);
triangleBatch.Draw();
//modelViewMatrix.PopMatrix();
// 应用另一个旋转,然后进行平移,然后再绘制球体
modelViewMatrix.Rotate(yRot * -2.0f, 0.0f, 1.0f, 0.0f);
modelViewMatrix.Translate(0.8f, 0.0f, 0.0f);
shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF, transformPipeline.GetModelViewMatrix(),
transformPipeline.GetProjectionMatrix(), vLightEyePos, vSphereColor);
sphereBatch.Draw();
// 还原到以前的模型视图矩阵 (单位矩阵)
modelViewMatrix.PopMatrix();
modelViewMatrix.PopMatrix();
// 进行缓冲区交换
glutSwapBuffers();
// 通知GLUT在进行一次同样操作
glutPostRedisplay();
// Respond to arrow keys by moving the camera frame of reference
void SpecialKeys(int key, int x, int y)
float linear = 0.1f;
float angular = float(m3dDegToRad(5.0f));
if (key == GLUT_KEY_UP)
cameraFrame.MoveForward(linear);
if (key == GLUT_KEY_DOWN)
cameraFrame.MoveForward(-linear);
if (key == GLUT_KEY_LEFT)
cameraFrame.RotateWorld(angular, 0.0f, 1.0f, 0.0f);
if (key == GLUT_KEY_RIGHT)
cameraFrame.RotateWorld(-angular, 0.0f, 1.0f, 0.0f);
int main(int argc, char* argv[])
gltSetWorkingDirectory(argv[0]);
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(800, 600);
glutCreateWindow(&OpenGL SphereWorld&);
glutSpecialFunc(SpecialKeys);
glutReshapeFunc(ChangeSize);
glutDisplayFunc(RenderScene);
GLenum err = glewInit();
if (GLEW_OK != err) {
fprintf(stderr, &GLEW Error: %s\n&, glewGetErrorString(err));
SetupRC();
glutMainLoop();
按方向键可以移动和旋转画面,可以看到三角形,小球围绕花圈转动,花圈自己在自旋转。

我要回帖

更多关于 虚拟机tp蓝屏 的文章

 

随机推荐