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