00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <RslPlugin.h>
00011 #include <rx.h>
00012 #include <map>
00013 #include <list>
00014 #include <pthread.h>
00015 #include <SeVec3d.h>
00016 #include <SeExpression.h>
00017 #include <SeExprFunc.h>
00018 #include <RixInterfaces.h>
00019 #include <cstdlib>
00020 #include <cstring>
00021 #include "immutable_hash_map.h"
00022
00023 namespace{
00024 RixTokenStorage* tokenizer;
00025 inline const char* tokenize(const char* str)
00026 {
00027 const char* result = tokenizer->GetToken(str);
00028 return result;
00029 }
00030
00031 int SeTokenize(RslContext* , int , const RslArg* argv[])
00032 {
00033 RslStringIter result(argv[0]);
00034 const char* str = *RslStringIter(argv[1]);
00035 *result = (RtString) tokenize(str);
00036 return 0;
00037 }
00038
00039 struct SeRmanVarMap {
00040 immutable_hash_map<const char*, int> indexMap;
00041 std::vector<int> groupStarts;
00042 std::vector<int> groupCounts;
00043 std::vector<int> groupIndices;
00044
00045 SeRmanVarMap(int nvars, const char** varnames, int* varindices, int* groupstarts)
00046 : indexMap(varnames, varindices, nvars),
00047 groupStarts(groupstarts, groupstarts + nvars),
00048 groupCounts(nvars),
00049 groupIndices(nvars)
00050 {
00051 int groupIndex = 0, i, j;
00052 for (i = 0; i < nvars; ) {
00053
00054 for (j = i+1; j < nvars; j++) {
00055 if (groupStarts[j] != groupStarts[i]) break;
00056 }
00057 int groupCount = j - i;
00058
00059 for (; i < j; i++) {
00060 groupCounts[i] = groupCount;
00061 groupIndices[i] = groupIndex;
00062 }
00063 groupIndex++;
00064 }
00065
00066 for(int i=0;i<indexMap._keys.size();i++){
00067 const char* name=indexMap._keys[i]?indexMap._keys[i]:"";
00068 }
00069 }
00070 };
00071 typedef std::map<const char*, SeRmanVarMap*> SeRmanVarMapMap;
00072 typedef std::map<const char*, int> SeRmanExprMap;
00073 typedef std::vector<int> SeVarBinding;
00074
00075 class SeRmanExpr;
00076
00077
00079 struct ThreadData {
00080
00081
00082 RixMessages *msgs;
00083
00084
00085 SeRmanVarMapMap varmaps;
00086
00087 SeRmanVarMap& getVarMap(const char* varMapHandle)
00088 {
00089 SeRmanVarMap*& varmap = varmaps[varMapHandle];
00090 if (!varmap) {
00091
00092 char* varlist = strdup(varMapHandle);
00093 std::vector<const char*> varnames;
00094 std::vector<int> groupStarts;
00095
00096
00097 char* varlist_end = 0;
00098 char* vargroup = strtok_r(varlist, " ", &varlist_end);
00099 do {
00100
00101 int groupStart = varnames.size();
00102 char* vargroup_end = 0;
00103 char* var = strtok_r(vargroup, ",", &vargroup_end);
00104 do {
00105 varnames.push_back(tokenize(var));
00106 groupStarts.push_back(groupStart);
00107 } while (var = strtok_r(0, ",", &vargroup_end));
00108 } while (vargroup = strtok_r(0, " ", &varlist_end));
00109
00110
00111 int nvars = varnames.size();
00112 int* varindices = (int*) alloca(sizeof(int)*nvars);
00113 for (int i = 0; i < nvars; i++){
00114 varindices[i] = i;
00115 }
00116 varmap = new SeRmanVarMap(nvars, &varnames[0], &varindices[0], &groupStarts[0]);
00117 free(varlist);
00118 }
00119 return *varmap;
00120 }
00121
00122 void ptError (char* fmt, ...) {
00123 static char strbuf[1024];
00124 va_list ap;
00125 va_start(ap, fmt);
00126 vsprintf(strbuf, fmt, ap);
00127 msgs->Error("%s", strbuf);
00128 va_end(ap);
00129 }
00130
00131 void ptWarn (char* fmt, ...) {
00132 static char strbuf[1024];
00133 va_list ap;
00134 va_start(ap, fmt);
00135 vsprintf(strbuf, fmt, ap);
00136 msgs->Warning("%s", strbuf);
00137 va_end(ap);
00138 }
00139
00140 SeRmanExprMap exprmap;
00141 std::vector<SeRmanExpr*> exprs;
00142
00143 RtColor* varValues;
00144 float* Ci;
00145
00146 ThreadData()
00147 {
00148 msgs = (RixMessages*)
00149 RxGetRixContext()->GetRixInterface(k_RixMessages);
00150 exprs.push_back(0);
00151 }
00152 };
00153
00155 ThreadData& getThreadData(RslContext* ctx)
00156 {
00157 ThreadData* td = (ThreadData*) ctx->GetThreadData();
00158 if (!td) {
00159 td = new ThreadData;
00160 ctx->SetThreadData(td);
00161 }
00162 return *td;
00163 }
00164
00166 class SeRmanVar : public SeExprVarRef
00167 {
00168 public:
00169 SeRmanVar(ThreadData& td) : td(td), index(0) {}
00170 virtual bool isVec() { return 1; }
00171 void setIndex(int i) { index = i; }
00172 virtual void eval(const SeExprVarNode* node, SeVec3d& result)
00173 {
00174 RtColor& c = td.varValues[index];
00175 result = c;
00176 }
00177 private:
00178 ThreadData& td;
00179 int index;
00180 };
00181
00183 class AttrVar : public SeExprVectorVarRef
00184 {
00185 std::string name;
00186 SeVec3d value;
00187 public:
00188
00189 AttrVar()
00190 :name(""),value(0.)
00191 {}
00192
00193 AttrVar(const std::string& nameIn)
00194 :value(0.)
00195 {
00196
00197 size_t pos=nameIn.find("::");
00198 name=nameIn.substr(0, pos)+nameIn.substr(pos+1,nameIn.size()-(pos-1));
00199 }
00200
00201 std::string getName(){return name;}
00202
00203 void doLookup()
00204 {
00205
00206 float fbuf16[16];
00207
00208 RxInfoType_t rxType;
00209 int count;
00210 int statusOpt, statusAttr;
00211
00212
00213 statusOpt = RxOption (name.c_str(), fbuf16, sizeof (fbuf16),
00214 &rxType, &count);
00215 statusAttr = RxAttribute (name.c_str(), fbuf16, sizeof (fbuf16),
00216 &rxType, &count);
00217
00218 if (statusAttr != 0 && statusOpt != 0) {
00219
00220 value.setValue(0.0, 0.0, 0.0);
00221 return;
00222 }
00223
00224
00225 switch (rxType)
00226 {
00227 case RxInfoFloat:
00228
00229 value.setValue (fbuf16[0], fbuf16[0], fbuf16[0]);
00230 break;
00231 case RxInfoColor:
00232 case RxInfoNormal:
00233 case RxInfoVector:
00234 case RxInfoPoint:
00235
00236 value.setValue (fbuf16[0], fbuf16[1], fbuf16[2]);
00237 break;
00238 default:
00239
00240
00241 break;
00242 }
00243 }
00244
00245
00246 virtual void eval(const SeExprVarNode* node, SeVec3d& result)
00247 {result = value;}
00248
00249 };
00250
00251
00253 class SeRmanExpr : public SeExpression {
00254 public:
00255 SeRmanExpr(const std::string &expr, ThreadData& td)
00256 : SeExpression(expr), _td(td), _boundVarMap(-1) {}
00257
00258 virtual SeExprVarRef* resolveVar(const std::string& name) const
00259 {
00260 if (name.find("::") != std::string::npos) {
00261 int i, size;
00262 for (i = 0, size = _attrrefs.size(); i < size; i++)
00263
00264 if (name == _attrrefs[i]->getName())
00265 return _attrrefs[i];
00266
00267
00268 AttrVar* attrVar = new AttrVar( name);
00269 _attrrefs.push_back(attrVar);
00270 return attrVar;
00271 }
00272
00273 const char* token = tokenize(name.c_str());
00274 for (int i = 0, size = _varrefs.size(); i < size; i++)
00275 if (_varnames[i] == token) return _varrefs[i];
00276 SeRmanVar* var = new SeRmanVar(_td);
00277 _varnames.push_back(token);
00278 _varrefs.push_back(var);
00279 return var;
00280 }
00281
00282 SeVarBinding* bindVars(const char* varMapHandle)
00283 {
00284 SeVarBinding*& binding = _bindings[varMapHandle];
00285 if (!binding) {
00286 binding = new SeVarBinding;
00287
00288
00289 SeRmanVarMap& varmap = _td.getVarMap(varMapHandle);
00290
00291 int nvars = _varnames.size();
00292 binding->resize(nvars);
00293 for (int i = 0; i < nvars; i++) {
00294 const char* name = _varnames[i];
00295 int index = varmap.indexMap[name];
00296 if (!index) {
00297
00298
00299
00300
00301
00302 char msg[] = "SeRmanExpr error: undefined variable \"$%s\"";
00303 _td.ptError(msg, name);
00304 }
00305 (*binding)[i] = index;
00306 }
00307 }
00308 _bindstack.push_back(binding);
00309 return binding;
00310 }
00311
00312 void lookupAttrs()
00313 {
00314 int nattrs = _attrrefs.size();
00315
00316
00317 for (int i = 0; i < nattrs; i++) {
00318 _attrrefs[i]->doLookup();
00319 }
00320 }
00321
00322 void setVarIndices()
00323 {
00324
00325
00326 SeVarBinding* binding = _bindstack.back();
00327 if (binding) {
00328 for (int i = 0, size = binding->size(); i < size; i++)
00329 _varrefs[i]->setIndex((*binding)[i]);
00330 }
00331 }
00332
00333 void unbindVars()
00334 {
00335 _bindstack.pop_back();
00336 }
00337
00338 private:
00339 mutable std::vector<const char*> _varnames;
00340 mutable std::vector<SeRmanVar*> _varrefs;
00341 mutable std::vector<AttrVar*> _attrrefs;
00342 mutable std::map<const char*, SeVarBinding*> _bindings;
00343 mutable std::vector<SeVarBinding*> _bindstack;
00344 ThreadData& _td;
00345 int _boundVarMap;
00346 };
00347
00348 void init(RixContext* ctx)
00349 {
00350 tokenizer = (RixTokenStorage*) ctx->GetRixInterface(k_RixGlobalTokenData);
00351
00352
00353 char* plugins_ptr = getenv("SE_EXPR_PLUGINS");
00354 std::string plugins;
00355 if (plugins_ptr) {
00356 plugins = plugins_ptr;
00357 unsetenv("SE_EXPR_PLUGINS");
00358 }
00359
00360
00361 SeExprFunc::init();
00362
00363
00364
00365 if (plugins_ptr)
00366 setenv("SE_EXPR_PLUGINS", plugins.c_str(), 1);
00367 }
00368
00369 int SeExprBind(RslContext* ctx, int argc, const RslArg* argv[])
00370 {
00371 RslFloatIter result(argv[0]);
00372 const char* exprstr = *RslStringIter(argv[1]);
00373 const char* varmapHandle = *RslStringIter(argv[2]);
00374
00375 if (!exprstr[0]) {
00376
00377 *result = 0;
00378 argv[3]->GetResizer()->Resize(0);
00379 return 0;
00380 }
00381
00382
00383 ThreadData& td = getThreadData(ctx);
00384 int& index = td.exprmap[exprstr];
00385 if (!index) {
00386
00387 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
00388 pthread_mutex_lock(&mutex);
00389 SeRmanExpr* expr = new SeRmanExpr(exprstr, td);
00390 bool valid = expr->isValid();
00391 pthread_mutex_unlock(&mutex);
00392 if (!valid) {
00393 char msg[] = "SeRmanExpr error: %s";
00394 td.ptError(msg, expr->parseError().c_str());
00395 index = 0;
00396 }
00397 else index = td.exprs.size();
00398
00399 td.exprs.push_back(expr);
00400 }
00401
00402 *result = index;
00403 if (index) {
00404
00405 SeRmanExpr* expr = td.exprs[index];
00406 expr->lookupAttrs();
00407 SeVarBinding& binding = *expr->bindVars(varmapHandle);
00408 int nvars = binding.size();
00409 argv[3]->GetResizer()->Resize(nvars);
00410 #if RSL_PLUGIN_VERSION >= 6
00411 RslFloatArrayIter varIndices(argv[3]);
00412 #else
00413 float* varIndices = *RslFloatArrayIter(argv[3]);
00414 #endif
00415 for (int i = 0; i < nvars; i++) {
00416 varIndices[i] = binding[i];
00417 }
00418 }
00419 else {
00420 argv[3]->GetResizer()->Resize(0);
00421 }
00422 return 0;
00423 }
00424
00425 int SeExprEval(RslContext* ctx, int argc, const RslArg* argv[])
00426 {
00427 int index = int(*RslFloatIter(argv[1]));
00428 RslColorArrayIter varValuesIter=argv[2];
00429 RslColorIter CiIter=argv[3];
00430
00431 int numVals = argv[3]->NumValues();
00432
00433 if (!index) {
00434 for (int i = 0; i < numVals; i++, CiIter++, varValuesIter++) {
00435 float* Ci = *CiIter;
00436 Ci[0] = Ci[1] = Ci[2] = 0;
00437 }
00438 return 0;
00439 }
00440
00441 ThreadData& td = getThreadData(ctx);
00442
00443 SeRmanExpr& expr = *td.exprs[index];
00444 expr.setVarIndices();
00445
00446 bool isThreadSafe = expr.isThreadSafe();
00447
00448 for (int i = 0; i < numVals; i++, CiIter++, varValuesIter++) {
00449 td.varValues = &varValuesIter[0];
00450 float* Ci = td.Ci = *CiIter;
00451
00452
00453 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
00454 if (!isThreadSafe)
00455 pthread_mutex_lock(&mutex);
00456
00457 SeVec3d v = expr.evaluate();
00458
00459 if (!isThreadSafe)
00460 pthread_mutex_unlock(&mutex);
00461
00462
00463 if (!isfinite(v[0]) || !isfinite(v[1]) || !isfinite(v[2])) {
00464 char msg[] = "Shader Expression: %s: resulted in NAN. Setting val to 1";
00465 td.ptWarn (msg, expr.getExpr().c_str());
00466 v[0] = v[1] = v[2] = 1;
00467 }
00468
00469 Ci[0] = v[0];
00470 Ci[1] = v[1];
00471 Ci[2] = v[2];
00472 }
00473
00474 expr.unbindVars();
00475 return 0;
00476 }
00477 }
00478
00479 extern "C" {
00480 static RslFunction funcs[] = {
00481
00482 {"string SeTokenize(string)", SeTokenize, NULL, NULL },
00483
00484
00485 {"float SeExprBind(string, string, output uniform float[])", SeExprBind, NULL, NULL },
00486
00487
00488 {"void SeExprEval(uniform float, color[], output color)", SeExprEval, NULL, NULL },
00489 NULL
00490 };
00491
00492 RslFunctionTable RslPublicFunctions(funcs, init);
00493 }