如何导出模型,请参考 Maya 部份。 现在我已经得到了一个非常简单易用的模型,下面就写一点代码把它加载到内存里,由于模型文件非常简单,所以加载非常简 单,而且不浪费内存。 如果你是 3DS Max 用户,那么在 Power VR SDK 里已经 带有相当强大的场景导出插件了,请参考相关文档及源码。
以下是头文件:
1 //
2 // @ Project : MayaMELObjectExport
3 // @ File Name : play3dObj.h
4 // @ Date : 2007-2-23
5 // @ Author : kongfu.yang
6 // @ Company : http://www.play3d.net
7 // @ Copyright : 2007-2, Example source license.
By keep this header comment,
you may use this source file in your project for non-commicial or commicial purpose.
8
9 #ifndef _GL_ES_OBJ_H__
10 #define _GL_ES_OBJ_H__
11
12 #include "gles/gl.h"
13
14 struct play3dObjFixed
15 {
16 int faceCount;
17 int vertexCount;
18 GLfixed *vertexs;
19 GLfixed *normals;
20 GLfixed *uvs;
21 unsigned short *faces;
22
23 void loadFromFile(const char * fname);
24 play3dObjFixed() { vertexs = normals = uvs = 0; faces = 0; }
25 ~play3dObjFixed() { clean(); }
26 void clean(void);
27 };
28
29
30
31 #endif // _GL_ES_OBJ_H__
以下是实现:
1 //
2 // @ Project : MayaMELObjectExport
3 // @ File Name : play3dObj.h
4 // @ Date : 2007-2-23
5 // @ Author : kongfu.yang
6 // @ Company : http://www.play3d.net
7 // @ Copyright : 2007-2, Example source license.
By keep this header comment,
you may use this source file in your project for non-commicial or commicial purpose.
8
9 #include "play3dObj.h"
10 #include <stdio.h>
11 #include <stdlib.h>
12
13 void play3dObjFixed::loadFromFile(const char * fname)
14 {
15 FILE * fp = fopen(fname, "rb");
16 fread( &faceCount, sizeof(int), 1, fp );
17 fread( &vertexCount, sizeof(int), 1, fp );
18
19 vertexs = (GLfixed *) malloc( sizeof(GLfixed) * vertexCount * 3 );
20 normals = (GLfixed *) malloc( sizeof(GLfixed) * vertexCount * 3 );
21 uvs = (GLfixed *) malloc( sizeof(GLfixed) * vertexCount * 2 );
22 faces = (unsigned short *) malloc( sizeof(unsigned short) * faceCount * 3 );
23
24 fread( vertexs, sizeof(GLfixed), vertexCount * 3, fp );
25 fread( normals, sizeof(GLfixed), vertexCount * 3, fp );
26 fread( uvs, sizeof(GLfixed), vertexCount * 2, fp );
27
28 fread( faces, sizeof(unsigned short), faceCount * 3, fp );
29
30 fclose(fp);
31 }
32
33 void play3dObjFixed::clean(void)
34 {
35 if ( vertexs != 0 ) free(vertexs);
36 if ( normals != 0 ) free(normals);
37 if ( uvs != 0 ) free(uvs);
38 if ( faces != 0 ) free(faces);
39 vertexs = normals = uvs = 0; faces = 0;
40 }
在适当的位置创建play3dObjFixed g_model并调用其loadFromFile()方法就不罗 嗦了。
以下是绘制:
万分抱歉,2007-3-1 之前这部份代码的 53 行少了"* 3",如果你直接拷过去使 用的话,会发现只能显示模型的 1/3 的面。这是因为我先后在家里的两台电脑 上改过这个程序,编写本文的台式机上的是比较老的版本,今天在做另一个例子 时才发现。看来,再简单的程序,也需要用 CVS 来管理呀。
37 void draw(HWND hWnd, HDC hdc)
38 {
39 if ( ! g_egl.isInitialized() ) return;
40
41 if ( g_egl.makeCurrent() )
42 {
43 glClear(GL_COLOR_BUFFER_BIT);
44
45 glEnableClientState( GL_VERTEX_ARRAY );
46 glEnableClientState( GL_NORMAL_ARRAY );
47 // glEnableClientState( GL_UV_ARRAY );
48 // 3 means (x,y,z) for one vertex, coord is in fixed number, stride is 0
49 glVertexPointer( 3, GL_FIXED, 0, g_model.vertexs );
50 glNormalPointer( GL_FIXED, 0, g_model.normals );
51 // glTexCoordPointer( 3, GL_FIXED, 0, g_model.uvs );
52
53 glDrawElements( GL_TRIANGLES, g_model.faceCount * 3, GL_UNSIGNED_SHORT, g_model.faces );
54
55 g_egl.swapBuffers();
56 }
57
58 reportError();
59 }
这里有三组重要的API:
glEnableClientState (...);
glVertexPointer (...);
glDrawElements (...);
glEnableClientState 是指示 OpenGL 状态机打开对 Vertex/Normal/UV Array 的支持,使得批量发送模型数据成为可能。
glVertexPointer,glNormalPointer, glTexCoordPoint 等 Pointer 则是实际用来发送模型数据的。
glDrawElements, glDrawArray 则是用利用已发送数据来绘制实际图形的,前者 通过额外的顶点索引数组来定义面,后者直接利用已经发送的模型数据数组绘制 (在HelloEGL例子里用的就是它),前者显然更加灵活。
glDrawElements 第一个参数决定绘制的图元,不过 OpenGL ES 1.x 最多画三角 形,四边形和多边形是不支持滴;第二个参数是索引元素的个数,不是面的个数; 第三个参数是顶点索引的数据类型,注意 OpenGL ES 1.x 不支持 int/unsigned int;最后是实际的数据。
当前 OpenGL ES 的书籍并不多,好在 OpenGL ES 对 OpenGL 删得多改得少,完 全可以把 OpenGL 的书籍拿来参考。以上 API 除了使用定点数之外,其它与 OpenGL 规范中的同名 API 用法完全相同,搞一本 OpenGL参考手册(Blue Book) 到手边是非常有必要的。
绘制效果:
图:PC Emulator
图:Dell Axim X51v Device