erebus
diff liberebus/src/scene.cc @ 19:6204e4d3f445
scene loading
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Tue, 27 May 2014 07:43:55 +0300 |
parents | e2d9bf168a41 |
children | ea95b62dbc87 |
line diff
1.1 --- a/liberebus/src/scene.cc Mon May 26 23:34:12 2014 +0300 1.2 +++ b/liberebus/src/scene.cc Tue May 27 07:43:55 2014 +0300 1.3 @@ -1,8 +1,14 @@ 1.4 +#include <stdio.h> 1.5 +#include <stdlib.h> 1.6 +#include <string.h> 1.7 #include "scene.h" 1.8 +#include "snode.h" 1.9 +#include "object.h" 1.10 +#include "geomobj.h" 1.11 1.12 // default enviromental parameters 1.13 Environment::Environment() 1.14 - : bgcolor(0.05, 0.05, 0.05), ambient(0.05, 0.05, 0.05) 1.15 + : bgcolor(0.01, 0.01, 0.01), ambient(0.01, 0.01, 0.01) 1.16 { 1.17 } 1.18 1.19 @@ -105,5 +111,232 @@ 1.20 1.21 bool Scene::load(const char *fname) 1.22 { 1.23 - return false; // TODO 1.24 + FILE *fp = fopen(fname, "r"); 1.25 + if(!fp) { 1.26 + fprintf(stderr, "failed to open scene file: %s\n", fname); 1.27 + return false; 1.28 + } 1.29 + 1.30 + bool res = load(fp); 1.31 + fclose(fp); 1.32 + return res; 1.33 } 1.34 + 1.35 +static char *strip_wspace(char *str) 1.36 +{ 1.37 + while(*str && isspace(*str)) str++; 1.38 + return str; 1.39 +} 1.40 + 1.41 +bool Scene::load(FILE *fp) 1.42 +{ 1.43 + char buf[256]; 1.44 + 1.45 + while(fgets(buf, sizeof buf, fp)) { 1.46 + char *line = strip_wspace(buf); 1.47 + if(!line || !*line || *line == '#') { 1.48 + continue; 1.49 + } 1.50 + 1.51 + std::vector<char*> cmd; 1.52 + 1.53 + char *tok = 0; 1.54 + while((tok = strtok(tok ? 0 : line, " \t\v\n\r"))) { 1.55 + printf("token: %s\n", tok); 1.56 + cmd.push_back(tok); 1.57 + } 1.58 + cmd.push_back(0); 1.59 + 1.60 + 1.61 + if(!proc_cmd((int)cmd.size() - 1, &cmd[0])) { 1.62 + return false; 1.63 + } 1.64 + } 1.65 + 1.66 + return true; 1.67 +} 1.68 + 1.69 +static int parse_vec(char **argv, float *vec) 1.70 +{ 1.71 + int nelem = 0; 1.72 + char *endp; 1.73 + 1.74 + for(int i=0; i<4; i++) { 1.75 + if(!argv[i]) break; 1.76 + 1.77 + vec[nelem] = strtod(argv[i], &endp); 1.78 + if(endp == argv[i]) { 1.79 + break; 1.80 + } 1.81 + nelem++; 1.82 + } 1.83 + return nelem; 1.84 +} 1.85 + 1.86 +static SceneNode *proc_object(Object *obj, int argc, char **argv) 1.87 +{ 1.88 + float vec[4]; 1.89 + SceneNode *node = new SceneNode(obj); 1.90 + GeomObject *gobj = (GeomObject*)obj; 1.91 + 1.92 + for(int i=1; i<argc; i++) { 1.93 + if(strcmp(argv[i], "-position") == 0) { 1.94 + int nelem = parse_vec(argv + i + 1, vec); 1.95 + if(nelem < 3) { 1.96 + fprintf(stderr, "-position must be followed by 3 numbers\n"); 1.97 + goto err; 1.98 + } 1.99 + node->set_position(Vector3(vec[0], vec[1], vec[2])); 1.100 + i += 3; 1.101 + 1.102 + } else if(strcmp(argv[i], "-rotation") == 0) { 1.103 + int nelem = parse_vec(argv + i + 1, vec); 1.104 + if(nelem < 4) { 1.105 + fprintf(stderr, "-rotation must be followed by axis vector and angle\n"); 1.106 + goto err; 1.107 + } 1.108 + node->set_rotation(Quaternion(Vector3(vec[0], vec[1], vec[2]), vec[3])); 1.109 + i += 4; 1.110 + 1.111 + } else if(strcmp(argv[i], "-scaling") == 0) { 1.112 + int nelem = parse_vec(argv + i + 1, vec); 1.113 + Vector3 s; 1.114 + if(nelem == 1) { 1.115 + s.x = s.y = s.z = vec[0]; 1.116 + } else if(nelem == 3) { 1.117 + s = Vector3(vec[0], vec[1], vec[2]); 1.118 + } else { 1.119 + fprintf(stderr, "-scaling must be followed by 1 or 3 numbers\n"); 1.120 + goto err; 1.121 + } 1.122 + node->set_scaling(s); 1.123 + i += nelem; 1.124 + 1.125 + } else if(strcmp(argv[i], "-diffuse") == 0) { 1.126 + int nelem = parse_vec(argv + i + 1, vec); 1.127 + if(nelem < 3) { 1.128 + fprintf(stderr, "-diffuse must be followed by a color (r g b)\n"); 1.129 + goto err; 1.130 + } 1.131 + gobj->mtl.set_attrib("diffuse", Color(vec[0], vec[1], vec[2])); 1.132 + i += 3; 1.133 + 1.134 + } else if(strcmp(argv[i], "-specular") == 0) { 1.135 + int nelem = parse_vec(argv + i + 1, vec); 1.136 + if(nelem < 3) { 1.137 + fprintf(stderr, "-specular must be followed by a color\n"); 1.138 + goto err; 1.139 + } 1.140 + gobj->mtl.set_attrib("specular", Color(vec[0], vec[1], vec[2])); 1.141 + i += 3; 1.142 + 1.143 + } else if(strcmp(argv[i], "-emissive") == 0) { 1.144 + int nelem = parse_vec(argv + i + 1, vec); 1.145 + Color emissive; 1.146 + if(nelem == 1) { 1.147 + emissive = Vector3(1, 1, 1); 1.148 + } else if(nelem == 3) { 1.149 + emissive = Vector3(vec[0], vec[1], vec[2]); 1.150 + } else { 1.151 + fprintf(stderr, "-emissive must be followed by an intensity or a color\n"); 1.152 + goto err; 1.153 + } 1.154 + i += nelem; 1.155 + gobj->mtl.set_attrib("emissive", emissive); 1.156 + 1.157 + } else { 1.158 + fprintf(stderr, "unrecognized %s option: %s\n", argv[0], argv[i]); 1.159 + goto err; 1.160 + } 1.161 + } 1.162 + 1.163 + return node; 1.164 +err: 1.165 + delete node; 1.166 + return 0; 1.167 +} 1.168 + 1.169 +static Camera *proc_camera(int argc, char **argv) 1.170 +{ 1.171 + float vec[4]; 1.172 + TargetCamera *cam = new TargetCamera; 1.173 + 1.174 + for(int i=1; i<argc; i++) { 1.175 + if(strcmp(argv[i], "-position") == 0) { 1.176 + int nelem = parse_vec(argv + i + 1, vec); 1.177 + if(nelem < 3) { 1.178 + fprintf(stderr, "-position must be followed by 3 numbers\n"); 1.179 + goto err; 1.180 + } 1.181 + cam->set_position(Vector3(vec[0], vec[1], vec[2])); 1.182 + i += 3; 1.183 + 1.184 + } else if(strcmp(argv[i], "-target") == 0) { 1.185 + int nelem = parse_vec(argv + i + 1, vec); 1.186 + if(nelem < 3) { 1.187 + fprintf(stderr, "-target must be followed by 3 numbers\n"); 1.188 + goto err; 1.189 + } 1.190 + cam->set_target(Vector3(vec[0], vec[1], vec[2])); 1.191 + i += 3; 1.192 + 1.193 + } else if(strcmp(argv[i], "-fov") == 0) { 1.194 + int nelem = parse_vec(argv + i + 1, vec); 1.195 + if(nelem < 1) { 1.196 + fprintf(stderr, "-fov must be followed by the field of view in degrees\n"); 1.197 + goto err; 1.198 + } 1.199 + cam->set_fov(vec[0]); 1.200 + i += 1; 1.201 + 1.202 + } else { 1.203 + fprintf(stderr, "unrecognized camera option: %s\n", argv[i]); 1.204 + goto err; 1.205 + } 1.206 + } 1.207 + return cam; 1.208 + 1.209 +err: 1.210 + delete cam; 1.211 + return 0; 1.212 +} 1.213 + 1.214 +bool Scene::proc_cmd(int argc, char **argv) 1.215 +{ 1.216 + Object *obj = 0; 1.217 + SceneNode *node = 0; 1.218 + 1.219 + if(strcmp(argv[0], "sphere") == 0) { 1.220 + obj = new Sphere; 1.221 + node = proc_object(obj, argc, argv); 1.222 + 1.223 + } else if(strcmp(argv[0], "box") == 0) { 1.224 + obj = new Box; 1.225 + node = proc_object(obj, argc, argv); 1.226 + 1.227 + } else if(strcmp(argv[0], "mesh") == 0) { 1.228 + fprintf(stderr, "meshes not implemented yet\n"); 1.229 + return false; 1.230 + 1.231 + } else if(strcmp(argv[0], "camera") == 0) { 1.232 + Camera *cam = proc_camera(argc, argv); 1.233 + if(!cam) { 1.234 + return false; 1.235 + } 1.236 + use_camera(cam); 1.237 + 1.238 + } else { 1.239 + fprintf(stderr, "unknown command: %s\n", argv[0]); 1.240 + return false; 1.241 + } 1.242 + 1.243 + if(obj) { 1.244 + if(!node) { 1.245 + return false; 1.246 + } 1.247 + add_object(obj); 1.248 + add_node(node); 1.249 + } 1.250 + 1.251 + return true; 1.252 +}