erebus

changeset 19:6204e4d3f445

scene loading
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 27 May 2014 07:43:55 +0300
parents 09028848f276
children ea95b62dbc87
files README.md liberebus/src/erebus.cc liberebus/src/scene.cc liberebus/src/scene.h src/main.cc test/scene
diffstat 6 files changed, 265 insertions(+), 34 deletions(-) [+]
line diff
     1.1 --- a/README.md	Mon May 26 23:34:12 2014 +0300
     1.2 +++ b/README.md	Tue May 27 07:43:55 2014 +0300
     1.3 @@ -4,7 +4,7 @@
     1.4  Copyright (C) 2014  John Tsiombikas <nuclear@member.fsf.org>
     1.5  
     1.6  This program is released as free software, under the terms of the GNU General
     1.7 -Public License v3, or at your option any later version, published by the Free
     1.8 +Public License v3, or at your option, any later version published by the Free
     1.9  Software Foundation.
    1.10  
    1.11  **This program is in a very early stage of development. Don't bother trying it.**
     2.1 --- a/liberebus/src/erebus.cc	Mon May 26 23:34:12 2014 +0300
     2.2 +++ b/liberebus/src/erebus.cc	Tue May 27 07:43:55 2014 +0300
     2.3 @@ -203,33 +203,9 @@
     2.4  	delete ctx->scn;
     2.5  	ctx->scn = new Scene;
     2.6  
     2.7 -	// XXX for now just create a test scene here
     2.8 -	Sphere *sph = new Sphere;
     2.9 -	sph->mtl.set_attrib("diffuse", Color(1.0, 0.3, 0.2));
    2.10 -	SceneNode *sph_node = new SceneNode(sph);
    2.11 -	ctx->scn->add_object(sph);
    2.12 -	ctx->scn->add_node(sph_node);
    2.13 -
    2.14 -	Box *box = new Box;
    2.15 -	box->mtl.set_attrib("diffuse", Color(0.9, 0.8, 0.75));
    2.16 -	SceneNode *box_node = new SceneNode(box);
    2.17 -	box_node->set_position(Vector3(0, -1.25, 0));
    2.18 -	box_node->set_scaling(Vector3(5, 0.5, 5));
    2.19 -	ctx->scn->add_object(box);
    2.20 -	ctx->scn->add_node(box_node);
    2.21 -
    2.22 -	Sphere *lt = new Sphere;
    2.23 -	lt->mtl.set_attrib("emissive", Color(10, 10, 10));
    2.24 -	SceneNode *lt_node = new SceneNode(lt);
    2.25 -	lt_node->set_position(Vector3(-15, 15, -10));
    2.26 -	lt_node->set_scaling(Vector3(8, 8, 8));
    2.27 -	ctx->scn->add_object(lt);
    2.28 -	ctx->scn->add_node(lt_node);
    2.29 -
    2.30 -	TargetCamera *cam = new TargetCamera(Vector3(0, 4, -8), Vector3(0, 0, 0));
    2.31 -	//ctx->scn->add_object(cam);
    2.32 -	ctx->scn->use_camera(cam);
    2.33 -
    2.34 +	if(!ctx->scn->load(fname)) {
    2.35 +		return -1;
    2.36 +	}
    2.37  	return 0;
    2.38  }
    2.39  
    2.40 @@ -317,8 +293,8 @@
    2.41  			Vector3 cpos = cam->get_position();
    2.42  			float mag = cpos.length();
    2.43  
    2.44 -			float theta = atan2(cpos.z / mag, cpos.x / mag) + DEG_TO_RAD(dx * 0.5);
    2.45 -			float phi = acos(cpos.y / mag) + DEG_TO_RAD(dy * 0.5);
    2.46 +			float theta = atan2(cpos.z / mag, cpos.x / mag) - DEG_TO_RAD(dx * 0.5);
    2.47 +			float phi = acos(cpos.y / mag) - DEG_TO_RAD(dy * 0.5);
    2.48  
    2.49  			if(phi < 0) phi = 0;
    2.50  			if(phi > M_PI) phi = M_PI;
     3.1 --- a/liberebus/src/scene.cc	Mon May 26 23:34:12 2014 +0300
     3.2 +++ b/liberebus/src/scene.cc	Tue May 27 07:43:55 2014 +0300
     3.3 @@ -1,8 +1,14 @@
     3.4 +#include <stdio.h>
     3.5 +#include <stdlib.h>
     3.6 +#include <string.h>
     3.7  #include "scene.h"
     3.8 +#include "snode.h"
     3.9 +#include "object.h"
    3.10 +#include "geomobj.h"
    3.11  
    3.12  // default enviromental parameters
    3.13  Environment::Environment()
    3.14 -	: bgcolor(0.05, 0.05, 0.05), ambient(0.05, 0.05, 0.05)
    3.15 +	: bgcolor(0.01, 0.01, 0.01), ambient(0.01, 0.01, 0.01)
    3.16  {
    3.17  }
    3.18  
    3.19 @@ -105,5 +111,232 @@
    3.20  
    3.21  bool Scene::load(const char *fname)
    3.22  {
    3.23 -	return false;	// TODO
    3.24 +	FILE *fp = fopen(fname, "r");
    3.25 +	if(!fp) {
    3.26 +		fprintf(stderr, "failed to open scene file: %s\n", fname);
    3.27 +		return false;
    3.28 +	}
    3.29 +
    3.30 +	bool res = load(fp);
    3.31 +	fclose(fp);
    3.32 +	return res;
    3.33  }
    3.34 +
    3.35 +static char *strip_wspace(char *str)
    3.36 +{
    3.37 +	while(*str && isspace(*str)) str++;
    3.38 +	return str;
    3.39 +}
    3.40 +
    3.41 +bool Scene::load(FILE *fp)
    3.42 +{
    3.43 +	char buf[256];
    3.44 +
    3.45 +	while(fgets(buf, sizeof buf, fp)) {
    3.46 +		char *line = strip_wspace(buf);
    3.47 +		if(!line || !*line || *line == '#') {
    3.48 +			continue;
    3.49 +		}
    3.50 +
    3.51 +		std::vector<char*> cmd;
    3.52 +
    3.53 +		char *tok = 0;
    3.54 +		while((tok = strtok(tok ? 0 : line, " \t\v\n\r"))) {
    3.55 +			printf("token: %s\n", tok);
    3.56 +			cmd.push_back(tok);
    3.57 +		}
    3.58 +		cmd.push_back(0);
    3.59 +
    3.60 +
    3.61 +		if(!proc_cmd((int)cmd.size() - 1, &cmd[0])) {
    3.62 +			return false;
    3.63 +		}
    3.64 +	}
    3.65 +
    3.66 +	return true;
    3.67 +}
    3.68 +
    3.69 +static int parse_vec(char **argv, float *vec)
    3.70 +{
    3.71 +	int nelem = 0;
    3.72 +	char *endp;
    3.73 +
    3.74 +	for(int i=0; i<4; i++) {
    3.75 +		if(!argv[i]) break;
    3.76 +
    3.77 +		vec[nelem] = strtod(argv[i], &endp);
    3.78 +		if(endp == argv[i]) {
    3.79 +			break;
    3.80 +		}
    3.81 +		nelem++;
    3.82 +	}
    3.83 +	return nelem;
    3.84 +}
    3.85 +
    3.86 +static SceneNode *proc_object(Object *obj, int argc, char **argv)
    3.87 +{
    3.88 +	float vec[4];
    3.89 +	SceneNode *node = new SceneNode(obj);
    3.90 +	GeomObject *gobj = (GeomObject*)obj;
    3.91 +
    3.92 +	for(int i=1; i<argc; i++) {
    3.93 +		if(strcmp(argv[i], "-position") == 0) {
    3.94 +			int nelem = parse_vec(argv + i + 1, vec);
    3.95 +			if(nelem < 3) {
    3.96 +				fprintf(stderr, "-position must be followed by 3 numbers\n");
    3.97 +				goto err;
    3.98 +			}
    3.99 +			node->set_position(Vector3(vec[0], vec[1], vec[2]));
   3.100 +			i += 3;
   3.101 +
   3.102 +		} else if(strcmp(argv[i], "-rotation") == 0) {
   3.103 +			int nelem = parse_vec(argv + i + 1, vec);
   3.104 +			if(nelem < 4) {
   3.105 +				fprintf(stderr, "-rotation must be followed by axis vector and angle\n");
   3.106 +				goto err;
   3.107 +			}
   3.108 +			node->set_rotation(Quaternion(Vector3(vec[0], vec[1], vec[2]), vec[3]));
   3.109 +			i += 4;
   3.110 +
   3.111 +		} else if(strcmp(argv[i], "-scaling") == 0) {
   3.112 +			int nelem = parse_vec(argv + i + 1, vec);
   3.113 +			Vector3 s;
   3.114 +			if(nelem == 1) {
   3.115 +				s.x = s.y = s.z = vec[0];
   3.116 +			} else if(nelem == 3) {
   3.117 +				s = Vector3(vec[0], vec[1], vec[2]);
   3.118 +			} else {
   3.119 +				fprintf(stderr, "-scaling must be followed by 1 or 3 numbers\n");
   3.120 +				goto err;
   3.121 +			}
   3.122 +			node->set_scaling(s);
   3.123 +			i += nelem;
   3.124 +
   3.125 +		} else if(strcmp(argv[i], "-diffuse") == 0) {
   3.126 +			int nelem = parse_vec(argv + i + 1, vec);
   3.127 +			if(nelem < 3) {
   3.128 +				fprintf(stderr, "-diffuse must be followed by a color (r g b)\n");
   3.129 +				goto err;
   3.130 +			}
   3.131 +			gobj->mtl.set_attrib("diffuse", Color(vec[0], vec[1], vec[2]));
   3.132 +			i += 3;
   3.133 +
   3.134 +		} else if(strcmp(argv[i], "-specular") == 0) {
   3.135 +			int nelem = parse_vec(argv + i + 1, vec);
   3.136 +			if(nelem < 3) {
   3.137 +				fprintf(stderr, "-specular must be followed by a color\n");
   3.138 +				goto err;
   3.139 +			}
   3.140 +			gobj->mtl.set_attrib("specular", Color(vec[0], vec[1], vec[2]));
   3.141 +			i += 3;
   3.142 +
   3.143 +		} else if(strcmp(argv[i], "-emissive") == 0) {
   3.144 +			int nelem = parse_vec(argv + i + 1, vec);
   3.145 +			Color emissive;
   3.146 +			if(nelem == 1) {
   3.147 +				emissive = Vector3(1, 1, 1);
   3.148 +			} else if(nelem == 3) {
   3.149 +				emissive = Vector3(vec[0], vec[1], vec[2]);
   3.150 +			} else {
   3.151 +				fprintf(stderr, "-emissive must be followed by an intensity or a color\n");
   3.152 +				goto err;
   3.153 +			}
   3.154 +			i += nelem;
   3.155 +			gobj->mtl.set_attrib("emissive", emissive);
   3.156 +
   3.157 +		} else {
   3.158 +			fprintf(stderr, "unrecognized %s option: %s\n", argv[0], argv[i]);
   3.159 +			goto err;
   3.160 +		}
   3.161 +	}
   3.162 +
   3.163 +	return node;
   3.164 +err:
   3.165 +	delete node;
   3.166 +	return 0;
   3.167 +}
   3.168 +
   3.169 +static Camera *proc_camera(int argc, char **argv)
   3.170 +{
   3.171 +	float vec[4];
   3.172 +	TargetCamera *cam = new TargetCamera;
   3.173 +
   3.174 +	for(int i=1; i<argc; i++) {
   3.175 +		if(strcmp(argv[i], "-position") == 0) {
   3.176 +			int nelem = parse_vec(argv + i + 1, vec);
   3.177 +			if(nelem < 3) {
   3.178 +				fprintf(stderr, "-position must be followed by 3 numbers\n");
   3.179 +				goto err;
   3.180 +			}
   3.181 +			cam->set_position(Vector3(vec[0], vec[1], vec[2]));
   3.182 +			i += 3;
   3.183 +
   3.184 +		} else if(strcmp(argv[i], "-target") == 0) {
   3.185 +			int nelem = parse_vec(argv + i + 1, vec);
   3.186 +			if(nelem < 3) {
   3.187 +				fprintf(stderr, "-target must be followed by 3 numbers\n");
   3.188 +				goto err;
   3.189 +			}
   3.190 +			cam->set_target(Vector3(vec[0], vec[1], vec[2]));
   3.191 +			i += 3;
   3.192 +
   3.193 +		} else if(strcmp(argv[i], "-fov") == 0) {
   3.194 +			int nelem = parse_vec(argv + i + 1, vec);
   3.195 +			if(nelem < 1) {
   3.196 +				fprintf(stderr, "-fov must be followed by the field of view in degrees\n");
   3.197 +				goto err;
   3.198 +			}
   3.199 +			cam->set_fov(vec[0]);
   3.200 +			i += 1;
   3.201 +
   3.202 +		} else {
   3.203 +			fprintf(stderr, "unrecognized camera option: %s\n", argv[i]);
   3.204 +			goto err;
   3.205 +		}
   3.206 +	}
   3.207 +	return cam;
   3.208 +
   3.209 +err:
   3.210 +	delete cam;
   3.211 +	return 0;
   3.212 +}
   3.213 +
   3.214 +bool Scene::proc_cmd(int argc, char **argv)
   3.215 +{
   3.216 +	Object *obj = 0;
   3.217 +	SceneNode *node = 0;
   3.218 +
   3.219 +	if(strcmp(argv[0], "sphere") == 0) {
   3.220 +		obj = new Sphere;
   3.221 +		node = proc_object(obj, argc, argv);
   3.222 +
   3.223 +	} else if(strcmp(argv[0], "box") == 0) {
   3.224 +		obj = new Box;
   3.225 +		node = proc_object(obj, argc, argv);
   3.226 +
   3.227 +	} else if(strcmp(argv[0], "mesh") == 0) {
   3.228 +		fprintf(stderr, "meshes not implemented yet\n");
   3.229 +		return false;
   3.230 +
   3.231 +	} else if(strcmp(argv[0], "camera") == 0) {
   3.232 +		Camera *cam = proc_camera(argc, argv);
   3.233 +		if(!cam) {
   3.234 +			return false;
   3.235 +		}
   3.236 +		use_camera(cam);
   3.237 +
   3.238 +	} else {
   3.239 +		fprintf(stderr, "unknown command: %s\n", argv[0]);
   3.240 +		return false;
   3.241 +	}
   3.242 +
   3.243 +	if(obj) {
   3.244 +		if(!node) {
   3.245 +			return false;
   3.246 +		}
   3.247 +		add_object(obj);
   3.248 +		add_node(node);
   3.249 +	}
   3.250 +
   3.251 +	return true;
   3.252 +}
     4.1 --- a/liberebus/src/scene.h	Mon May 26 23:34:12 2014 +0300
     4.2 +++ b/liberebus/src/scene.h	Tue May 27 07:43:55 2014 +0300
     4.3 @@ -1,6 +1,7 @@
     4.4  #ifndef SCENE_H_
     4.5  #define SCENE_H_
     4.6  
     4.7 +#include <stdio.h>
     4.8  #include <vector>
     4.9  #include "snode.h"
    4.10  #include "camera.h"
    4.11 @@ -52,6 +53,9 @@
    4.12  	bool intersect(const Ray &ray, RayHit *hit) const;
    4.13  
    4.14  	bool load(const char *fname);
    4.15 +	bool load(FILE *fp);
    4.16 +
    4.17 +	bool proc_cmd(int argc, char **argv);
    4.18  };
    4.19  
    4.20  #endif	// SCENE_H_
     5.1 --- a/src/main.cc	Mon May 26 23:34:12 2014 +0300
     5.2 +++ b/src/main.cc	Tue May 27 07:43:55 2014 +0300
     5.3 @@ -1,6 +1,7 @@
     5.4  #include <stdio.h>
     5.5  #include <stdlib.h>
     5.6  #include <assert.h>
     5.7 +#include <vector>
     5.8  #include "opengl.h"
     5.9  #include "erebus.h"
    5.10  
    5.11 @@ -25,11 +26,17 @@
    5.12  static erebus *erb;
    5.13  static bool render_pending;
    5.14  
    5.15 +static std::vector<char*> sfiles;
    5.16  
    5.17  int main(int argc, char **argv)
    5.18  {
    5.19  	glutInitWindowSize(1024, 600);
    5.20  	glutInit(&argc, argv);
    5.21 +
    5.22 +	for(int i=1; i<argc; i++) {
    5.23 +		sfiles.push_back(argv[i]);
    5.24 +	}
    5.25 +
    5.26  	glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
    5.27  	glutCreateWindow("erebus OpenGL frontend");
    5.28  
    5.29 @@ -61,8 +68,11 @@
    5.30  	erb_setopti(erb, ERB_OPT_WIDTH, width);
    5.31  	erb_setopti(erb, ERB_OPT_HEIGHT, height);
    5.32  
    5.33 -	if(erb_load_scene(erb, "scene") == -1) {
    5.34 -		return false;
    5.35 +	for(size_t i=0; i<sfiles.size(); i++) {
    5.36 +		printf("loading scene file: %s\n", sfiles[i]);
    5.37 +		if(erb_load_scene(erb, sfiles[i]) == -1) {
    5.38 +			return false;
    5.39 +		}
    5.40  	}
    5.41  
    5.42  	printf("begin rendering\n");
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/test/scene	Tue May 27 07:43:55 2014 +0300
     6.3 @@ -0,0 +1,8 @@
     6.4 +# test scene
     6.5 +
     6.6 +sphere -position 0 0 0 -scaling 1 1 1 -diffuse 1 0.5 0.4
     6.7 +box -position 0 -1.25 0 -scaling 4 0.5 4 -diffuse 0.3 0.4 1.0
     6.8 +
     6.9 +box -position 0 5 0 -scaling 3 0.1 3 -emissive 4 4 4
    6.10 +
    6.11 +camera -position 0 3 -6 -target 0 0 0