crt/conf.cpp
#include "conf.hpp"
#include "objects.hpp"
#include "shaders.hpp"
#include "lights.hpp"
#include "texture.hpp"
#include "img.hpp"
pan_s pan = {}; // NOLINT(cert-err58-cpp)
static INLINE bool parse(char* s, vertex_t& v) {
return s && sscanf(s, " ( %" COORD_FORMAT " , %" COORD_FORMAT " , %" COORD_FORMAT " ) " , &v.x, &v.y, &v.z) == 3;
}
static INLINE bool parse(char* s, coord_t& c) {
return s && sscanf(s, " %" COORD_FORMAT " ", &c) == 1;
}
static INLINE bool parse(char* s, unsigned& u) {
return s && sscanf(s, " %u ", &u) == 1;
}
static INLINE bool parse(char* s, Img::rgb_t& c) {
unsigned r, g, b;
if (!s || sscanf(s, " 0x%02x%02x%02x ", &r, &g, &b) != 3) return false;
c.r = r; c.g = g; c.b = b;
return true;
}
static INLINE bool parse(char* s, Texture*& t) {
unsigned r = 0;
char* p;
if (*s >= '0' && *s <= '9' && (p = strchr(s, '+')) != NULL) {
*p = '\0';
r = atoi(s);
s = p+1;
}
Img::rgb_t c1;
if (!s) {
return false;
} else if (parse(s, c1)) {
t = new ColorTexture(r, c1);
return true;
} else {
char* mod = strrchr(s, ':');
if (mod) {
*(mod++) = '\0';
}
t = ImageTexture::load(r, s, mod);
return (t != NULL);
}
}
static INLINE bool parse(char* n, char* v) {
if (!n || !v) return false;
for (unsigned i=0; i<sizeof(config)/sizeof(config_t::val_t); ++i) {
config_t::val_t* val = &(((config_t::val_t*)&config)[i]);
if (!strcmp(n, val->name)) {
val->i = atoi(v);
val->d = atof(v);
return true;
}
}
return false;
}
static INLINE bool parse_line(char* l, Scene*& scene, Camera*& camera) {
coord_t a;
unsigned d, e;
vertex_t u, v, w;
Texture* t;
Img::rgb_t c;
char* tok = strtok(l, " \t");
if (!tok || *tok == '#') {
return true;
} else if (!strcmp(tok, "sphere")) {
if (!parse(strtok(NULL, " \t"), t)) return false;
if (!parse(strtok(NULL, " \t"), u)) return false;
if (!parse(strtok(NULL, " \t"), a)) return false;
Sphere* s = new Sphere(t, u, a);
if (!scene->push(s)) return false;
} else if (!strcmp(tok, "plane")) {
if (!parse(strtok(NULL, " \t"), t)) return false;
if (!parse(strtok(NULL, " \t"), u)) return false;
if (!parse(strtok(NULL, " \t"), v)) return false;
if (!parse(strtok(NULL, " \t"), w)) return false;
if (!scene->push(new Plane(t, u, v, w))) return false;
} else if (!strcmp(tok, "axisplane")) {
if (!parse(strtok(NULL, " \t"), t)) return false;
if (!parse(strtok(NULL, " \t"), u)) return false;
if (!parse(strtok(NULL, " \t"), v)) return false;
if (!scene->push(new AxisPlane(t, u, v))) return false;
} else if (!strcmp(tok, "cylinder")) {
if (!parse(strtok(NULL, " \t"), t)) return false;
if (!parse(strtok(NULL, " \t"), u)) return false;
if (!parse(strtok(NULL, " \t"), v)) return false;
if (!parse(strtok(NULL, " \t"), a)) return false;
if (!scene->push(new Cylinder(t, u, v, a))) return false;
} else if (!strcmp(tok, "globallight")) {
if (!parse(strtok(NULL, " \t"), d)) return false;
if (!scene->push(new GlobalLight(d))) return false;
} else if (!strcmp(tok, "raylight")) {
if (!parse(strtok(NULL, " \t"), d)) return false;
if (!scene->push(new RayLight(d))) return false;
} else if (!strcmp(tok, "pointlight")) {
if (!parse(strtok(NULL, " \t"), u)) return false;
if (!parse(strtok(NULL, " \t"), c)) return false;
if (!parse(strtok(NULL, " \t"), d)) return false;
if (!parse(strtok(NULL, " \t"), e)) return false;
if (!scene->push(new PointLight(u, c, d, e))) return false;
} else if (!strcmp(tok, "arealight")) {
if (!parse(strtok(NULL, " \t"), u)) return false;
if (!parse(strtok(NULL, " \t"), v)) return false;
if (!parse(strtok(NULL, " \t"), d)) return false;
if (!parse(strtok(NULL, " \t"), e)) return false;
if (!scene->push(new AreaLight(u, v, d, e))) return false;
} else if (!strcmp(tok, "depthfog")) {
if (!parse(strtok(NULL, " \t"), c)) return false;
if (!parse(strtok(NULL, " \t"), a)) return false;
if (!parse(strtok(NULL, " \t"), d)) return false;
new DepthFog(c, a, d);
} else if (!strcmp(tok, "depthblur")) {
if (!parse(strtok(NULL, " \t"), d)) return false;
if (!parse(strtok(NULL, " \t"), e)) return false;
new DepthBlur(d, e);
} else if (!strcmp(tok, "volumetriclight")) {
if (!parse(strtok(NULL, " \t"), u)) return false;
if (!parse(strtok(NULL, " \t"), d)) return false;
if (!parse(strtok(NULL, " \t"), e)) return false;
new VolumetricLight(u, d, e);
} else if (!strcmp(tok, "camera")) {
if (!parse(strtok(NULL, " \t"), u)) return false;
if (!parse(strtok(NULL, " \t"), v)) return false;
if (!parse(strtok(NULL, " \t"), d)) return false;
if (!parse(strtok(NULL, " \t"), e)) return false;
if (camera) return false;
camera = new Camera(u, v, d, e);
} else if (!strcmp(tok, "set")) {
char* name = strtok(NULL, " \t");
char* val = strtok(NULL, " \t");
if (!parse(name, val)) return false;
} else if (!strcmp(tok, "pan")) {
if (!parse(strtok(NULL, " \t"), pan.frames)) return false;
if (!parse(strtok(NULL, " \t"), pan.camera_move)) return false;
if (!parse(strtok(NULL, " \t"), pan.camera_pan)) return false;
} else {
return false;
}
return true;
}
bool parse_file(const char* fn, Scene*& scene, Camera*& camera) {
size_t len;
char* buf = file_read(fn, len);
if (!buf) return false;
scene = new Scene();
camera = NULL;
unsigned lineno = 0;
char* p = buf;
char* nl;
while ((nl = strchr(p, '\n'))) {
*nl = '\0';
lineno++;
if (!parse_line(p, scene, camera)) {
LOG("cannot parse '%s' line %u ('%s')", fn, lineno, p);
delete scene;
if (camera) {
delete camera;
}
free(buf);
return false;
}
p = nl+1;
}
free(buf);
if (!camera) {
delete scene;
return false;
}
if (!pan.frames) {
delete scene;
delete camera;
return false;
}
scene->finalize();
return true;
}