view3d
view src/scene.c @ 1:7650e941805c
forgot two files
author | John Tsiombikas <nuclear@mutantstargoat.com> |
---|---|
date | Thu, 19 Jan 2012 00:17:49 +0200 |
parents | |
children | 9b10c8183d4e |
line source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <float.h>
5 #include <GL/glew.h>
7 #include <assimp/assimp.h>
8 #include <assimp/aiScene.h>
9 #include <assimp/aiPostProcess.h>
11 #include <imago2.h>
13 #include "scene.h"
15 static void color(float *dest, float r, float g, float b);
16 static struct mesh *create_mesh(const struct aiScene *aiscn, struct aiMesh *aim);
17 static unsigned int create_buffer(unsigned int type, void *data, size_t sz);
18 static unsigned int load_texture(const char *fname);
21 int load_scene(struct scene *scn, const char *fname)
22 {
23 int i, j;
24 const struct aiScene *aiscn;
25 unsigned int proc_flags = aiProcess_JoinIdenticalVertices |
26 aiProcess_PreTransformVertices | aiProcess_Triangulate |
27 aiProcess_GenNormals | aiProcess_SortByPType;
29 if(!(aiscn = aiImportFile(fname, proc_flags))) {
30 fprintf(stderr, "failed to load: %s\n", fname);
31 return -1;
32 }
34 scn->meshes = 0;
35 scn->lights = 0;
37 scn->bbox.min[0] = scn->bbox.min[1] = scn->bbox.min[2] = FLT_MAX;
38 scn->bbox.max[0] = scn->bbox.max[1] = scn->bbox.max[2] = -FLT_MAX;
40 for(i=0; i<aiscn->mNumMeshes; i++) {
41 struct mesh *m;
43 if(!(m = create_mesh(aiscn, aiscn->mMeshes[i]))) {
44 return -1;
45 }
47 for(j=0; j<3; j++) {
48 if(m->bbox.min[j] < scn->bbox.min[j]) {
49 scn->bbox.min[j] = m->bbox.min[j];
50 }
51 if(m->bbox.max[j] > scn->bbox.max[j]) {
52 scn->bbox.max[j] = m->bbox.max[j];
53 }
54 }
56 m->next = scn->meshes;
57 scn->meshes = m;
58 }
60 printf("scene bounds: %.2f %.2f %.2f -> %.2f %.2f %.2f\n", scn->bbox.min[0], scn->bbox.min[1],
61 scn->bbox.min[2], scn->bbox.max[0], scn->bbox.max[1], scn->bbox.max[2]);
63 aiReleaseImport(aiscn);
64 return 0;
65 }
67 static void color(float *dest, float r, float g, float b)
68 {
69 dest[0] = r;
70 dest[1] = g;
71 dest[2] = b;
72 dest[3] = 1.0;
73 }
75 static struct mesh *create_mesh(const struct aiScene *aiscn, struct aiMesh *aim)
76 {
77 int i, j;
78 struct mesh *m;
79 struct aiMaterial *mat = aiscn->mMaterials[aim->mMaterialIndex];
80 float sstr = 1.0;
81 unsigned int sz, *idxarr, *dptr;
82 struct aiVector3D *vptr;
83 struct aiString tex_name;
85 if(!(m = calloc(1, sizeof *m))) {
86 perror("failed to allocate mesh");
87 return 0;
88 }
90 /* default material */
91 color(m->mat.kd, 1, 1, 1);
92 color(m->mat.ks, 0, 0, 0);
93 m->mat.shin = 60.0;
95 aiGetMaterialColor(mat, AI_MATKEY_COLOR_DIFFUSE, (void*)m->mat.kd);
96 aiGetMaterialColor(mat, AI_MATKEY_COLOR_SPECULAR, (void*)m->mat.ks);
97 sz = 1;
98 aiGetMaterialFloatArray(mat, AI_MATKEY_SHININESS, &m->mat.shin, &sz);
99 sz = 1;
100 aiGetMaterialFloatArray(mat, AI_MATKEY_SHININESS_STRENGTH, &sstr, &sz);
101 color(m->mat.ks, m->mat.ks[0] * sstr, m->mat.ks[1] * sstr, m->mat.ks[2] * sstr);
103 if(aiGetMaterialString(mat, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0), &tex_name) == 0) {
104 m->mat.tex = load_texture(tex_name.data);
105 }
107 m->num_verts = aim->mNumVertices;
108 m->num_faces = aim->mNumFaces;
110 m->bbox.min[0] = m->bbox.min[1] = m->bbox.min[2] = FLT_MAX;
111 m->bbox.max[0] = m->bbox.max[1] = m->bbox.max[2] = -FLT_MAX;
113 vptr = aim->mVertices;
114 for(i=0; i<m->num_verts; i++) {
115 if(vptr->x < m->bbox.min[0]) m->bbox.min[0] = vptr->x;
116 if(vptr->y < m->bbox.min[1]) m->bbox.min[1] = vptr->y;
117 if(vptr->z < m->bbox.min[2]) m->bbox.min[2] = vptr->z;
118 if(vptr->x > m->bbox.max[0]) m->bbox.max[0] = vptr->x;
119 if(vptr->y > m->bbox.max[1]) m->bbox.max[1] = vptr->y;
120 if(vptr->z > m->bbox.max[2]) m->bbox.max[2] = vptr->z;
121 vptr++;
122 }
124 m->vert_buf = create_buffer(GL_ARRAY_BUFFER, aim->mVertices, m->num_verts * sizeof *aim->mVertices);
125 if(aim->mNormals) {
126 m->norm_buf = create_buffer(GL_ARRAY_BUFFER, aim->mNormals, m->num_verts * sizeof *aim->mNormals);
127 }
128 if(aim->mTextureCoords) {
129 m->tex_buf = create_buffer(GL_ARRAY_BUFFER, aim->mTextureCoords, m->num_verts * sizeof *aim->mTextureCoords);
130 }
132 /* indices are scattered all over the fucking place... map the buffer and collect them there directly */
133 m->idx_buf = create_buffer(GL_ELEMENT_ARRAY_BUFFER, 0, m->num_faces * 3 * sizeof *aim->mFaces[0].mIndices);
134 dptr = idxarr = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY);
136 for(i=0; i<m->num_faces; i++) {
137 for(j=0; j<3; j++) {
138 *dptr++ = aim->mFaces[i].mIndices[j];
139 }
140 }
141 glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
142 return m;
143 }
145 static unsigned int create_buffer(unsigned int type, void *data, size_t sz)
146 {
147 unsigned int vbo;
148 glGenBuffers(1, &vbo);
149 glBindBuffer(type, vbo);
150 glBufferData(type, sz, data, GL_STATIC_DRAW);
151 return vbo;
152 }
154 static unsigned int load_texture(const char *fname)
155 {
156 unsigned int tex;
157 void *pixels;
158 int xsz, ysz;
160 if(!(pixels = img_load_pixels(fname, &xsz, &ysz, IMG_FMT_RGBA32))) {
161 fprintf(stderr, "failed to load image: %s\n", fname);
162 return 0;
163 }
165 glGenTextures(1, &tex);
166 glBindTexture(GL_TEXTURE_2D, tex);
167 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
168 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
169 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
170 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
171 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, xsz, ysz, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
173 img_free_pixels(pixels);
174 return tex;
175 }
177 void render_scene(struct scene *scn)
178 {
179 struct mesh *m = scn->meshes;
180 while(m) {
181 render_mesh(m);
182 m = m->next;
183 }
184 }
186 void render_mesh(struct mesh *m)
187 {
188 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, m->mat.kd);
189 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, m->mat.ks);
190 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, m->mat.shin);
192 if(m->mat.tex) {
193 glEnable(GL_TEXTURE_2D);
194 glBindTexture(GL_TEXTURE_2D, m->mat.tex);
195 }
197 /* TODO texture */
199 glBindBuffer(GL_ARRAY_BUFFER, m->vert_buf);
200 glVertexPointer(3, GL_FLOAT, 0, 0);
201 glEnableClientState(GL_VERTEX_ARRAY);
203 if(m->norm_buf) {
204 glBindBuffer(GL_ARRAY_BUFFER, m->norm_buf);
205 glNormalPointer(GL_FLOAT, 0, 0);
206 glEnableClientState(GL_NORMAL_ARRAY);
207 }
208 if(m->tex_buf) {
209 glBindBuffer(GL_ARRAY_BUFFER, m->tex_buf);
210 glTexCoordPointer(3, GL_FLOAT, 0, 0);
211 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
212 }
214 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m->idx_buf);
215 glDrawElements(GL_TRIANGLES, m->num_faces * 3, GL_UNSIGNED_INT, 0);
217 glDisableClientState(GL_VERTEX_ARRAY);
218 glDisableClientState(GL_NORMAL_ARRAY);
219 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
221 if(m->mat.tex) {
222 glDisable(GL_TEXTURE_2D);
223 }
224 }