view3d

changeset 1:7650e941805c

forgot two files
author John Tsiombikas <nuclear@mutantstargoat.com>
date Thu, 19 Jan 2012 00:17:49 +0200
parents 182bfd9f55c7
children 9b10c8183d4e
files src/scene.c src/scene.h
diffstat 2 files changed, 270 insertions(+), 0 deletions(-) [+]
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/scene.c	Thu Jan 19 00:17:49 2012 +0200
     1.3 @@ -0,0 +1,224 @@
     1.4 +#include <stdio.h>
     1.5 +#include <stdlib.h>
     1.6 +#include <float.h>
     1.7 +
     1.8 +#include <GL/glew.h>
     1.9 +
    1.10 +#include <assimp/assimp.h>
    1.11 +#include <assimp/aiScene.h>
    1.12 +#include <assimp/aiPostProcess.h>
    1.13 +
    1.14 +#include <imago2.h>
    1.15 +
    1.16 +#include "scene.h"
    1.17 +
    1.18 +static void color(float *dest, float r, float g, float b);
    1.19 +static struct mesh *create_mesh(const struct aiScene *aiscn, struct aiMesh *aim);
    1.20 +static unsigned int create_buffer(unsigned int type, void *data, size_t sz);
    1.21 +static unsigned int load_texture(const char *fname);
    1.22 +
    1.23 +
    1.24 +int load_scene(struct scene *scn, const char *fname)
    1.25 +{
    1.26 +	int i, j;
    1.27 +	const struct aiScene *aiscn;
    1.28 +	unsigned int proc_flags = aiProcess_JoinIdenticalVertices |
    1.29 +		aiProcess_PreTransformVertices | aiProcess_Triangulate |
    1.30 +		aiProcess_GenNormals | aiProcess_SortByPType;
    1.31 +
    1.32 +	if(!(aiscn = aiImportFile(fname, proc_flags))) {
    1.33 +		fprintf(stderr, "failed to load: %s\n", fname);
    1.34 +		return -1;
    1.35 +	}
    1.36 +
    1.37 +	scn->meshes = 0;
    1.38 +	scn->lights = 0;
    1.39 +
    1.40 +	scn->bbox.min[0] = scn->bbox.min[1] = scn->bbox.min[2] = FLT_MAX;
    1.41 +	scn->bbox.max[0] = scn->bbox.max[1] = scn->bbox.max[2] = -FLT_MAX;
    1.42 +
    1.43 +	for(i=0; i<aiscn->mNumMeshes; i++) {
    1.44 +		struct mesh *m;
    1.45 +
    1.46 +		if(!(m = create_mesh(aiscn, aiscn->mMeshes[i]))) {
    1.47 +			return -1;
    1.48 +		}
    1.49 +
    1.50 +		for(j=0; j<3; j++) {
    1.51 +			if(m->bbox.min[j] < scn->bbox.min[j]) {
    1.52 +				scn->bbox.min[j] = m->bbox.min[j];
    1.53 +			}
    1.54 +			if(m->bbox.max[j] > scn->bbox.max[j]) {
    1.55 +				scn->bbox.max[j] = m->bbox.max[j];
    1.56 +			}
    1.57 +		}
    1.58 +
    1.59 +		m->next = scn->meshes;
    1.60 +		scn->meshes = m;
    1.61 +	}
    1.62 +
    1.63 +	printf("scene bounds: %.2f %.2f %.2f -> %.2f %.2f %.2f\n", scn->bbox.min[0], scn->bbox.min[1],
    1.64 +			scn->bbox.min[2], scn->bbox.max[0], scn->bbox.max[1], scn->bbox.max[2]);
    1.65 +
    1.66 +	aiReleaseImport(aiscn);
    1.67 +	return 0;
    1.68 +}
    1.69 +
    1.70 +static void color(float *dest, float r, float g, float b)
    1.71 +{
    1.72 +	dest[0] = r;
    1.73 +	dest[1] = g;
    1.74 +	dest[2] = b;
    1.75 +	dest[3] = 1.0;
    1.76 +}
    1.77 +
    1.78 +static struct mesh *create_mesh(const struct aiScene *aiscn, struct aiMesh *aim)
    1.79 +{
    1.80 +	int i, j;
    1.81 +	struct mesh *m;
    1.82 +	struct aiMaterial *mat = aiscn->mMaterials[aim->mMaterialIndex];
    1.83 +	float sstr = 1.0;
    1.84 +	unsigned int sz, *idxarr, *dptr;
    1.85 +	struct aiVector3D *vptr;
    1.86 +	struct aiString tex_name;
    1.87 +
    1.88 +	if(!(m = calloc(1, sizeof *m))) {
    1.89 +		perror("failed to allocate mesh");
    1.90 +		return 0;
    1.91 +	}
    1.92 +
    1.93 +	/* default material */
    1.94 +	color(m->mat.kd, 1, 1, 1);
    1.95 +	color(m->mat.ks, 0, 0, 0);
    1.96 +	m->mat.shin = 60.0;
    1.97 +
    1.98 +	aiGetMaterialColor(mat, AI_MATKEY_COLOR_DIFFUSE, (void*)m->mat.kd);
    1.99 +	aiGetMaterialColor(mat, AI_MATKEY_COLOR_SPECULAR, (void*)m->mat.ks);
   1.100 +	sz = 1;
   1.101 +	aiGetMaterialFloatArray(mat, AI_MATKEY_SHININESS, &m->mat.shin, &sz);
   1.102 +	sz = 1;
   1.103 +	aiGetMaterialFloatArray(mat, AI_MATKEY_SHININESS_STRENGTH, &sstr, &sz);
   1.104 +	color(m->mat.ks, m->mat.ks[0] * sstr, m->mat.ks[1] * sstr, m->mat.ks[2] * sstr);
   1.105 +
   1.106 +	if(aiGetMaterialString(mat, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0), &tex_name) == 0) {
   1.107 +		m->mat.tex = load_texture(tex_name.data);
   1.108 +	}
   1.109 +
   1.110 +	m->num_verts = aim->mNumVertices;
   1.111 +	m->num_faces = aim->mNumFaces;
   1.112 +
   1.113 +	m->bbox.min[0] = m->bbox.min[1] = m->bbox.min[2] = FLT_MAX;
   1.114 +	m->bbox.max[0] = m->bbox.max[1] = m->bbox.max[2] = -FLT_MAX;
   1.115 +
   1.116 +	vptr = aim->mVertices;
   1.117 +	for(i=0; i<m->num_verts; i++) {
   1.118 +		if(vptr->x < m->bbox.min[0]) m->bbox.min[0] = vptr->x;
   1.119 +		if(vptr->y < m->bbox.min[1]) m->bbox.min[1] = vptr->y;
   1.120 +		if(vptr->z < m->bbox.min[2]) m->bbox.min[2] = vptr->z;
   1.121 +		if(vptr->x > m->bbox.max[0]) m->bbox.max[0] = vptr->x;
   1.122 +		if(vptr->y > m->bbox.max[1]) m->bbox.max[1] = vptr->y;
   1.123 +		if(vptr->z > m->bbox.max[2]) m->bbox.max[2] = vptr->z;
   1.124 +		vptr++;
   1.125 +	}
   1.126 +
   1.127 +	m->vert_buf = create_buffer(GL_ARRAY_BUFFER, aim->mVertices, m->num_verts * sizeof *aim->mVertices);
   1.128 +	if(aim->mNormals) {
   1.129 +		m->norm_buf = create_buffer(GL_ARRAY_BUFFER, aim->mNormals, m->num_verts * sizeof *aim->mNormals);
   1.130 +	}
   1.131 +	if(aim->mTextureCoords) {
   1.132 +		m->tex_buf = create_buffer(GL_ARRAY_BUFFER, aim->mTextureCoords, m->num_verts * sizeof *aim->mTextureCoords);
   1.133 +	}
   1.134 +
   1.135 +	/* indices are scattered all over the fucking place... map the buffer and collect them there directly */
   1.136 +	m->idx_buf = create_buffer(GL_ELEMENT_ARRAY_BUFFER, 0, m->num_faces * 3 * sizeof *aim->mFaces[0].mIndices);
   1.137 +	dptr = idxarr = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY);
   1.138 +
   1.139 +	for(i=0; i<m->num_faces; i++) {
   1.140 +		for(j=0; j<3; j++) {
   1.141 +			*dptr++ = aim->mFaces[i].mIndices[j];
   1.142 +		}
   1.143 +	}
   1.144 +	glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
   1.145 +	return m;
   1.146 +}
   1.147 +
   1.148 +static unsigned int create_buffer(unsigned int type, void *data, size_t sz)
   1.149 +{
   1.150 +	unsigned int vbo;
   1.151 +	glGenBuffers(1, &vbo);
   1.152 +	glBindBuffer(type, vbo);
   1.153 +	glBufferData(type, sz, data, GL_STATIC_DRAW);
   1.154 +	return vbo;
   1.155 +}
   1.156 +
   1.157 +static unsigned int load_texture(const char *fname)
   1.158 +{
   1.159 +	unsigned int tex;
   1.160 +	void *pixels;
   1.161 +	int xsz, ysz;
   1.162 +
   1.163 +	if(!(pixels = img_load_pixels(fname, &xsz, &ysz, IMG_FMT_RGBA32))) {
   1.164 +		fprintf(stderr, "failed to load image: %s\n", fname);
   1.165 +		return 0;
   1.166 +	}
   1.167 +
   1.168 +	glGenTextures(1, &tex);
   1.169 +	glBindTexture(GL_TEXTURE_2D, tex);
   1.170 +	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   1.171 +	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
   1.172 +	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
   1.173 +	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
   1.174 +	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, xsz, ysz, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
   1.175 +
   1.176 +	img_free_pixels(pixels);
   1.177 +	return tex;
   1.178 +}
   1.179 +
   1.180 +void render_scene(struct scene *scn)
   1.181 +{
   1.182 +	struct mesh *m = scn->meshes;
   1.183 +	while(m) {
   1.184 +		render_mesh(m);
   1.185 +		m = m->next;
   1.186 +	}
   1.187 +}
   1.188 +
   1.189 +void render_mesh(struct mesh *m)
   1.190 +{
   1.191 +	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, m->mat.kd);
   1.192 +	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, m->mat.ks);
   1.193 +	glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, m->mat.shin);
   1.194 +
   1.195 +	if(m->mat.tex) {
   1.196 +		glEnable(GL_TEXTURE_2D);
   1.197 +		glBindTexture(GL_TEXTURE_2D, m->mat.tex);
   1.198 +	}
   1.199 +
   1.200 +	/* TODO texture */
   1.201 +
   1.202 +	glBindBuffer(GL_ARRAY_BUFFER, m->vert_buf);
   1.203 +	glVertexPointer(3, GL_FLOAT, 0, 0);
   1.204 +	glEnableClientState(GL_VERTEX_ARRAY);
   1.205 +
   1.206 +	if(m->norm_buf) {
   1.207 +		glBindBuffer(GL_ARRAY_BUFFER, m->norm_buf);
   1.208 +		glNormalPointer(GL_FLOAT, 0, 0);
   1.209 +		glEnableClientState(GL_NORMAL_ARRAY);
   1.210 +	}
   1.211 +	if(m->tex_buf) {
   1.212 +		glBindBuffer(GL_ARRAY_BUFFER, m->tex_buf);
   1.213 +		glTexCoordPointer(3, GL_FLOAT, 0, 0);
   1.214 +		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
   1.215 +	}
   1.216 +
   1.217 +	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m->idx_buf);
   1.218 +	glDrawElements(GL_TRIANGLES, m->num_faces * 3, GL_UNSIGNED_INT, 0);
   1.219 +
   1.220 +	glDisableClientState(GL_VERTEX_ARRAY);
   1.221 +	glDisableClientState(GL_NORMAL_ARRAY);
   1.222 +	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
   1.223 +
   1.224 +	if(m->mat.tex) {
   1.225 +		glDisable(GL_TEXTURE_2D);
   1.226 +	}
   1.227 +}
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/src/scene.h	Thu Jan 19 00:17:49 2012 +0200
     2.3 @@ -0,0 +1,46 @@
     2.4 +#ifndef SCENE_H_
     2.5 +#define SCENE_H_
     2.6 +
     2.7 +struct aabb {
     2.8 +	float min[3], max[3];
     2.9 +};
    2.10 +
    2.11 +struct material {
    2.12 +	float kd[4];
    2.13 +	float ks[4];
    2.14 +	float shin;
    2.15 +	unsigned int tex;
    2.16 +};
    2.17 +
    2.18 +struct mesh {
    2.19 +	unsigned int vert_buf, norm_buf, tex_buf, idx_buf;
    2.20 +	int num_verts, num_faces;
    2.21 +
    2.22 +	struct material mat;
    2.23 +
    2.24 +	struct aabb bbox;
    2.25 +
    2.26 +	struct mesh *next;
    2.27 +};
    2.28 +
    2.29 +struct light {
    2.30 +	float pos[4];
    2.31 +	float color[4];
    2.32 +
    2.33 +	struct light *next;
    2.34 +};
    2.35 +
    2.36 +struct scene {
    2.37 +	struct mesh *meshes;
    2.38 +	struct light *lights;
    2.39 +
    2.40 +	struct aabb bbox;
    2.41 +};
    2.42 +
    2.43 +
    2.44 +int load_scene(struct scene *scn, const char *fname);
    2.45 +
    2.46 +void render_scene(struct scene *scn);
    2.47 +void render_mesh(struct mesh *m);
    2.48 +
    2.49 +#endif	/* SCENE_H_ */