rev |
line source |
nuclear@19
|
1 #include <stdio.h>
|
nuclear@19
|
2 #include <stdlib.h>
|
nuclear@19
|
3 #include <assert.h>
|
nuclear@19
|
4 #ifndef __APPLE__
|
nuclear@19
|
5 #include <GL/glut.h>
|
nuclear@19
|
6 #else
|
nuclear@19
|
7 #include <GLUT/glut.h>
|
nuclear@19
|
8 #endif
|
nuclear@19
|
9 #include "goat3d.h"
|
nuclear@19
|
10
|
nuclear@19
|
11 static void cleanup(void);
|
nuclear@19
|
12 static void disp(void);
|
nuclear@19
|
13 static void draw_scene(struct goat3d *g);
|
nuclear@19
|
14 static void draw_mesh(struct goat3d_mesh *mesh);
|
nuclear@19
|
15 static void reshape(int x, int y);
|
nuclear@19
|
16 static void keyb(unsigned char key, int x, int y);
|
nuclear@19
|
17 static void mouse(int bn, int st, int x, int y);
|
nuclear@19
|
18 static void motion(int x, int y);
|
nuclear@19
|
19
|
nuclear@19
|
20 static struct goat3d *goat;
|
nuclear@19
|
21 static float cam_theta, cam_phi, cam_dist = 10;
|
nuclear@19
|
22
|
nuclear@19
|
23 int main(int argc, char **argv)
|
nuclear@19
|
24 {
|
nuclear@46
|
25 int i, nmeshes;
|
nuclear@46
|
26
|
nuclear@19
|
27 glutInitWindowSize(800, 600);
|
nuclear@19
|
28 glutInit(&argc, argv);
|
nuclear@19
|
29
|
nuclear@19
|
30 if(!argv[1]) {
|
nuclear@19
|
31 fprintf(stderr, "you must specify a goat3d scene file to open\n");
|
nuclear@19
|
32 return 1;
|
nuclear@19
|
33 }
|
nuclear@19
|
34
|
nuclear@19
|
35 if(!(goat = goat3d_create())) {
|
nuclear@19
|
36 fprintf(stderr, "failed to create goat3d\n");
|
nuclear@19
|
37 return 1;
|
nuclear@19
|
38 }
|
nuclear@19
|
39 if(goat3d_load(goat, argv[1]) == -1) {
|
nuclear@19
|
40 fprintf(stderr, "failed to load goat3d scene: %s\n", argv[1]);
|
nuclear@19
|
41 goat3d_free(goat);
|
nuclear@19
|
42 return 1;
|
nuclear@19
|
43 }
|
nuclear@19
|
44
|
nuclear@46
|
45 nmeshes = goat3d_get_mesh_count(goat);
|
nuclear@46
|
46 printf("loaded %d meshes\n", nmeshes);
|
nuclear@46
|
47 for(i=0; i<nmeshes; i++) {
|
nuclear@46
|
48 struct goat3d_mesh *m = goat3d_get_mesh(goat, i);
|
nuclear@46
|
49
|
nuclear@46
|
50 printf("- mesh[%d]: %s (%d verts, %d faces)\n", i, goat3d_get_mesh_name(m),
|
nuclear@46
|
51 goat3d_get_mesh_attrib_count(m, GOAT3D_MESH_ATTR_VERTEX),
|
nuclear@46
|
52 goat3d_get_mesh_face_count(m));
|
nuclear@46
|
53 }
|
nuclear@46
|
54
|
nuclear@19
|
55 glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
|
nuclear@19
|
56 glutCreateWindow(argv[1]);
|
nuclear@19
|
57
|
nuclear@19
|
58 glutDisplayFunc(disp);
|
nuclear@19
|
59 glutReshapeFunc(reshape);
|
nuclear@19
|
60 glutKeyboardFunc(keyb);
|
nuclear@19
|
61 glutMouseFunc(mouse);
|
nuclear@19
|
62 glutMotionFunc(motion);
|
nuclear@19
|
63
|
nuclear@19
|
64 glEnable(GL_DEPTH_TEST);
|
nuclear@19
|
65 glEnable(GL_CULL_FACE);
|
nuclear@19
|
66 glEnable(GL_LIGHTING);
|
nuclear@19
|
67 glEnable(GL_LIGHT0);
|
nuclear@19
|
68
|
nuclear@19
|
69 glClearColor(0.1, 0.1, 0.1, 1.0);
|
nuclear@19
|
70
|
nuclear@19
|
71 atexit(cleanup);
|
nuclear@19
|
72
|
nuclear@19
|
73 glutMainLoop();
|
nuclear@19
|
74 return 0;
|
nuclear@19
|
75 }
|
nuclear@19
|
76
|
nuclear@19
|
77 static void cleanup(void)
|
nuclear@19
|
78 {
|
nuclear@19
|
79 goat3d_free(goat);
|
nuclear@19
|
80 }
|
nuclear@19
|
81
|
nuclear@19
|
82 static void disp(void)
|
nuclear@19
|
83 {
|
nuclear@19
|
84 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
nuclear@19
|
85
|
nuclear@19
|
86 glMatrixMode(GL_MODELVIEW);
|
nuclear@19
|
87 glLoadIdentity();
|
nuclear@19
|
88 glTranslatef(0, 0, -cam_dist);
|
nuclear@19
|
89 glRotatef(cam_phi, 1, 0, 0);
|
nuclear@19
|
90 glRotatef(cam_theta, 0, 1, 0);
|
nuclear@19
|
91
|
nuclear@19
|
92 draw_scene(goat);
|
nuclear@19
|
93
|
nuclear@19
|
94 glutSwapBuffers();
|
nuclear@19
|
95 assert(glGetError() == GL_NO_ERROR);
|
nuclear@19
|
96 }
|
nuclear@19
|
97
|
nuclear@19
|
98 static void draw_scene(struct goat3d *g)
|
nuclear@19
|
99 {
|
nuclear@19
|
100 int i, num_meshes;
|
nuclear@19
|
101
|
nuclear@19
|
102 num_meshes = goat3d_get_mesh_count(g);
|
nuclear@19
|
103 for(i=0; i<num_meshes; i++) {
|
nuclear@19
|
104 struct goat3d_mesh *mesh = goat3d_get_mesh(g, i);
|
nuclear@19
|
105 draw_mesh(mesh);
|
nuclear@19
|
106 }
|
nuclear@19
|
107 }
|
nuclear@19
|
108
|
nuclear@19
|
109 static void draw_mesh(struct goat3d_mesh *mesh)
|
nuclear@19
|
110 {
|
nuclear@19
|
111 int vnum, fnum;
|
nuclear@19
|
112 struct goat3d_material *mtl;
|
nuclear@19
|
113 float *verts, *normals, *texcoords;
|
nuclear@19
|
114 int *vidx;
|
nuclear@19
|
115
|
nuclear@19
|
116 if((mtl = goat3d_get_mesh_mtl(mesh))) {
|
nuclear@20
|
117 float white[] = {1, 1, 1, 1};
|
nuclear@20
|
118 float black[] = {0, 0, 0, 0};
|
nuclear@20
|
119 float zero = 0.0;
|
nuclear@20
|
120 const float *diffuse, *specular, *shininess;
|
nuclear@20
|
121
|
nuclear@20
|
122 if(!(diffuse = goat3d_get_mtl_attrib(mtl, GOAT3D_MAT_ATTR_DIFFUSE))) {
|
nuclear@20
|
123 diffuse = white;
|
nuclear@20
|
124 }
|
nuclear@20
|
125 if(!(specular = goat3d_get_mtl_attrib(mtl, GOAT3D_MAT_ATTR_SPECULAR))) {
|
nuclear@20
|
126 specular = black;
|
nuclear@20
|
127 }
|
nuclear@20
|
128 if(!(shininess = goat3d_get_mtl_attrib(mtl, GOAT3D_MAT_ATTR_SHININESS))) {
|
nuclear@20
|
129 shininess = &zero;
|
nuclear@20
|
130 }
|
nuclear@20
|
131
|
nuclear@20
|
132 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, diffuse);
|
nuclear@20
|
133 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular);
|
nuclear@20
|
134 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, *shininess);
|
nuclear@19
|
135 }
|
nuclear@19
|
136
|
nuclear@19
|
137 vnum = goat3d_get_mesh_attrib_count(mesh, GOAT3D_MESH_ATTR_VERTEX);
|
nuclear@19
|
138 fnum = goat3d_get_mesh_face_count(mesh);
|
nuclear@19
|
139
|
nuclear@19
|
140 if(!vnum || !fnum) {
|
nuclear@19
|
141 return;
|
nuclear@19
|
142 }
|
nuclear@19
|
143
|
nuclear@19
|
144 verts = goat3d_get_mesh_attribs(mesh, GOAT3D_MESH_ATTR_VERTEX);
|
nuclear@19
|
145 normals = goat3d_get_mesh_attribs(mesh, GOAT3D_MESH_ATTR_NORMAL);
|
nuclear@19
|
146 texcoords = goat3d_get_mesh_attribs(mesh, GOAT3D_MESH_ATTR_TEXCOORD);
|
nuclear@19
|
147 vidx = goat3d_get_mesh_faces(mesh);
|
nuclear@19
|
148
|
nuclear@19
|
149 glEnableClientState(GL_VERTEX_ARRAY);
|
nuclear@19
|
150 glVertexPointer(3, GL_FLOAT, 0, verts);
|
nuclear@19
|
151
|
nuclear@19
|
152 if(normals) {
|
nuclear@19
|
153 glEnableClientState(GL_NORMAL_ARRAY);
|
nuclear@19
|
154 glNormalPointer(GL_FLOAT, 0, normals);
|
nuclear@19
|
155 }
|
nuclear@19
|
156 if(texcoords) {
|
nuclear@19
|
157 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
nuclear@19
|
158 glTexCoordPointer(2, GL_FLOAT, 0, texcoords);
|
nuclear@19
|
159 }
|
nuclear@19
|
160
|
nuclear@19
|
161 glDrawElements(GL_TRIANGLES, fnum * 3, GL_UNSIGNED_INT, vidx);
|
nuclear@19
|
162
|
nuclear@19
|
163 glDisableClientState(GL_VERTEX_ARRAY);
|
nuclear@19
|
164 if(normals) {
|
nuclear@19
|
165 glDisableClientState(GL_NORMAL_ARRAY);
|
nuclear@19
|
166 }
|
nuclear@19
|
167 if(texcoords) {
|
nuclear@19
|
168 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
nuclear@19
|
169 }
|
nuclear@19
|
170 }
|
nuclear@19
|
171
|
nuclear@19
|
172 static void reshape(int x, int y)
|
nuclear@19
|
173 {
|
nuclear@19
|
174 glViewport(0, 0, x, y);
|
nuclear@19
|
175
|
nuclear@19
|
176 glMatrixMode(GL_PROJECTION);
|
nuclear@19
|
177 glLoadIdentity();
|
nuclear@19
|
178 gluPerspective(50.0, (float)x / (float)y, 0.5, 1000.0);
|
nuclear@19
|
179 }
|
nuclear@19
|
180
|
nuclear@19
|
181 static void keyb(unsigned char key, int x, int y)
|
nuclear@19
|
182 {
|
nuclear@19
|
183 switch(key) {
|
nuclear@19
|
184 case 27:
|
nuclear@19
|
185 exit(0);
|
nuclear@19
|
186 }
|
nuclear@19
|
187 }
|
nuclear@19
|
188
|
nuclear@19
|
189 static int bnstate[32];
|
nuclear@19
|
190 static int prev_x, prev_y;
|
nuclear@19
|
191
|
nuclear@19
|
192 static void mouse(int bn, int st, int x, int y)
|
nuclear@19
|
193 {
|
nuclear@19
|
194 bnstate[bn - GLUT_LEFT_BUTTON] = (st == GLUT_DOWN);
|
nuclear@19
|
195 prev_x = x;
|
nuclear@19
|
196 prev_y = y;
|
nuclear@19
|
197 }
|
nuclear@19
|
198
|
nuclear@19
|
199 static void motion(int x, int y)
|
nuclear@19
|
200 {
|
nuclear@19
|
201 int dx = x - prev_x;
|
nuclear@19
|
202 int dy = y - prev_y;
|
nuclear@19
|
203 prev_x = x;
|
nuclear@19
|
204 prev_y = y;
|
nuclear@19
|
205
|
nuclear@19
|
206 if(bnstate[0]) {
|
nuclear@19
|
207 cam_theta += dx * 0.5;
|
nuclear@19
|
208 cam_phi += dy * 0.5;
|
nuclear@19
|
209
|
nuclear@19
|
210 if(cam_phi < -90) cam_phi = -90;
|
nuclear@19
|
211 if(cam_phi > 90) cam_phi = 90;
|
nuclear@19
|
212 glutPostRedisplay();
|
nuclear@19
|
213 }
|
nuclear@19
|
214 if(bnstate[2]) {
|
nuclear@19
|
215 cam_dist += dy * 0.1;
|
nuclear@19
|
216
|
nuclear@19
|
217 if(cam_dist < 0) cam_dist = 0;
|
nuclear@19
|
218 glutPostRedisplay();
|
nuclear@19
|
219 }
|
nuclear@19
|
220 }
|