# HG changeset patch # User John Tsiombikas # Date 1401165835 -10800 # Node ID 6204e4d3f4455e1df7ab095cab3aae867a06199c # Parent 09028848f276d4a94a31f916f7a14a36bd454848 scene loading diff -r 09028848f276 -r 6204e4d3f445 README.md --- a/README.md Mon May 26 23:34:12 2014 +0300 +++ b/README.md Tue May 27 07:43:55 2014 +0300 @@ -4,7 +4,7 @@ Copyright (C) 2014 John Tsiombikas This program is released as free software, under the terms of the GNU General -Public License v3, or at your option any later version, published by the Free +Public License v3, or at your option, any later version published by the Free Software Foundation. **This program is in a very early stage of development. Don't bother trying it.** diff -r 09028848f276 -r 6204e4d3f445 liberebus/src/erebus.cc --- a/liberebus/src/erebus.cc Mon May 26 23:34:12 2014 +0300 +++ b/liberebus/src/erebus.cc Tue May 27 07:43:55 2014 +0300 @@ -203,33 +203,9 @@ delete ctx->scn; ctx->scn = new Scene; - // XXX for now just create a test scene here - Sphere *sph = new Sphere; - sph->mtl.set_attrib("diffuse", Color(1.0, 0.3, 0.2)); - SceneNode *sph_node = new SceneNode(sph); - ctx->scn->add_object(sph); - ctx->scn->add_node(sph_node); - - Box *box = new Box; - box->mtl.set_attrib("diffuse", Color(0.9, 0.8, 0.75)); - SceneNode *box_node = new SceneNode(box); - box_node->set_position(Vector3(0, -1.25, 0)); - box_node->set_scaling(Vector3(5, 0.5, 5)); - ctx->scn->add_object(box); - ctx->scn->add_node(box_node); - - Sphere *lt = new Sphere; - lt->mtl.set_attrib("emissive", Color(10, 10, 10)); - SceneNode *lt_node = new SceneNode(lt); - lt_node->set_position(Vector3(-15, 15, -10)); - lt_node->set_scaling(Vector3(8, 8, 8)); - ctx->scn->add_object(lt); - ctx->scn->add_node(lt_node); - - TargetCamera *cam = new TargetCamera(Vector3(0, 4, -8), Vector3(0, 0, 0)); - //ctx->scn->add_object(cam); - ctx->scn->use_camera(cam); - + if(!ctx->scn->load(fname)) { + return -1; + } return 0; } @@ -317,8 +293,8 @@ Vector3 cpos = cam->get_position(); float mag = cpos.length(); - float theta = atan2(cpos.z / mag, cpos.x / mag) + DEG_TO_RAD(dx * 0.5); - float phi = acos(cpos.y / mag) + DEG_TO_RAD(dy * 0.5); + float theta = atan2(cpos.z / mag, cpos.x / mag) - DEG_TO_RAD(dx * 0.5); + float phi = acos(cpos.y / mag) - DEG_TO_RAD(dy * 0.5); if(phi < 0) phi = 0; if(phi > M_PI) phi = M_PI; diff -r 09028848f276 -r 6204e4d3f445 liberebus/src/scene.cc --- a/liberebus/src/scene.cc Mon May 26 23:34:12 2014 +0300 +++ b/liberebus/src/scene.cc Tue May 27 07:43:55 2014 +0300 @@ -1,8 +1,14 @@ +#include +#include +#include #include "scene.h" +#include "snode.h" +#include "object.h" +#include "geomobj.h" // default enviromental parameters Environment::Environment() - : bgcolor(0.05, 0.05, 0.05), ambient(0.05, 0.05, 0.05) + : bgcolor(0.01, 0.01, 0.01), ambient(0.01, 0.01, 0.01) { } @@ -105,5 +111,232 @@ bool Scene::load(const char *fname) { - return false; // TODO + FILE *fp = fopen(fname, "r"); + if(!fp) { + fprintf(stderr, "failed to open scene file: %s\n", fname); + return false; + } + + bool res = load(fp); + fclose(fp); + return res; } + +static char *strip_wspace(char *str) +{ + while(*str && isspace(*str)) str++; + return str; +} + +bool Scene::load(FILE *fp) +{ + char buf[256]; + + while(fgets(buf, sizeof buf, fp)) { + char *line = strip_wspace(buf); + if(!line || !*line || *line == '#') { + continue; + } + + std::vector cmd; + + char *tok = 0; + while((tok = strtok(tok ? 0 : line, " \t\v\n\r"))) { + printf("token: %s\n", tok); + cmd.push_back(tok); + } + cmd.push_back(0); + + + if(!proc_cmd((int)cmd.size() - 1, &cmd[0])) { + return false; + } + } + + return true; +} + +static int parse_vec(char **argv, float *vec) +{ + int nelem = 0; + char *endp; + + for(int i=0; i<4; i++) { + if(!argv[i]) break; + + vec[nelem] = strtod(argv[i], &endp); + if(endp == argv[i]) { + break; + } + nelem++; + } + return nelem; +} + +static SceneNode *proc_object(Object *obj, int argc, char **argv) +{ + float vec[4]; + SceneNode *node = new SceneNode(obj); + GeomObject *gobj = (GeomObject*)obj; + + for(int i=1; iset_position(Vector3(vec[0], vec[1], vec[2])); + i += 3; + + } else if(strcmp(argv[i], "-rotation") == 0) { + int nelem = parse_vec(argv + i + 1, vec); + if(nelem < 4) { + fprintf(stderr, "-rotation must be followed by axis vector and angle\n"); + goto err; + } + node->set_rotation(Quaternion(Vector3(vec[0], vec[1], vec[2]), vec[3])); + i += 4; + + } else if(strcmp(argv[i], "-scaling") == 0) { + int nelem = parse_vec(argv + i + 1, vec); + Vector3 s; + if(nelem == 1) { + s.x = s.y = s.z = vec[0]; + } else if(nelem == 3) { + s = Vector3(vec[0], vec[1], vec[2]); + } else { + fprintf(stderr, "-scaling must be followed by 1 or 3 numbers\n"); + goto err; + } + node->set_scaling(s); + i += nelem; + + } else if(strcmp(argv[i], "-diffuse") == 0) { + int nelem = parse_vec(argv + i + 1, vec); + if(nelem < 3) { + fprintf(stderr, "-diffuse must be followed by a color (r g b)\n"); + goto err; + } + gobj->mtl.set_attrib("diffuse", Color(vec[0], vec[1], vec[2])); + i += 3; + + } else if(strcmp(argv[i], "-specular") == 0) { + int nelem = parse_vec(argv + i + 1, vec); + if(nelem < 3) { + fprintf(stderr, "-specular must be followed by a color\n"); + goto err; + } + gobj->mtl.set_attrib("specular", Color(vec[0], vec[1], vec[2])); + i += 3; + + } else if(strcmp(argv[i], "-emissive") == 0) { + int nelem = parse_vec(argv + i + 1, vec); + Color emissive; + if(nelem == 1) { + emissive = Vector3(1, 1, 1); + } else if(nelem == 3) { + emissive = Vector3(vec[0], vec[1], vec[2]); + } else { + fprintf(stderr, "-emissive must be followed by an intensity or a color\n"); + goto err; + } + i += nelem; + gobj->mtl.set_attrib("emissive", emissive); + + } else { + fprintf(stderr, "unrecognized %s option: %s\n", argv[0], argv[i]); + goto err; + } + } + + return node; +err: + delete node; + return 0; +} + +static Camera *proc_camera(int argc, char **argv) +{ + float vec[4]; + TargetCamera *cam = new TargetCamera; + + for(int i=1; iset_position(Vector3(vec[0], vec[1], vec[2])); + i += 3; + + } else if(strcmp(argv[i], "-target") == 0) { + int nelem = parse_vec(argv + i + 1, vec); + if(nelem < 3) { + fprintf(stderr, "-target must be followed by 3 numbers\n"); + goto err; + } + cam->set_target(Vector3(vec[0], vec[1], vec[2])); + i += 3; + + } else if(strcmp(argv[i], "-fov") == 0) { + int nelem = parse_vec(argv + i + 1, vec); + if(nelem < 1) { + fprintf(stderr, "-fov must be followed by the field of view in degrees\n"); + goto err; + } + cam->set_fov(vec[0]); + i += 1; + + } else { + fprintf(stderr, "unrecognized camera option: %s\n", argv[i]); + goto err; + } + } + return cam; + +err: + delete cam; + return 0; +} + +bool Scene::proc_cmd(int argc, char **argv) +{ + Object *obj = 0; + SceneNode *node = 0; + + if(strcmp(argv[0], "sphere") == 0) { + obj = new Sphere; + node = proc_object(obj, argc, argv); + + } else if(strcmp(argv[0], "box") == 0) { + obj = new Box; + node = proc_object(obj, argc, argv); + + } else if(strcmp(argv[0], "mesh") == 0) { + fprintf(stderr, "meshes not implemented yet\n"); + return false; + + } else if(strcmp(argv[0], "camera") == 0) { + Camera *cam = proc_camera(argc, argv); + if(!cam) { + return false; + } + use_camera(cam); + + } else { + fprintf(stderr, "unknown command: %s\n", argv[0]); + return false; + } + + if(obj) { + if(!node) { + return false; + } + add_object(obj); + add_node(node); + } + + return true; +} diff -r 09028848f276 -r 6204e4d3f445 liberebus/src/scene.h --- a/liberebus/src/scene.h Mon May 26 23:34:12 2014 +0300 +++ b/liberebus/src/scene.h Tue May 27 07:43:55 2014 +0300 @@ -1,6 +1,7 @@ #ifndef SCENE_H_ #define SCENE_H_ +#include #include #include "snode.h" #include "camera.h" @@ -52,6 +53,9 @@ bool intersect(const Ray &ray, RayHit *hit) const; bool load(const char *fname); + bool load(FILE *fp); + + bool proc_cmd(int argc, char **argv); }; #endif // SCENE_H_ diff -r 09028848f276 -r 6204e4d3f445 src/main.cc --- a/src/main.cc Mon May 26 23:34:12 2014 +0300 +++ b/src/main.cc Tue May 27 07:43:55 2014 +0300 @@ -1,6 +1,7 @@ #include #include #include +#include #include "opengl.h" #include "erebus.h" @@ -25,11 +26,17 @@ static erebus *erb; static bool render_pending; +static std::vector sfiles; int main(int argc, char **argv) { glutInitWindowSize(1024, 600); glutInit(&argc, argv); + + for(int i=1; i