view3d

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