三维图形的这是opengl的强项,大型3D游戏都会把它作为首选。
图像处理,是opencv的锁定的目标,大多都是C的api,也有少部分是C++的,工业图像表现,图像识别,都会考虑opencv的。
webgl,这是3维向web延伸的方案,它可以直接调用支持opengl的接口,硬件加速或者软件模拟,很强大,结和html5....
blender,可以完成三维模型制作,3D动画制作了。
http://www.2cto.com/kf/201305/210028.html
PC 游戏还是 DirectX 开发? 事实上在早年OpenGL即使在游戏领域也是对DirectX压倒性的优势。John Carmack曾嘲讽DirectX是“horribly broken” 的API。 直到DirectX6时代OpenGL都被认为是比DirectX更加优秀的API,即使那个时候DirectX已经有《CS》《极品飞车5》等大作的支持,却依然不受当时FPS游戏霸主id Software的待见。作为那个时代的显卡杀手,《Quake III》都仅仅只支持OpenGL。 DirectX7发布之后DirectX和OpenGL开始逐渐平起平坐。直到2000年DirectX8的发布才使DirectX在游戏领域完全确立了自己的优势 —— 支持革命性的programmable GPU rendering pipeline来代替原有的fixed function pipeline,引入了Vertex Shader和Pixel Shader。而OpenGL的核心正式支持programmable rendering pipeline已经是四年之后OpenGL 2.0发布的时候了。想想这中间会有多少游戏公司/游戏引擎公司会倒向DirectX吧。 说到OpenGL衰落的原因,不得不提到OpenGL开发的机制。OpenGL早期一直是由ARB ( OpenGL Architecture Review Board,成员包括Nvidia, ATI, Intel, Apple, IBM, SGI等等)成员共同维护。每个成员可以为了支持自己硬件新的feature来开发OpenGL enxtension, 所有成员一致通过的extension才能加入到下个版本OpenGL核心中。这就造成了不同成员为了各自利益互相斗争,拖慢了开发进度。微软曾经也是ARB的成员之一,后来因为受不了这种机制退出专心搞自己的DirectX去了。 如果一个API越流行,那么去学习这个API的人就会越多,游戏公司会越容易招到掌握这个API的图形程序员,也就会更多的基于这个API开发游戏。用这个API的游戏越来越多,就会更多的得到 硬件厂商的支持,为面向这个API的驱动做更多的优化,然后这个API就会更加流行。如此进入一个良性循环,这就造成了DirectX现在称霸游戏领域,OpenGL几乎绝迹的局面。 在06年从ARB交由Khronos Group掌管之后, OpenGL最近几年也迎头赶上,从性能,易用性来说其实和DirectX已经相差不大。但是在相比DirectX没有突出优点的情况下(除了跨平台),已经习惯使用DirectX的游戏厂商也不可能重新投出OpenGL的怀抱。 最后一点,OpenGL只是一个单纯的图形库,而DirectX是包含图形(Direct3D), 声音(DirectSound), 输入(DirectInput), 网络(DirectPlay)的一整套游戏开发解决方案。对开发者来说使用DirectX显然要方便的多。 /*******************************************************************************************************/ 下面是我之前一个同事看完我的回答的评论,也贴上来吧。 “还有很重要的一点, GL从不淘汰任何老的API. DX10相对于DX9,是个全新的API,革命性的更新,彻底推倒重来. 但GL为了向后兼容,保留了很多对硬件和驱动都不友好的API.除了跨平台和早期对精度的要求比DX高,其他简直是一无是处” 于是Game开发者就都去用DX了。如果Linux上有类似于DX的接口,只要它真正被广泛支持了,包括但不限于OpenGL DSA 扩展,相信我,没有哪个开发者会脑袋抽风继续跟随坑爹的状态机的。 OpenGL的硬件兼容性不如DirectX。用OpenGL写一个程序,在nVidia上跑起来了,百分之八十是没法在intel上跑,百分之九十九没法在AMD上跑。OpenGL直到目前为止如果不用DSA的话,设置一个对象的属性还得先绑定,这样一来就使得code变得高度依赖于一个时刻在变的状态,而且很多驱动的实现某些特定的状态下有各种bug,极难调试。例如我之前在intel上跑一个程序,如果不每帧都重新设置一个framebuffer object的render target, 那个framebuffer到了下一帧就莫名其妙的失效了,而在NV和AMD上都没有此问题,但是AMD又出了另外一个问题。 DirectX的好处有微软帮你测试兼容性。一个驱动想拿到WDDM认证,先得跑通积累了十几年的test set,这样一来在实际中遇到问题的可能性就大为减少了。另外DX有开发调试环境的优势,以及更合理的API设计。 dx甩opengl几条街 学图形学还是多看看理论书吧,看API没什么意思。 你要知道,至少到vs2008,vs自带的opengl头文件都只是1.1版本的,你这叫人如何用? 微软为了发展DX抑制OpenGL几乎每一本OpenGL书籍都会提到。 -------分割更新-------- 再有就是DX的SDK属于虽然要自己下而且很大但是可以开箱即用,OpenGL就不一样了,glew,glext,glut等等一大堆各式版本的头文件,还要自己保证兼容等等问题……不说了,都是泪 对于从游戏开发者角度而言,OpenGL 曾经是个没人用的东西,Windows / Xbox 上可以用 DirectX,PS3 和 Wii 则又是另外的图像API。 直到iPhone的兴起,OpenGL 居然又活了过来,你看现在连 WebGL 都出现了,有一种统一天下的感觉。 游戏开发者又开始重视 OpenGL 了,当然主要还是 OpenGL ES。 对于显卡公司而言,Windows 上的 D3D 驱动特别重要,会针对各种流行游戏进行定制、优化、hack……至于 OpenGL 驱动,似乎只要满足 CAD 大厂的需求即可,毕竟几乎没有 Windows 上的 OpenGL 游戏啊…… 现阶段,从性能考虑(D3D 驱动会特别优化),大型的游戏还是以 D3D 的形式发布,不排除 OpenGL 的优化上去以后也会有大型的桌面 OpenGL 游戏。 对于微软而言,他对于OpenGL的限制非常多,比如WindowsRT,Windows Phone是不支持OpenGL,Windows商店里的应用也必须是DirectX的。 Dota2的OS X和Linux版就是OpenGL的Source引擎做的 近10年来,opengl追赶dx就跟java追赶C#一样。opengl原本是一种设计来做CAD的api,后来被用来搞游戏,火了之后不思进取,造成了计算模型落后到爆炸,后面才慢慢改成了dx11现在的样子的。 而且opengl煞笔还要怪那些A开头公司的编译器。众所周知,一个公司一旦以A开头,那他自主研发的编译器就跟垃圾一样。opengl(和opencl一样)标准要求驱动程序自己去写编译器,就别说linux了,在windows上不同的卡都有互相不兼容的bug。而directx的标准要求驱动程序解释一个指令集的中间语言,不兼容的情况就少了好多,虽然还有,但是已经没什么所谓了。 不过由于底子不好,opengl的api用起来始终没有dx11那么舒服。 P.S.,由于opencl也是一个德行,在windows上的A卡定义一个struct都会导致驱动程序崩溃什么的,让人怎么用啊,只能选cuda或directcompute了。 llvm是apple买的?llvm的创造者在apple工作了快有十年了,而且他还是swift的创造者,他本人已经算apple的一份子了吧。llvm确实是2000年就诞生了,但是走向成熟且大展拳脚则是在加盟apple以后吧 强烈建议初学计算机图形学的玩家不要跳OpenGL这个坑,可能在你编译第一个demo的时候,这辈子就和CG绝缘了。下面就是我的血泪史: 首先,OpenGL自身功能集成度太低,你要么选择大量的附加依赖项,要么写大量的代码。于是各种附加依赖层出不穷,从创建Wnd的glut到windows扩展glew,你都需要了解学习。不过你学习的过程就会惊喜的发现,有一些竟然不更新了,XP available ONLY 哦!剩下那些有更新也是一个丑的不能看的网站(还不如GNU系列的网站,你懂得),只提供源码(由于服务器缘故,下载速度让我还以为被墙了),需要自己编译。很多还是有多层依赖的,这些都需要自己一层一层的下载编译。而且由于C++编译选项千奇百怪,你必须要注意每个库的编译,否则链接错误就是个灾难。而且由于都是自己编译的,拿到别人的电脑上也没法用,别人也需要重新编译,甚至还要修改一些头文件的引用!面对一堆不是你写的,一坨宏和依赖项的C++头文件,去修改,画面真美。而且每换一个地方就要编译20分钟,那酸爽也是绝了。 而且你想写原生的windows窗口,使用Windows Message Loop,而不是用glut的玩具一样的功能,由于没有Help Templates,我当时为了写一个支持多重采样的窗体,看了十几个OpenGL的英文(中文几乎没有开发者!呵呵)wiki和网上教程,才理解了gl绘图上下文的“二次创建”还有颜色模式。最后写出了一个好几百行、N多函数满地宏的main.cpp。当我给别人讲这些的时候,别人都觉得是天书。而一年之后,我也忘了。而DX3D我下载了Sample之后,由于有Templates、Help Tools,我根本不操心窗体创建、Message Loop,可以直奔主题编辑图形,感觉直接到了天堂。 此外,OpenGL里面各种绑定,API接口,让人头晕目眩,一个函数N个参数(而且参数名字长相还特别像,还都是宏,酸爽你懂得),还由于开发者少,生态差,没有一份清晰的文档,也没有特别好的教程。当时为了学习OpenGL,我买了一本红宝书,简直是API Reference + 计算机图形学导论啊,就觉得100块钱买了个砖,根本看不下去。顺带一提,这个绑定机制极其反人类,当时一不小心绑定错了一个ID,各种诡异的现象都出现了,因为模型库都来自于修改第三方,debug用了一天,顺便读了一次3000多行的3D图形导入库,对这一坨坨的递归找BUG,学到的知识简直丰富无比,DEBUG技能点不知道增长了多少。 同样是由于生态差,目前本应该主流使用的GLSL也很难找到资料学习,所以只能用1.1版本的API。然而放弃GLSL就等于回到了那个固定流水的老GPU时代,现代GPU的高效运算、多线程根本用不到了,又回到那个CPU运算为主,命令列表渲染的低效率时代。老师讲解的模型视点变换、透视变换,本来都应该是自己用GLSL实现的,结果都变成了调用现成API,学的东西和练习的东西完全脱节,导致课程实验效果很差,学生们做起来都是十分痛苦。最后图形学的知识几乎成了死记硬背来考试的,学生也没有在实验中获得多少快乐(个别如我这种喜欢自虐的除外。 当然,最大的问题是难以调试!纯C++的OpenGL出BUG时尽管看不到调试的图形反应,但是起码能看到数据反映。但是加入了着色器以后的,如果C++部分编译、运行全部正常,然而却没有任何图像或者不尽如人意的话,恭喜你,锅都在GLSL的部分,而这一部分根本你不能调试,只能对着黑屏发呆思考哪个公式不对,那个数据传递有问题,可能一折腾几个小时就过去了。后来尽管有nSight,但是笔记本双显卡还不能用(默哀~,不知道现在改进了吗?)。这样的调试支持,可以说是要把开发者逼上梁山,不能Debug还玩毛线啊。 网上有人评论,OpenGL你看一本红宝书下去,写出的代码都未必能运行;但是你用DX3D,HelloWorld Sample能跑,基本就可以出程序了。看我想他们易用性差距也就这么大吧。 最后,因为OpenGL的一坨坑,我差点放弃学习计算机图形学,幸好我凭借“毅力”挺了过来,还做出了一个有天空盒、地形、模型导入、粒子系统、反狗牙的小图形引擎,拿了很高的分数。尽管如此,这两天搞毕设,我宁愿用从来没有接触过的DX3D做,也不愿意再碰OpenGL了,毕竟少生点气,多活两年比啥也重要。 我大学的图形学课程教了我OpenGL入门。 如果改成DirectX入门我估计要挂到天荒地老... OpenGL上手容易:强大的glut封装了很多诸如创建窗口之类的繁琐工作,而且一开始你根本不需要接触复杂的顶点缓冲之类的复杂概念,挨着调用glVertex(),glColor()之类的函数就可以一个一个的将顶点画上去。反观DX,除了从一开始你就得掌握一些windows编程知识用于基本的创建窗口之外,你还必须掌握定点缓冲,一次性传输所有顶点进去才可以让DX进行绘制。作为新手,用OpenGL画一个正方体比DX容易太多... 也更容易建立初始的成就感和兴趣... 事实上老师根本没有讲到顶点缓冲以后的知识。毕竟是计算机图形学,不是OpenGL课... 这些都是我后来自学的。不过还好我学了,DX才能入门.. 作为一个两边都接触过的码农来回这个帖子。因为太久没碰GL,可能有误,欢迎指出。代码我就不贴了。
Estereo
Estereo是一个开源的双目或者三目立体视觉重建程序,可以在这个地址下载https://sourceforge.net/project/stats/detail.php?group_id=126733&ugn=estereo&type=prdownload
编译需要安装vc.net和directx9.0 sdk,编译时可能需要修改几处地方
1.很多显卡不支持硬件VB,所以修改这里
D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
m_hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,//D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE,
&m_d3dpp,
&m_pD3DDevice);
2.有些电脑不能显示三维重建结果,需要修改这里将这些代码移出OnInitdialog
CWnd* pParent = GetParent();
CRect rcParent;
pParent->GetWindowRect(&rcParent);
MoveWindow(&rcParent);
C3DWindow* p3DWindow= (C3DWindow*)GetDlgItem(IDC_3D_CONTROL);
if(p3DWindow)
{
CRect rcControl;
GetClientRect(&rcControl);
rcControl.DeflateRect(10,10,10,10);
p3DWindow->MoveWindow(&rcControl);
if(((CButton*)GetDlgItem(IDC_CHECK_INITPOS))->GetCheck())
p3DWindow->SetRegistryKey("3D Reconstruction");//arcball params should be kept separate
p3DWindow->Start(false);
p3DWindow->CreateVB(m_nPoints,m_pX,m_pY,m_pZ,m_pC,m_pS);
}
可以自己加上一个按钮,将这些代码加入按钮的响应函数中
//#include <GL/gl.h>
#include <GL/glaux.h>
#include <glut.h>
//glaux.lib glut32.lib
namespace Test9
{
#include <windows.h> // Header File For Windows
#include <math.h> // Math Library Header File
#include <stdio.h> // Header File For Standard Input/Output
#include <glgl.h> // Header File For The OpenGL32 Library
#include <glglu.h> // Header File For The GLu32 Library
#include <glglaux.h> // Header File For The Glaux Library
HDC hDC=NULL; // Private GDI Device Context
HGLRC hRC=NULL; // Permanent Rendering Context
HWND hWnd=NULL; // Holds Our Window Handle
HINSTANCE hInstance; // Holds The Instance Of The Application
bool keys[256]; // Array Used For The Keyboard Routine
bool active=TRUE; // Window Active Flag Set To TRUE By Default
bool fullscreen=TRUE; // Fullscreen Flag Set To Fullscreen Mode By Default
bool blend; // Blending ON/OFF
bool bp; // B Pressed?
bool fp; // F Pressed?
const float piover180 = 0.0174532925f;
GLfloat walkbias = 0;
GLfloat walkbiasangle = 0;
GLfloat rot_x = 0.0f;
GLfloat rot_y=0; // Y Rotation
GLfloat rot_z=0;
GLfloat g_z=-5.0f; // Depth Into The Screen
GLfloat x=0.0f; // Depth Into The Screen
GLfloat y=0.0f; // Depth Into The Screen
GLuint filter; // Which Filter To Use
GLuint texture[3]; // Storage For 3 Textures
typedef struct tagVERTEX
{
float x, y, z;//3D坐标
float u, v;//纹理坐标
} VERTEX;
typedef struct tagTRIANGLE
{//Triangle三角形结构
VERTEX vertex[3];
} TRIANGLE;
typedef struct tagSECTOR
{
int numtriangles;// Sector中的三角形个数
TRIANGLE* triangle;// 指向三角数组的指针
} SECTOR;
SECTOR sector1; // Our Model Goes Here:
typedef struct{
int numPoints;
VERTEX *vertex;
}MYPOINTS;
MYPOINTS g_pts;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Declaration For WndProc
void readstr(FILE *f,char *string)
{// 读入一个字符串
do
{
fgets(string, 255, f);
int i1=0,i2=strlen(string),i;
while (string[i1] && (string[i1]==' ' || string[i1]==' '))i1++;
// printf("i1=%d ",i1);
// printf(string);
// while (string[i2]==' ' || string[i2]==' ')i1--;
if(i1>=i2)
continue;
else if(i1>0)
{
for (i=i1;i<i2;i++)
{
string[i-i1]=string[i];
}
string[i2-i1]=0;
// printf(string);
}
} while ((string[0] == '/') || (string[0] == ' '));
return;
}
void SetupWorld()
{// 设置我们的世界
float x, y, z, u, v;
int numtriangles;
FILE *filein;
char oneline[255];
filein = fopen("world.txt", "rt"); // File To Load World Data From
CHECK(filein);
readstr(filein,oneline);
//printf(oneline);
sscanf(oneline, "NUMPOLLIES %d ", &numtriangles);
CHECK(numtriangles>0);
sector1.triangle = new TRIANGLE[numtriangles];
sector1.numtriangles = numtriangles;
for (int loop = 0; loop < numtriangles; loop++)
{
for (int vert = 0; vert < 3; vert++)
{
readstr(filein,oneline);
sscanf(oneline, "%f %f %f %f %f", &x, &y, &z, &u, &v);
sector1.triangle[loop].vertex[vert].x = x;
sector1.triangle[loop].vertex[vert].y = y;
sector1.triangle[loop].vertex[vert].z = z;
sector1.triangle[loop].vertex[vert].u = u;
sector1.triangle[loop].vertex[vert].v = v;
}
}
fclose(filein);
return;
}
//支持定义点和面(三角和四边形)
void SetupWorld2()
{// 设置我们的世界
float x, y, z, u, v;
int numpoints;
FILE *filein;
char oneline[255];
filein = fopen("world2.txt", "rt"); // File To Load World Data From
CHECK(filein);
//读入点
readstr(filein,oneline);
CHECK(1==sscanf(oneline, "NUMPOINTS %d ", &numpoints));
CHECK(numpoints>0);
g_pts.numPoints=numpoints;
g_pts.vertex=new VERTEX[numpoints];
for (int loop = 0; loop < numpoints; loop++)
{
readstr(filein,oneline);
CHECK(5==sscanf(oneline, "%f %f %f %f %f", &x, &y, &z, &u, &v));
g_pts.vertex[loop].x=x;
g_pts.vertex[loop].y=y;
g_pts.vertex[loop].z=z;
g_pts.vertex[loop].u=u;
g_pts.vertex[loop].v=v;
}
//读入面
int numtriangles=0;
readstr(filein,oneline);
CHECK(1==sscanf(oneline, "NUMPTRIANGLES %d ", &numtriangles));
CHECK(numtriangles>0);
sector1.triangle = new TRIANGLE[numtriangles];
sector1.numtriangles = numtriangles;
for ( loop = 0; loop < numtriangles; loop++)
{
int index[3];
readstr(filein,oneline);
CHECK(3==sscanf(oneline, "%d %d %d",index,index+1,index+2));
CHECK(index[0]>=0 && index[0]<g_pts.numPoints);
CHECK(index[1]>=0 && index[1]<g_pts.numPoints);
CHECK(index[2]>=0 && index[2]<g_pts.numPoints);
for (int vert = 0; vert < 3; vert++)
{
sector1.triangle[loop].vertex[vert]= g_pts.vertex[index[vert]];
}
}
fclose(filein);
return;
}
AUX_RGBImageRec *LoadBMP(char *Filename) // Loads A Bitmap Image
{
FILE *File=NULL; // File Handle
if (!Filename) // Make Sure A Filename Was Given
{
return NULL; // If Not Return NULL
}
File=fopen(Filename,"r"); // Check To See If The File Exists
if (File) // Does The File Exist?
{
fclose(File); // Close The Handle
return auxDIBImageLoad(Filename); // Load The Bitmap And Return A Pointer
}
return NULL; // If Load Failed Return NULL
}
int LoadGLTextures() // Load Bitmaps And Convert To Textures
{
int Status=FALSE; // Status Indicator
AUX_RGBImageRec *TextureImage[1]; // Create Storage Space For The Texture
memset(TextureImage,0,sizeof(void *)*1); // Set The Pointer To NULL
// Load The Bitmap, Check For Errors, If Bitmap's Not Found Quit
if (TextureImage[0]=LoadBMP("1.bmp"))
{
Status=TRUE; // Set The Status To TRUE
glGenTextures(3, &texture[0]); // Create Three Textures
// Create Nearest Filtered Texture
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);
// Create Linear Filtered Texture
glBindTexture(GL_TEXTURE_2D, texture[1]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);
// Create MipMapped Texture
glBindTexture(GL_TEXTURE_2D, texture[2]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);
}
if (TextureImage[0]) // If Texture Exists
{
if (TextureImage[0]->data) // If Texture Image Exists
{
free(TextureImage[0]->data); // Free The Texture Image Memory
}
free(TextureImage[0]); // Free The Image Structure
}
return Status; // Return The Status
}
GLvoid ReSizeGLScene(GLsizei width, GLsizei height) // Resize And Initialize The GL Window
{
if (height==0) // Prevent A Divide By Zero By
{
height=1; // Making Height Equal One
}
glViewport(0,0,width,height); // Reset The Current Viewport
glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
glLoadIdentity(); // Reset The Projection Matrix
// Calculate The Aspect Ratio Of The Window
gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
glLoadIdentity(); // Reset The Modelview Matrix
}
int InitGL(GLvoid) // All Setup For OpenGL Goes Here
{
if (!LoadGLTextures()) // Jump To Texture Loading Routine
{
return FALSE; // If Texture Didn't Load Return FALSE
}
glEnable(GL_TEXTURE_2D); // Enable Texture Mapping
glBlendFunc(GL_SRC_ALPHA,GL_ONE); // Set The Blending Function For Translucency
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // This Will Clear The Background Color To Black
glClearDepth(1.0); // Enables Clearing Of The Depth Buffer
glDepthFunc(GL_LESS); // The Type Of Depth Test To Do
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glShadeModel(GL_SMOOTH); // Enables Smooth Color Shading
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations
SetupWorld2();//建立世界
return TRUE; // Initialization Went OK
}
int DrawGLScene(GLvoid) // Here's Where We Do All The Drawing
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
glLoadIdentity(); // Reset The View
GLfloat x_m, y_m, z_m, u_m, v_m;
static DWORD tickCnt=GetTickCount();
int numtriangles;
glTranslatef(x, y, g_z);
#if 1
glRotatef(rot_x,1.0f,0,0);
glRotatef(rot_y,0,1.0f,0);
glRotatef(rot_z,0,0,1.0f);
#else
int norm=sqrt(rot_x*rot_x+rot_y*rot_y+rot_z*rot_z);
int ang_x=0;
int ang_y=0;
int ang_z=0;
if(norm>10)
{
ang_x=rot_x/norm;
ang_y=rot_y/norm;
ang_z=rot_z/norm;
}
else
norm=0;
glRotatef(norm,rot_x,rot_y,rot_z);
#endif
if(GetTickCount()-tickCnt>1000)
{
printf("Trans %8g %8g %8g ",x,y,g_z);
printf("Rot %8g %8g %8g ",rot_x,rot_y,rot_z);
tickCnt=GetTickCount();
}
glBindTexture(GL_TEXTURE_2D, texture[filter]);
numtriangles = sector1.numtriangles;
// Process Each Triangle
for (int loop_m = 0; loop_m < numtriangles; loop_m++)
{
glBegin(GL_TRIANGLES);
glNormal3f( 0.0f, 0.0f, 1.0f);
x_m = sector1.triangle[loop_m].vertex[0].x;
y_m = sector1.triangle[loop_m].vertex[0].y;
z_m = sector1.triangle[loop_m].vertex[0].z;
u_m = sector1.triangle[loop_m].vertex[0].u;
v_m = sector1.triangle[loop_m].vertex[0].v;
glTexCoord2f(u_m,v_m); glVertex3f(x_m,y_m,z_m);
x_m = sector1.triangle[loop_m].vertex[1].x;
y_m = sector1.triangle[loop_m].vertex[1].y;
z_m = sector1.triangle[loop_m].vertex[1].z;
u_m = sector1.triangle[loop_m].vertex[1].u;
v_m = sector1.triangle[loop_m].vertex[1].v;
glTexCoord2f(u_m,v_m); glVertex3f(x_m,y_m,z_m);
x_m = sector1.triangle[loop_m].vertex[2].x;
y_m = sector1.triangle[loop_m].vertex[2].y;
z_m = sector1.triangle[loop_m].vertex[2].z;
u_m = sector1.triangle[loop_m].vertex[2].u;
v_m = sector1.triangle[loop_m].vertex[2].v;
glTexCoord2f(u_m,v_m); glVertex3f(x_m,y_m,z_m);
glEnd();
}
return TRUE; // Everything Went OK
}
GLvoid KillGLWindow(GLvoid) // Properly Kill The Window
{
if (fullscreen) // Are We In Fullscreen Mode?
{
ChangeDisplaySettings(NULL,0); // If So Switch Back To The Desktop
ShowCursor(TRUE); // Show Mouse Pointer
}
if (hRC) // Do We Have A Rendering Context?
{
if (!wglMakeCurrent(NULL,NULL)) // Are We Able To Release The DC And RC Contexts?
{
MessageBox(NULL,"Release Of DC And RC Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
}
if (!wglDeleteContext(hRC)) // Are We Able To Delete The RC?
{
MessageBox(NULL,"Release Rendering Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
}
hRC=NULL; // Set RC To NULL
}
if (hDC && !ReleaseDC(hWnd,hDC)) // Are We Able To Release The DC
{
MessageBox(NULL,"Release Device Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
hDC=NULL; // Set DC To NULL
}
if (hWnd && !DestroyWindow(hWnd)) // Are We Able To Destroy The Window?
{
MessageBox(NULL,"Could Not Release hWnd.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
hWnd=NULL; // Set hWnd To NULL
}
if (!UnregisterClass("OpenGL",hInstance)) // Are We Able To Unregister Class
{
MessageBox(NULL,"Could Not Unregister Class.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
hInstance=NULL; // Set hInstance To NULL
}
}
/* This Code Creates Our OpenGL Window. Parameters Are: *
* title - Title To Appear At The Top Of The Window *
* width - Width Of The GL Window Or Fullscreen Mode *
* height - Height Of The GL Window Or Fullscreen Mode *
* bits - Number Of Bits To Use For Color (8/16/24/32) *
* fullscreenflag - Use Fullscreen Mode (TRUE) Or Windowed Mode (FALSE) */
BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag)
{
GLuint PixelFormat; // Holds The Results After Searching For A Match
WNDCLASS wc; // Windows Class Structure
DWORD dwExStyle; // Window Extended Style
DWORD dwStyle; // Window Style
RECT WindowRect; // Grabs Rectangle Upper Left / Lower Right Values
WindowRect.left=(long)0; // Set Left Value To 0
WindowRect.right=(long)width; // Set Right Value To Requested Width
WindowRect.top=(long)0; // Set Top Value To 0
WindowRect.bottom=(long)height; // Set Bottom Value To Requested Height
fullscreen=fullscreenflag; // Set The Global Fullscreen Flag
hInstance = GetModuleHandle(NULL); // Grab An Instance For Our Window
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Redraw On Size, And Own DC For Window.
wc.lpfnWndProc = (WNDPROC) WndProc; // WndProc Handles Messages
wc.cbClsExtra = 0; // No Extra Window Data
wc.cbWndExtra = 0; // No Extra Window Data
wc.hInstance = hInstance; // Set The Instance
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); // Load The Default Icon
wc.hCursor = LoadCursor(NULL, IDC_ARROW); // Load The Arrow Pointer
wc.hbrBackground = NULL; // No Background Required For GL
wc.lpszMenuName = NULL; // We Don't Want A Menu
wc.lpszClassName = "OpenGL"; // Set The Class Name
if (!RegisterClass(&wc)) // Attempt To Register The Window Class
{
MessageBox(NULL,"Failed To Register The Window Class.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
if (fullscreen) // Attempt Fullscreen Mode?
{
DEVMODE dmScreenSettings; // Device Mode
memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); // Makes Sure Memory's Cleared
dmScreenSettings.dmSize=sizeof(dmScreenSettings); // Size Of The Devmode Structure
dmScreenSettings.dmPelsWidth = width; // Selected Screen Width
dmScreenSettings.dmPelsHeight = height; // Selected Screen Height
dmScreenSettings.dmBitsPerPel = bits; // Selected Bits Per Pixel
dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
// Try To Set Selected Mode And Get Results. NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar.
if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
{
// If The Mode Fails, Offer Two Options. Quit Or Use Windowed Mode.
if (MessageBox(NULL,"The Requested Fullscreen Mode Is Not Supported By Your Video Card. Use Windowed Mode Instead?","NeHe GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
{
fullscreen=FALSE; // Windowed Mode Selected. Fullscreen = FALSE
}
else
{
// Pop Up A Message Box Letting User Know The Program Is Closing.
MessageBox(NULL,"Program Will Now Close.","ERROR",MB_OK|MB_ICONSTOP);
return FALSE; // Return FALSE
}
}
}
if (fullscreen) // Are We Still In Fullscreen Mode?
{
dwExStyle=WS_EX_APPWINDOW; // Window Extended Style
dwStyle=WS_POPUP; // Windows Style
ShowCursor(FALSE); // Hide Mouse Pointer
}
else
{
dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // Window Extended Style
dwStyle=WS_OVERLAPPEDWINDOW; // Windows Style
}
AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle); // Adjust Window To True Requested Size
// Create The Window
if (!(hWnd=CreateWindowEx( dwExStyle, // Extended Style For The Window
"OpenGL", // Class Name
title, // Window Title
dwStyle | // Defined Window Style
WS_CLIPSIBLINGS | // Required Window Style
WS_CLIPCHILDREN, // Required Window Style
0, 0, // Window Position
WindowRect.right-WindowRect.left, // Calculate Window Width
WindowRect.bottom-WindowRect.top, // Calculate Window Height
NULL, // No Parent Window
NULL, // No Menu
hInstance, // Instance
NULL))) // Dont Pass Anything To WM_CREATE
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Window Creation Error.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
static PIXELFORMATDESCRIPTOR pfd= // pfd Tells Windows How We Want Things To Be
{
sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
1, // Version Number
PFD_DRAW_TO_WINDOW | // Format Must Support Window
PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
PFD_DOUBLEBUFFER, // Must Support Double Buffering
PFD_TYPE_RGBA, // Request An RGBA Format
bits, // Select Our Color Depth
0, 0, 0, 0, 0, 0, // Color Bits Ignored
0, // No Alpha Buffer
0, // Shift Bit Ignored
0, // No Accumulation Buffer
0, 0, 0, 0, // Accumulation Bits Ignored
16, // 16Bit Z-Buffer (Depth Buffer)
0, // No Stencil Buffer
0, // No Auxiliary Buffer
PFD_MAIN_PLANE, // Main Drawing Layer
0, // Reserved
0, 0, 0 // Layer Masks Ignored
};
if (!(hDC=GetDC(hWnd))) // Did We Get A Device Context?
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Can't Create A GL Device Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd))) // Did Windows Find A Matching Pixel Format?
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Can't Find A Suitable PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
if(!SetPixelFormat(hDC,PixelFormat,&pfd)) // Are We Able To Set The Pixel Format?
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Can't Set The PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
if (!(hRC=wglCreateContext(hDC))) // Are We Able To Get A Rendering Context?
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Can't Create A GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
if(!wglMakeCurrent(hDC,hRC)) // Try To Activate The Rendering Context
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Can't Activate The GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
ShowWindow(hWnd,SW_SHOW); // Show The Window
SetForegroundWindow(hWnd); // Slightly Higher Priority
SetFocus(hWnd); // Sets Keyboard Focus To The Window
ReSizeGLScene(width, height); // Set Up Our Perspective GL Screen
if (!InitGL()) // Initialize Our Newly Created GL Window
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Initialization Failed.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
return TRUE; // Success
}
LRESULT CALLBACK WndProc( HWND hWnd, // Handle For This Window
UINT uMsg, // Message For This Window
WPARAM wParam, // Additional Message Information
LPARAM lParam) // Additional Message Information
{
switch (uMsg) // Check For Windows Messages
{
case WM_ACTIVATE: // Watch For Window Activate Message
{
if (!HIWORD(wParam)) // Check Minimization State
{
active=TRUE; // Program Is Active
}
else
{
active=FALSE; // Program Is No Longer Active
}
return 0; // Return To The Message Loop
}
case WM_SYSCOMMAND: // Intercept System Commands
{
switch (wParam) // Check System Calls
{
case SC_SCREENSAVE: // Screensaver Trying To Start?
case SC_MONITORPOWER: // Monitor Trying To Enter Powersave?
return 0; // Prevent From Happening
}
break; // Exit
}
case WM_CLOSE: // Did We Receive A Close Message?
{
PostQuitMessage(0); // Send A Quit Message
return 0; // Jump Back
}
case WM_KEYDOWN: // Is A Key Being Held Down?
{
keys[wParam] = TRUE; // If So, Mark It As TRUE
return 0; // Jump Back
}
case WM_KEYUP: // Has A Key Been Released?
{
keys[wParam] = FALSE; // If So, Mark It As FALSE
return 0; // Jump Back
}
case WM_SIZE: // Resize The OpenGL Window
{
ReSizeGLScene(LOWORD(lParam),HIWORD(lParam)); // LoWord=Width, HiWord=Height
return 0; // Jump Back
}
}
// Pass All Unhandled Messages To DefWindowProc
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
int WINAPI WinMain( HINSTANCE hInstance, // Instance
HINSTANCE hPrevInstance, // Previous Instance
LPSTR lpCmdLine, // Command Line Parameters
int nCmdShow) // Window Show State
{
MSG msg; // Windows Message Structure
BOOL done=FALSE; // Bool Variable To Exit Loop
// Ask The User Which Screen Mode They Prefer
if (MessageBox(NULL,"Would You Like To Run In Fullscreen Mode?", "Start FullScreen?",MB_YESNO|MB_ICONQUESTION)==IDNO)
{
fullscreen=FALSE; // Windowed Mode
}
// Create Our OpenGL Window
if (!CreateGLWindow("Lionel Brits & NeHe's 3D World Tutorial",640,480,16,fullscreen))
{
return 0; // Quit If Window Was Not Created
}
while(!done) // Loop That Runs While done=FALSE
{
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) // Is There A Message Waiting?
{
if (msg.message==WM_QUIT) // Have We Received A Quit Message?
{
done=TRUE; // If So done=TRUE
}
else // If Not, Deal With Window Messages
{
TranslateMessage(&msg); // Translate The Message
DispatchMessage(&msg); // Dispatch The Message
}
}
else // If There Are No Messages
{
// Draw The Scene. Watch For ESC Key And Quit Messages From DrawGLScene()
if ((active && !DrawGLScene()) || keys[VK_ESCAPE]) // Active? Was There A Quit Received?
{
done=TRUE; // ESC or DrawGLScene Signalled A Quit
}
else // Not Time To Quit, Update Screen
{
SwapBuffers(hDC); // Swap Buffers (Double Buffering)
if (keys['B'] && !bp)
{
bp=TRUE;
blend=!blend;
if (!blend)
{
glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
}
else
{
glEnable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
}
}
if (!keys['B'])
{
bp=FALSE;
}
if (keys['F'] && !fp)
{
fp=TRUE;
filter+=1;
if (filter>2)
{
filter=0;
}
}
if (!keys['F'])
{
fp=FALSE;
}
if (keys['R'])//Reset totation matrix
{
rot_x=rot_y=rot_z=0;
}
if (keys['T'])//Reset totation matrix
{
x=y=0;
g_z=-5;
}
if (keys[VK_F1])//pgup
{
x-=0.01f;
}
if (keys[VK_F2])
{
x+=0.01f;
}
if (keys[VK_F3])//pgup
{
y-=0.01f;
}
if (keys[VK_F4])
{
y+=0.01f;
}
if (keys[VK_F5])//pgup
{
g_z-=0.01f;
}
if (keys[VK_F6])
{
g_z+=0.01f;
}
if (keys[VK_PRIOR])//pgup
{
rot_z-=1.0f;
}
if (keys[VK_NEXT])
{
rot_z+=1.0f;
}
if (keys[VK_RIGHT])
{
rot_y -= 1.0f;
}
if (keys[VK_LEFT])
{
rot_y += 1.0f;
}
if (keys[VK_UP])
{
rot_x-= 1.0f;
}
if (keys[VK_DOWN])
{
rot_x+= 1.0f;
}
// if (keys[VK_ESCAPE]) // Is F1 Being Pressed?
// {
// keys[VK_F1]=FALSE; // If So Make Key FALSE
// KillGLWindow(); // Kill Our Current Window
// fullscreen=!fullscreen; // Toggle Fullscreen / Windowed Mode
// // Recreate Our OpenGL Window
// if (!CreateGLWindow("Lionel Brits & NeHe's 3D World Tutorial",640,480,16,fullscreen))
// {
// return 0; // Quit If Window Was Not Created
// }
// }
}
}
}
// Shutdown
KillGLWindow(); // Kill The Window
return (msg.wParam); // Exit The Program
}
}
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// initialize MFC and print and error on failure
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
cerr << _T("Fatal Error: MFC initialization failed") << endl;
nRetCode = 1;
}
else
{
// TODO: code your application's behavior here.
CString strHello;
strHello.LoadString(IDS_HELLO);
cout << (LPCTSTR)strHello << endl;
}
//Test1::main2();
Test9::WinMain(0,0,0,SW_SHOWNORMAL);
return nRetCode;
}
附上测试使用的world2.txt
0 0 0 0 1
1 0 0 0.25 1
1 0 1 0.75 1
0 0 1 1 1
0 1 0 0 0
1 1 0 0.25 0
1 1 1 0.75 0
0 1 1 1 0
NUMPTRIANGLES 8
0 1 4
4 1 5
1 2 5
2 5 6
2 3 6
3 6 7
0 3 7
0 7 4
mud.bmp