17 #include <RslPlugin.h>
23 #include <SeExpression.h>
24 #include <SeExprFunc.h>
25 #include <RixInterfaces.h>
31 RixTokenStorage* tokenizer;
32 inline const char* tokenize(
const char* str) {
33 const char* result = tokenizer->GetToken(str);
37 int SeTokenize(RslContext* ctx,
int argc,
const RslArg* argv[]) {
38 RslStringIter result(argv[0]);
39 const char* str = *RslStringIter(argv[1]);
40 *result = (RtString)tokenize(str);
45 immutable_hash_map<const char*, int> indexMap;
46 std::vector<int> groupStarts;
47 std::vector<int> groupCounts;
48 std::vector<int> groupIndices;
50 SeRmanVarMap(
int nvars,
const char** varnames,
int* varindices,
int* groupstarts)
51 : indexMap(varnames, varindices, nvars), groupStarts(groupstarts, groupstarts + nvars), groupCounts(nvars),
53 int groupIndex = 0, i, j;
54 for (i = 0; i < nvars;) {
56 for (j = i + 1; j < nvars; j++) {
57 if (groupStarts[j] != groupStarts[i])
break;
59 int groupCount = j - i;
62 groupCounts[i] = groupCount;
63 groupIndices[i] = groupIndex;
73 typedef std::map<const char*, SeRmanVarMap*> SeRmanVarMapMap;
74 typedef std::map<const char*, int> SeRmanExprMap;
75 typedef std::vector<int> SeVarBinding;
86 SeRmanVarMapMap varmaps;
88 SeRmanVarMap& getVarMap(
const char* varMapHandle) {
89 SeRmanVarMap*& varmap = varmaps[varMapHandle];
92 char* varlist = strdup(varMapHandle);
93 std::vector<const char*> varnames;
94 std::vector<int> groupStarts;
97 char* varlist_end = 0;
98 char* vargroup = strtok_r(varlist,
" ", &varlist_end);
101 int groupStart = varnames.size();
102 char* vargroup_end = 0;
103 char* var = strtok_r(vargroup,
",", &vargroup_end);
105 varnames.push_back(tokenize(var));
106 groupStarts.push_back(groupStart);
107 }
while ((var = strtok_r(0,
",", &vargroup_end)));
108 }
while ((vargroup = strtok_r(0,
" ", &varlist_end)));
111 int nvars = varnames.size();
112 int* varindices = (
int*)alloca(
sizeof(
int) * nvars);
113 for (
int i = 0; i < nvars; i++) {
116 varmap =
new SeRmanVarMap(nvars, &varnames[0], &varindices[0], &groupStarts[0]);
122 void ptError(
char* fmt, ...) {
123 static char strbuf[1024];
126 vsprintf(strbuf, fmt, ap);
127 msgs->Error(
"%s", strbuf);
131 void ptWarn(
char* fmt, ...) {
132 static char strbuf[1024];
135 vsprintf(strbuf, fmt, ap);
136 msgs->Warning(
"%s", strbuf);
140 SeRmanExprMap exprmap;
141 std::vector<SeRmanExpr*> exprs;
147 msgs = (RixMessages*)RxGetRixContext()->GetRixInterface(k_RixMessages);
153 ThreadData& getThreadData(RslContext* ctx) {
154 ThreadData* td = (ThreadData*)ctx->GetThreadData();
157 ctx->SetThreadData(td);
163 class SeRmanVar :
public SeExprVarRef {
165 SeRmanVar(ThreadData& td) : SeExprVarRef(SeExprType().FP(3).Varying()), td(td),
index(0) {}
167 virtual bool isVec() {
return 1; }
168 void setIndex(
int i) {
index = i; }
169 virtual void eval(
const SeExprVarNode* node, SeVec3d& result) {
170 RtColor& c = td.varValues[
index];
181 class AttrVar :
public SeExprVectorVarRef {
186 AttrVar() : name(
""),
value(0.) {}
188 AttrVar(
const std::string& nameIn) :
value(0.) {
190 size_t pos = nameIn.find(
"::");
191 name = nameIn.substr(0, pos) + nameIn.substr(pos + 1, nameIn.size() - (pos - 1));
194 std::string getName() {
return name; }
202 int statusOpt, statusAttr;
205 statusOpt = RxOption(name.c_str(), fbuf16,
sizeof(fbuf16), &rxType, &count);
206 statusAttr = RxAttribute(name.c_str(), fbuf16,
sizeof(fbuf16), &rxType, &count);
208 if (statusAttr != 0 && statusOpt != 0) {
210 value.setValue(0.0, 0.0, 0.0);
218 value.setValue(fbuf16[0], fbuf16[0], fbuf16[0]);
225 value.setValue(fbuf16[0], fbuf16[1], fbuf16[2]);
236 virtual void eval(
const SeExprVarNode* node, SeVec3d& result) { result =
value; }
240 class SeRmanExpr :
public SeExpression {
242 SeRmanExpr(
const std::string&
expr, ThreadData& td) : SeExpression(expr), _td(td), _boundVarMap(-1) {}
244 virtual SeExprVarRef*
resolveVar(
const std::string& name)
const {
245 if (name.find(
"::") != std::string::npos) {
247 for (i = 0, size = _attrrefs.size(); i < size; i++)
249 if (name == _attrrefs[i]->getName())
return _attrrefs[i];
252 AttrVar* attrVar =
new AttrVar( name);
253 _attrrefs.push_back(attrVar);
257 const char* token = tokenize(name.c_str());
258 for (
int i = 0, size = _varrefs.size(); i < size; i++)
259 if (_varnames[i] == token)
return _varrefs[i];
260 SeRmanVar* var =
new SeRmanVar(_td);
261 _varnames.push_back(token);
262 _varrefs.push_back(var);
266 SeVarBinding* bindVars(
const char* varMapHandle) {
267 SeVarBinding*& binding = _bindings[varMapHandle];
269 binding =
new SeVarBinding;
272 SeRmanVarMap& varmap = _td.getVarMap(varMapHandle);
274 int nvars = _varnames.size();
275 binding->resize(nvars);
276 for (
int i = 0; i < nvars; i++) {
277 const char* name = _varnames[i];
278 int index = varmap.indexMap[name];
285 char msg[] =
"SeRmanExpr error: undefined variable \"$%s\"";
286 _td.ptError(msg, name);
288 (*binding)[i] =
index;
291 _bindstack.push_back(binding);
296 int nattrs = _attrrefs.size();
299 for (
int i = 0; i < nattrs; i++) {
300 _attrrefs[i]->doLookup();
304 void setVarIndices() {
307 SeVarBinding* binding = _bindstack.back();
309 for (
int i = 0, size = binding->size(); i < size; i++) _varrefs[i]->setIndex((*binding)[i]);
313 void unbindVars() { _bindstack.pop_back(); }
316 mutable std::vector<const char*> _varnames;
317 mutable std::vector<SeRmanVar*> _varrefs;
318 mutable std::vector<AttrVar*> _attrrefs;
319 mutable std::map<const char*, SeVarBinding*> _bindings;
320 mutable std::vector<SeVarBinding*> _bindstack;
325 void init(RixContext* ctx) {
326 tokenizer = (RixTokenStorage*)ctx->GetRixInterface(k_RixGlobalTokenData);
329 char* plugins_ptr = getenv(
"SE_EXPR_PLUGINS");
332 plugins = plugins_ptr;
333 unsetenv(
"SE_EXPR_PLUGINS");
341 if (plugins_ptr) setenv(
"SE_EXPR_PLUGINS", plugins.c_str(), 1);
344 int SeExprBind(RslContext* ctx,
int argc,
const RslArg* argv[]) {
345 RslFloatIter result(argv[0]);
346 const char* exprstr = *RslStringIter(argv[1]);
347 const char* varmapHandle = *RslStringIter(argv[2]);
352 argv[3]->GetResizer()->Resize(0);
357 ThreadData& td = getThreadData(ctx);
358 int& index = td.exprmap[exprstr];
361 static pthread_mutex_t
mutex = PTHREAD_MUTEX_INITIALIZER;
362 pthread_mutex_lock(&mutex);
363 SeRmanExpr*
expr =
new SeRmanExpr(exprstr, td);
364 bool valid = expr->isValid();
365 pthread_mutex_unlock(&mutex);
367 char msg[] =
"SeRmanExpr error: %s";
368 td.ptError(msg, expr->parseError().c_str());
371 index = td.exprs.size();
373 td.exprs.push_back(expr);
379 SeRmanExpr* expr = td.exprs[
index];
381 SeVarBinding& binding = *expr->bindVars(varmapHandle);
382 int nvars = binding.size();
383 argv[3]->GetResizer()->Resize(nvars);
384 float* varIndices = *RslFloatArrayIter(argv[3]);
385 for (
int i = 0; i < nvars; i++) {
386 varIndices[i] = binding[i];
389 argv[3]->GetResizer()->Resize(0);
394 int SeExprEval(RslContext* ctx,
int argc,
const RslArg* argv[]) {
395 int index = int(*RslFloatIter(argv[1]));
396 RslColorArrayIter varValuesIter = argv[2];
397 RslColorIter CiIter = argv[3];
399 int numVals = argv[3]->NumValues();
402 for (
int i = 0; i < numVals; i++, CiIter++, varValuesIter++) {
404 Ci[0] = Ci[1] = Ci[2] = 0;
409 ThreadData& td = getThreadData(ctx);
411 SeRmanExpr& expr = *td.exprs[
index];
412 expr.setVarIndices();
414 bool isThreadSafe = expr.isThreadSafe();
416 for (
int i = 0; i < numVals; i++, CiIter++, varValuesIter++) {
417 td.varValues = &varValuesIter[0];
418 float* Ci = td.Ci = *CiIter;
421 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
422 if (!isThreadSafe) pthread_mutex_lock(&mutex);
424 SeVec3d v = expr.evaluate();
426 if (!isThreadSafe) pthread_mutex_unlock(&mutex);
428 if (!isfinite(v[0]) || !isfinite(v[1]) || !isfinite(v[2])) {
429 char msg[] =
"Shader Expression: %s: resulted in NAN. Setting val to 1";
430 td.ptWarn(msg, expr.getExpr().c_str());
431 v[0] = v[1] = v[2] = 1;
447 {
"string SeTokenize(string)", SeTokenize, NULL, NULL},
450 {
"float SeExprBind(string, string, output uniform float[])", SeExprBind, NULL, NULL},
453 {
"void SeExprEval(uniform float, color[], output color)", SeExprEval, NULL, NULL},
static SeExprInternal2::Mutex mutex
</pre >< h2 > Evaluating expressions</h2 > Evaluating an expression is pretty easy But before we can do that we need to make an instance< pre > GrapherExpr expr("x+x^2")
virtual void eval(ArgHandle args)
For any rgb or hsl value(except for negative s values)
The result is computed int int< br >< divstyle="margin-left:40px;"> Picks values randomly between loRange and hiRange based on supplied index(which is automatically hashed). 
RslFunctionTable RslPublicFunctions(funcs, init)
</pre > Once we have this we need an instance to store our variable and provide a reference to that We make it because resolveVar() is const .One does not need to store a variable reference in a given expression.In fact
static RslFunction funcs[]