1 // Copyright 2016-2021 Doug Moen
2 // Licensed under the Apache License, version 2.0
3 // See accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0
4 
5 #include <libcurv/render.h>
6 
7 #include <libcurv/context.h>
8 #include <libcurv/exception.h>
9 #include <libcurv/function.h>
10 #include <libcurv/record.h>
11 #include <libcurv/shape.h>
12 
13 #include <climits>
14 
15 namespace curv {
16 
17 const std::vector<const char*>
18 Render_Opts::shader_enum { "standard", "pew", "sf1" };
19 
20 void
set_shader(Value val,const Context & cx)21 Render_Opts::set_shader(Value val, const Context& cx)
22 {
23     auto v = value_to_variant(val, cx);
24     if (v.first == "standard") {
25         if (v.second.is_missing()) {
26             shader_ = Shader::standard;
27             return;
28         }
29         goto error;
30     }
31     if (v.first == "pew") {
32         if (v.second.is_missing()) {
33             shader_ = Shader::pew;
34             return;
35         }
36         goto error;
37     }
38     if (v.first == "sf1") {
39         shader_ = Shader::sf1;
40         if (!v.second.is_missing()) {
41             sf1_ = maybe_function(v.second, cx);
42             if (sf1_ == nullptr)
43                 goto error;
44         }
45         return;
46     }
47 error:
48     throw Exception(cx,
49         stringify(val," is not #standard|#pew|{sf1:<function>}"));
50 }
51 
52 void
update_from_record(Record & r,const Context & cx)53 Render_Opts::update_from_record(
54     Record& r,
55     const Context& cx)
56 {
57     auto aa_val = r.find_field(make_symbol("aa"), cx);
58     if (!aa_val.is_missing()) {
59         aa_ = aa_val.to_int(1, INT_MAX, At_Field("aa", cx));
60     }
61     auto taa_val = r.find_field(make_symbol("taa"), cx);
62     if (!taa_val.is_missing()) {
63         taa_ = taa_val.to_int(1, INT_MAX, At_Field("taa", cx));
64     }
65     auto fdur_val = r.find_field(make_symbol("fdur"), cx);
66     if (!fdur_val.is_missing()) {
67         fdur_ = fdur_val.to_num(At_Field("fdur", cx));
68     }
69     auto bg_val = r.find_field(make_symbol("bg"), cx);
70     if (!bg_val.is_missing()) {
71         bg_ = value_to_vec3(bg_val, At_Field("bg", cx));
72     }
73     auto ray_max_iter_val = r.find_field(make_symbol("ray_max_iter"), cx);
74     if (!ray_max_iter_val.is_missing()) {
75         ray_max_iter_ = ray_max_iter_val.to_int(1, INT_MAX,
76             At_Field("ray_max_iter", cx));
77     }
78     auto ray_max_depth_val = r.find_field(make_symbol("ray_max_depth"), cx);
79     if (!ray_max_depth_val.is_missing()) {
80         ray_max_depth_ = ray_max_depth_val.to_num(
81             At_Field("ray_max_depth", cx));
82     }
83     auto shader_val = r.find_field(make_symbol("shader"), cx);
84     if (!shader_val.is_missing()) {
85         set_shader(shader_val, At_Field("shader", cx));
86     }
87 }
88 
89 void
describe_opts(std::ostream & out,const char * prefix)90 Render_Opts::describe_opts(std::ostream& out, const char* prefix)
91 {
92   Render_Opts opts;
93   out
94   << prefix <<
95   "-O aa=<supersampling factor for antialiasing> (1 means disabled)\n"
96   << prefix <<
97   "-O taa=<supersampling factor for temporal antialiasing> (1 means disabled)\n"
98   << prefix <<
99   "-O fdur=<frame duration, in seconds> : Used with -Otaa and -Oanimate\n"
100   << prefix <<
101   "-O bg=<background colour>\n"
102   << prefix <<
103   "-O ray_max_iter=<maximum # of ray-march iterations> (default "
104     << opts.ray_max_iter_ << ")\n"
105   << prefix <<
106   "-O ray_max_depth=<maximum ray-marching depth> (default "
107     << opts.ray_max_depth_ << ")\n"
108   << prefix <<
109   "-O shader=#standard|#pew|{sf1:<function>}\n"
110   ;
111 }
112 
113 bool
set_field(const std::string & name,Value val,const Context & cx)114 Render_Opts::set_field(const std::string& name, Value val, const Context& cx)
115 {
116     if (name == "aa") {
117         aa_ = val.to_int(1, INT_MAX, cx);
118         return true;
119     }
120     if (name == "taa") {
121         taa_ = val.to_int(1, INT_MAX, cx);
122         return true;
123     }
124     if (name == "fdur") {
125         fdur_ = val.to_num(cx);
126         return true;
127     }
128     if (name == "bg") {
129         bg_ = value_to_vec3(val, cx);
130         return true;
131     }
132     if (name == "ray_max_iter") {
133         ray_max_iter_ = val.to_int(1, INT_MAX, cx);
134         return true;
135     }
136     if (name == "ray_max_depth") {
137         ray_max_depth_ = val.to_num(cx);
138         return true;
139     }
140     if (name == "shader") {
141         set_shader(val, cx);
142         return true;
143     }
144     return false;
145 }
146 
147 } // namespace curv
148