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 }