Fixed:
[blender.git] / source / blender / yafray / intern / export_Plugin.cpp
1 #include"export_Plugin.h"
2
3 #include <math.h>
4 using namespace std;
5
6
7 #ifdef WIN32 
8
9 #include<windows.h>
10
11 #ifndef FILE_MAXDIR
12 #define FILE_MAXDIR  160
13 #endif
14
15 #ifndef FILE_MAXFILE
16 #define FILE_MAXFILE 80
17 #endif
18
19
20 static string find_path()
21 {
22         HKEY    hkey;
23         DWORD dwType, dwSize;
24
25         if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,"Software\\YafRay Team\\YafRay",0,KEY_READ,&hkey)==ERROR_SUCCESS)
26         {
27                 dwType = REG_EXPAND_SZ;
28                 dwSize = MAX_PATH;
29                 DWORD dwStat;
30
31                 char *pInstallDir=new char[MAX_PATH];
32
33                 dwStat=RegQueryValueEx(hkey, TEXT("InstallDir"), 
34                         NULL, NULL,(LPBYTE)pInstallDir, &dwSize);
35                 
36                 if (dwStat == NO_ERROR)
37                 {
38                         string res=pInstallDir;
39                         delete [] pInstallDir;
40                         return res;
41                 }
42                 else
43                         cout << "Couldn't READ \'InstallDir\' value. Is yafray correctly installed?\n";
44                 delete [] pInstallDir;
45
46                 RegCloseKey(hkey);
47         }       
48         else
49                 cout << "Couldn't FIND registry key for yafray, is it installed?\n";
50
51         return string("");
52
53 }
54
55 static int createDir(char* name)
56 {
57         if (BLI_exists(name))
58                 return 2;       //exists
59         if (CreateDirectory((LPCTSTR)(name), NULL)) {
60                 cout << "Directory: " << name << " created\n";
61                 return 1;       // created
62         }
63         else    {
64                 cout << "Could not create directory: " << name << endl;
65                 return 0;       // fail
66         }
67 }
68
69 extern "C" { extern char bprogname[]; }
70
71 // add drive character if not in path string, using blender executable location as reference
72 static void addDrive(string &path)
73 {
74         int sp = path.find_first_of(":");
75         if (sp==-1) {
76                 string blpath = bprogname;
77                 sp = blpath.find_first_of(":");
78                 if (sp!=-1) path = blpath.substr(0, sp+1) + path;
79         }
80 }
81
82 #else
83
84 #include <sys/stat.h>
85 #include <sys/types.h>
86 #include <sys/wait.h>
87 #include <signal.h>
88 #include <stdlib.h>
89 #include <unistd.h>
90 #endif
91
92 static string YafrayPath()
93 {
94 #ifdef WIN32
95         string path=find_path();
96         return path; 
97         
98 #else
99         static char *alternative[]=
100         {
101                 "/usr/local/lib/",
102                 "/usr/lib/",
103                 NULL
104         };
105
106         for(int i=0;alternative[i]!=NULL;++i)
107         {
108                 string fp=string(alternative[i])+"libyafrayplugin.so";
109                 struct stat st;
110                 if(stat(fp.c_str(),&st)<0) continue;
111                 if(st.st_mode&S_IROTH) return fp;
112         }
113         return "";
114 #endif
115 }
116
117 static string YafrayPluginPath()
118 {
119 #ifdef WIN32
120         return find_path()+"\\plugins";
121 #else
122         static char *alternative[]=
123         {
124                 "/usr/local/lib/yafray",
125                 "/usr/lib/yafray",
126                 NULL
127         };
128
129         for(int i=0;alternative[i]!=NULL;++i)
130         {
131                 struct stat st;
132                 if(stat(alternative[i],&st)<0) continue;
133                 if(S_ISDIR(st.st_mode) && (st.st_mode&S_IXOTH)) return alternative[i];
134         }
135         return "";
136 #endif
137 }
138
139
140
141 yafrayPluginRender_t::~yafrayPluginRender_t()
142 {
143         if(yafrayGate!=NULL) delete yafrayGate;
144         if(handle!=NULL) PIL_dynlib_close(handle);
145 #ifdef WIN32
146         if(corehandle!=NULL) PIL_dynlib_close(corehandle);
147 #endif
148 }
149
150 bool yafrayPluginRender_t::initExport()
151 {
152         if(handle==NULL)
153         {
154                 string location=YafrayPath();
155 #ifdef WIN32
156                 /* Win 32 loader cannot find needed libs in yafray dir, so we have to load them
157                  * by hand. This could be fixed using setdlldirectory function, but it is not
158                  * available in all win32 versions
159                  */
160                 corehandle=PIL_dynlib_open((char *)(location+"\\yafraycore.dll").c_str());
161                 if(corehandle==NULL)
162                 {
163                         cerr<<"Error loading yafray plugin: "<<PIL_dynlib_get_error_as_string(corehandle)<<endl;
164                         return false;
165                 }
166                 location+="\\yafrayplugin.dll";
167 #endif
168
169                 handle=PIL_dynlib_open((char *)location.c_str());
170                  if(handle==NULL)
171                 {
172                         //cerr<<"Error loading yafray plugin: "<<dlerror()<<endl;
173                         cerr<<"Error loading yafray plugin: "<<PIL_dynlib_get_error_as_string(handle)<<endl;
174                         return false;
175                 }
176                 yafray::yafrayConstructor *constructor;
177                 constructor=(yafray::yafrayConstructor *)PIL_dynlib_find_symbol(handle,YAFRAY_SYMBOL);
178                 if(constructor==NULL)
179                 {
180                         cerr<<"Error loading yafray plugin: "<<PIL_dynlib_get_error_as_string(handle)<<endl;
181                         return false;
182                 }
183                 yafrayGate=constructor(1,YafrayPluginPath());
184                 
185                 cout<<"YafRay plugin loaded"<<endl;
186         }
187         
188         if(R.rectot == NULL)
189                 R.rectot = (unsigned int *)MEM_callocN(sizeof(int)*R.rectx*R.recty, "rectot");
190
191         for (unsigned short y=0;y<R.recty;y++) {
192                 unsigned char* bpt = (unsigned char*)R.rectot + ((((R.recty-1)-y)*R.rectx)<<2);
193                 for (unsigned short x=0;x<R.rectx;x++) {
194                         bpt[2] = 128;
195                         bpt[1] = 0;
196                         bpt[0] = 0;
197                         bpt[3] = 255;
198                         bpt += 4;
199                 }
200         }
201         
202         cout<<"Image allocated"<<endl;
203         return true;
204 }
205
206 bool yafrayPluginRender_t::writeRender()
207 {
208         yafray::paramMap_t params;
209         params["camera_name"]=yafray::parameter_t("MAINCAM");
210         params["raydepth"]=yafray::parameter_t((float)R.r.YF_raydepth);
211         params["gamma"]=yafray::parameter_t(R.r.YF_gamma);
212         params["exposure"]=yafray::parameter_t(R.r.YF_exposure);
213         if (R.r.YF_AA)
214         {
215                 params["AA_passes"] = yafray::parameter_t((int)R.r.YF_AApasses);
216                 params["AA_minsamples"] = yafray::parameter_t(R.r.YF_AAsamples);
217                 params["AA_pixelwidth"] = yafray::parameter_t(R.r.YF_AApixelsize);
218                 params["AA_threshold"] = yafray::parameter_t(R.r.YF_AAthreshold);
219         }
220         else
221         {
222                 if ((R.r.GImethod!=0) && (R.r.GIquality>1) && (!R.r.GIcache))
223                 {
224                         params["AA_passes"]=yafray::parameter_t(5);
225                         params["AA_minsamples"]=yafray::parameter_t(5);
226                 }
227                 else if ((R.r.mode & R_OSA) && (R.r.osa)) 
228                 {
229                         params["AA_passes"]=yafray::parameter_t((R.r.osa%4)==0 ? R.r.osa/4 : 1);
230                         params["AA_minsamples"]=yafray::parameter_t((R.r.osa%4)==0 ? 4 : R.r.osa);
231                 }
232                 else 
233                 {
234                         params["AA_passes"]=yafray::parameter_t(0);
235                         params["AA_minsamples"]=yafray::parameter_t(1);
236                 }
237                 params["AA_pixelwidth"]=yafray::parameter_t(1.5);
238                 params["AA_threshold"]=yafray::parameter_t(0.05f);
239         }
240         if (hasworld) params["background_name"]=yafray::parameter_t("world_background");
241         params["bias"]=yafray::parameter_t(R.r.YF_raybias);
242         //params["outfile"]=yafray::parameter_t(imgout);
243         blenderYafrayOutput_t output;
244         yafrayGate->render(params,output);
245         cout<<"render finished"<<endl;
246         yafrayGate->clear();
247         return true;
248 }
249
250 bool yafrayPluginRender_t::finishExport()
251 {
252         //displayImage();
253         return true;
254 }
255
256 // displays the image rendered with xml export
257 // Now loads rendered image into blender renderbuf.
258 void yafrayPluginRender_t::displayImage()
259 {
260         // although it is possible to load the image using blender,
261         // maybe it is best to just do a read here, for now the yafray output is always a raw tga anyway
262
263         // rectot already freed in initrender
264         R.rectot = (unsigned int *)MEM_callocN(sizeof(int)*R.rectx*R.recty, "rectot");
265
266         FILE* fp = fopen(imgout.c_str(), "rb");
267         if (fp==NULL) {
268                 cout << "YAF_displayImage(): Could not open image file\n";
269                 return;
270         }
271
272         unsigned char header[18];
273         fread(&header, 1, 18, fp);
274         unsigned short width = (unsigned short)(header[12] + (header[13]<<8));
275         unsigned short height = (unsigned short)(header[14] + (header[15]<<8));
276         unsigned char byte_per_pix = (unsigned char)(header[16]>>3);
277         // read past any id (none in this case though)
278         unsigned int idlen = (unsigned int)header[0];
279         if (idlen) fseek(fp, idlen, SEEK_CUR);
280
281         // read data directly into buffer, picture is upside down
282         for (unsigned short y=0;y<height;y++) {
283                 unsigned char* bpt = (unsigned char*)R.rectot + ((((height-1)-y)*width)<<2);
284                 for (unsigned short x=0;x<width;x++) {
285                         bpt[2] = (unsigned char)fgetc(fp);
286                         bpt[1] = (unsigned char)fgetc(fp);
287                         bpt[0] = (unsigned char)fgetc(fp);
288                         if (byte_per_pix==4)
289                                 bpt[3] = (unsigned char)fgetc(fp);
290                         else
291                                 bpt[3] = 255;
292                         bpt += 4;
293                 }
294         }
295
296         fclose(fp);
297         fp = NULL;
298 }
299
300
301 #ifdef WIN32
302 #define MAXPATHLEN MAX_PATH
303 #else
304 #include <sys/param.h>
305 #endif
306 static void adjustPath(string &path)
307 {
308         // if relative, expand to full path
309         char cpath[MAXPATHLEN];
310         strcpy(cpath, path.c_str());
311         BLI_convertstringcode(cpath, G.sce, 0);
312         path = cpath;
313 #ifdef WIN32
314         // add drive char if not there
315         addDrive(path);
316 #endif
317 }
318
319
320 static string noise2string(short nbtype)
321 {
322         switch (nbtype) {
323                 case TEX_BLENDER:
324                         return "blender";
325                 case TEX_STDPERLIN:
326                         return "stdperlin";
327                 case TEX_VORONOI_F1:
328                         return "voronoi_f1";
329                 case TEX_VORONOI_F2:
330                         return "voronoi_f2";
331                 case TEX_VORONOI_F3:
332                         return "voronoi_f3";
333                 case TEX_VORONOI_F4:
334                         return "voronoi_f4";
335                 case TEX_VORONOI_F2F1:
336                         return "voronoi_f2f1";
337                 case TEX_VORONOI_CRACKLE:
338                         return "voronoi_crackle";
339                 case TEX_CELLNOISE:
340                         return "cellnoise";
341                 default:
342                 case TEX_NEWPERLIN:
343                         return "newperlin";
344         }
345 }
346
347 void yafrayPluginRender_t::writeTextures()
348 {
349         string ts;
350         yafray::paramMap_t params;
351         list<yafray::paramMap_t> lparams;
352         for (map<string, MTex*>::const_iterator blendtex=used_textures.begin();
353                                                 blendtex!=used_textures.end();++blendtex) 
354         {
355                 MTex* mtex = blendtex->second;
356                 Tex* tex = mtex->tex;
357                 // name is image name instead of texture name when type is image (see TEX_IMAGE case below)
358                 // (done because of possible combinations of 'TexFace' images and regular image textures, to avoid duplicates)
359                 if (tex->type!=TEX_IMAGE) params["name"] = yafray::parameter_t(blendtex->first);
360
361                 float nsz = tex->noisesize;
362                 if (nsz!=0.f) nsz=1.f/nsz;
363
364                 // noisebasis type
365                 string ntype = noise2string(tex->noisebasis);
366
367                 switch (tex->type) {
368                         case TEX_STUCCI:
369                                 // stucci is clouds as bump, but could be added to yafray to handle both wall in/out as well.
370                                 // noisedepth must be at least 1 in yafray
371                         case TEX_CLOUDS: {
372                                 params["type"] = yafray::parameter_t("clouds");
373                                 params["depth"] = yafray::parameter_t(tex->noisedepth+1);
374                                 params["size"] = yafray::parameter_t(nsz);
375                                 params["noise_type"] = ntype;
376                                 break;
377                         }
378                         case TEX_WOOD:
379                         {
380                                 params["type"] = yafray::parameter_t("wood");
381                                 params["depth"] = yafray::parameter_t(tex->noisedepth+1);
382                                 params["turbulence"] = yafray::parameter_t(tex->turbul);
383                                 params["ringscale_x"] = yafray::parameter_t(mtex->size[0]);
384                                 params["ringscale_y"] = yafray::parameter_t(mtex->size[1]);
385                                 ts = "on";
386                                 if (tex->noisetype==TEX_NOISESOFT) ts = "off";
387                                 params["hard"] = yafray::parameter_t(ts);
388                                 break;
389                         }
390                         case TEX_MARBLE: 
391                         {
392                                 params["type"]=yafray::parameter_t("marble");
393                                 params["depth"]=yafray::parameter_t(tex->noisedepth+1);
394                                 params["turbulence"]=yafray::parameter_t(tex->turbul);
395                                 ts = "on";
396                                 if (tex->noisetype==TEX_NOISESOFT) ts = "off";
397                                 params["hard"]=yafray::parameter_t(ts);
398                                 if (tex->stype==1)
399                                         params["sharpness"]=yafray::parameter_t(5);
400                                 else if (tex->stype==2)
401                                         params["sharpness"]=yafray::parameter_t(10);
402                                 else
403                                         params["sharpness"]=yafray::parameter_t(1);
404                                 break;
405                         }
406                         case TEX_IMAGE: 
407                         {
408                                 Image* ima = tex->ima;
409                                 if (ima) {
410                                         // remove from imagetex list to avoid possible duplicates when TexFace used
411                                         imagetex.erase(ima);
412                                         params["type"] = yafray::parameter_t("image");
413                                         params["name"] = yafray::parameter_t(ima->id.name);
414                                         string texpath = ima->name;
415                                         adjustPath(texpath);
416                                         params["filename"] = yafray::parameter_t(texpath);
417                                 }
418                                 break;
419                         }
420                         case TEX_VORONOI:
421                         {
422                                 params["type"] = yafray::parameter_t("voronoi");
423                                 ts = "int";
424                                 if (tex->vn_coltype==1)
425                                         ts = "col1";
426                                 else if (tex->vn_coltype==2)
427                                         ts = "col2";
428                                 else if (tex->vn_coltype==3)
429                                         ts = "col3";
430                                 params["color_type"] = yafray::parameter_t(ts);
431                                 params["weight1"] = yafray::parameter_t(tex->vn_w1);
432                                 params["weight2"] = yafray::parameter_t(tex->vn_w2);
433                                 params["weight3"] = yafray::parameter_t(tex->vn_w3);
434                                 params["weight4"] = yafray::parameter_t(tex->vn_w4);
435                                 params["mk_exponent"] = yafray::parameter_t(tex->vn_mexp);
436                                 params["intensity"] = yafray::parameter_t(tex->ns_outscale);
437                                 params["size"] = yafray::parameter_t(nsz);
438                                 ts = "actual";
439                                 if (tex->vn_distm==TEX_DISTANCE_SQUARED)
440                                         ts = "squared";
441                                 else if (tex->vn_distm==TEX_MANHATTAN)
442                                         ts = "manhattan";
443                                 else if (tex->vn_distm==TEX_CHEBYCHEV)
444                                         ts = "chebychev";
445                                 else if (tex->vn_distm==TEX_MINKOVSKY_HALF)
446                                         ts = "minkovsky_half";
447                                 else if (tex->vn_distm==TEX_MINKOVSKY_FOUR)
448                                         ts = "minkovsky_four";
449                                 else if (tex->vn_distm==TEX_MINKOVSKY)
450                                         ts = "minkovsky";
451                                 params["distance_metric"] = yafray::parameter_t(ts);
452                                 break;
453                         }
454                         case TEX_MUSGRAVE:
455                         {
456                                 params["type"] = yafray::parameter_t("musgrave");
457                                 switch (tex->stype) {
458                                         case TEX_MFRACTAL:
459                                                 ts = "multifractal";
460                                                 break;
461                                         case TEX_RIDGEDMF:
462                                                 ts = "ridgedmf";
463                                                 break;
464                                         case TEX_HYBRIDMF:
465                                                 ts = "hybridmf";
466                                                 break;
467                                         case TEX_HTERRAIN:
468                                                 ts = "heteroterrain";
469                                                 break;
470                                         default:
471                                         case TEX_FBM:
472                                                 ts = "fBm";
473                                 }
474                                 params["musgrave_type"] = yafray::parameter_t(ts);
475                                 params["noise_type"] = yafray::parameter_t(ntype);
476                                 params["H"] = yafray::parameter_t(tex->mg_H);
477                                 params["lacunarity"] = yafray::parameter_t(tex->mg_lacunarity);
478                                 params["octaves"] = yafray::parameter_t(tex->mg_octaves);
479                                 if ((tex->stype==TEX_HTERRAIN) || (tex->stype==TEX_RIDGEDMF) || (tex->stype==TEX_HYBRIDMF)) {
480                                         params["offset"] = yafray::parameter_t(tex->mg_offset);
481                                         if ((tex->stype==TEX_RIDGEDMF) || (tex->stype==TEX_HYBRIDMF))
482                                                 params["gain"] = yafray::parameter_t(tex->mg_gain);
483                                 }
484                                 params["size"] = yafray::parameter_t(nsz);
485                                 params["intensity"] = yafray::parameter_t(tex->ns_outscale);
486                                 break;
487                         }
488                         case TEX_DISTNOISE:
489                         {
490                                 params["type"] = yafray::parameter_t("distorted_noise");
491                                 params["distort"] = yafray::parameter_t(tex->dist_amount);
492                                 params["size"] = yafray::parameter_t(nsz);
493                                 params["noise_type1"] = yafray::parameter_t(ntype);
494                                 params["noise_type2"] = yafray::parameter_t(noise2string(tex->noisebasis2));
495                         }
496                         default:
497                                 cout << "Unsupported texture type\n";
498                 }
499                 yafrayGate->addShader(params, lparams);
500
501                 // colorbands
502                 if (tex->flag & TEX_COLORBAND) 
503                 {
504                         ColorBand* cb = tex->coba;
505                         if (cb) 
506                         {
507                                 params.clear();
508                                 params["type"]=yafray::parameter_t("colorband");
509                                 params["name"]=yafray::parameter_t(blendtex->first + "_coba");
510                                 params["input"]=yafray::parameter_t(blendtex->first);
511                                 for (int i=0;i<cb->tot;i++) 
512                                 {
513                                         yafray::paramMap_t mparams;
514                                         mparams["value"]=yafray::parameter_t(cb->data[i].pos);
515                                         mparams["color"]=yafray::parameter_t(yafray::colorA_t(cb->data[i].r,
516                                                                                                                                                                                                                                                                 cb->data[i].g,
517                                                                                                                                                                                                                                                                 cb->data[i].b,
518                                                                                                                                                                                                                                                                 cb->data[i].a));
519                                         lparams.push_back(mparams);
520                                 }
521                                 yafrayGate->addShader(params, lparams);
522                         }
523                 }
524
525         }
526
527         // If used, textures for the material 'TexFace' case
528         if (!imagetex.empty()) {
529                 for (map<Image*, Material*>::const_iterator imgtex=imagetex.begin();
530                                         imgtex!=imagetex.end();++imgtex)
531                 {
532                         params.clear();
533                         params["name"] = yafray::parameter_t(imgtex->first->id.name);
534                         params["type"] = yafray::parameter_t("image");
535                         string texpath(imgtex->first->name);
536                         adjustPath(texpath);
537                         params["filename"] = yafray::parameter_t(texpath);
538                         yafrayGate->addShader(params, lparams);
539                 }
540         }
541
542 }
543
544
545 void yafrayPluginRender_t::writeShader(const string &shader_name, Material* matr, const string &facetexname)
546 {
547         yafray::paramMap_t params;
548         params["type"] = yafray::parameter_t("blendershader");
549         params["name"] = yafray::parameter_t(shader_name);
550         float diff = matr->alpha;
551         params["color"] = yafray::parameter_t(yafray::color_t(matr->r*diff, matr->g*diff, matr->b*diff));
552         params["specular_color"] = yafray::parameter_t(yafray::color_t(matr->specr, matr->specg, matr->specb));
553         params["mirror_color"] = yafray::parameter_t(yafray::color_t(matr->mirr, matr->mirg, matr->mirb));
554         params["diffuse_reflect"] = yafray::parameter_t(matr->ref);
555         params["specular_amount"] = yafray::parameter_t(matr->spec);
556         params["hard"] = yafray::parameter_t(matr->har);
557         params["alpha"] = yafray::parameter_t(matr->alpha);
558         
559         // if no GI used, the GIpower parameter is not always initialized, so in that case ignore it
560         float bg_mult = (R.r.GImethod==0) ? 1 : R.r.GIpower;
561         params["emit"]=yafray::parameter_t(matr->emit*bg_mult);
562
563         // reflection/refraction
564         if ( (matr->mode & MA_RAYMIRROR) || (matr->mode & MA_RAYTRANSP) )
565                 params["IOR"] = yafray::parameter_t(matr->ang);
566         if (matr->mode & MA_RAYMIRROR) 
567         {
568                 float rf = matr->ray_mirror;
569                 // blender uses mir color for reflection as well
570                 params["reflected"] = yafray::parameter_t(yafray::color_t(matr->mirr, matr->mirg, matr->mirb));
571                 params["min_refle"] = yafray::parameter_t(rf);
572                 if (matr->ray_depth>maxraydepth) maxraydepth = matr->ray_depth;
573         }
574         if (matr->mode & MA_RAYTRANSP) 
575         {
576                 float tr = 1.0-matr->alpha;
577                 params["transmitted"]=yafray::parameter_t(yafray::color_t(matr->r*tr, matr->g*tr, matr->b*tr));
578                 // tir on by default
579                 params["tir"] = yafray::parameter_t("on");
580                 if (matr->ray_depth_tra>maxraydepth) maxraydepth = matr->ray_depth_tra;
581         }
582
583         string Mmode = "";
584         if (matr->mode & MA_TRACEBLE) Mmode += "traceable";
585         if (matr->mode & MA_SHADOW) Mmode += " shadow";
586         if (matr->mode & MA_SHLESS) Mmode += " shadeless";
587         if (matr->mode & MA_VERTEXCOL) Mmode += " vcol_light";
588         if (matr->mode & MA_VERTEXCOLP) Mmode += " vcol_paint";
589         if (matr->mode & MA_ZTRA) Mmode += " ztransp";
590         if (matr->mode & MA_ONLYSHADOW) Mmode += " onlyshadow";
591         if (Mmode!="") params["matmodes"] = yafray::parameter_t(Mmode);
592
593         // modulators
594         list<yafray::paramMap_t> lparams;
595
596         // first modulator is the texture of the face, if used (TexFace mode)
597         if (facetexname.length()!=0) {
598                         yafray::paramMap_t mparams;
599                         mparams["input"] = yafray::parameter_t(facetexname);
600                         mparams["color"] = yafray::parameter_t(1);
601                         lparams.push_back(mparams);
602         }
603         
604         for (int m2=0;m2<8;m2++)
605         {
606                 if (matr->septex & (1<<m2)) continue;// all active channels
607                 // ignore null mtex
608                 MTex* mtex = matr->mtex[m2];
609                 if (mtex==NULL) continue;
610                 // ignore null tex
611                 Tex* tex = mtex->tex;
612                 if (tex==NULL) continue;
613
614                 map<string, MTex*>::const_iterator mtexL = used_textures.find(string(tex->id.name));
615                 if (mtexL!=used_textures.end()) 
616                 {
617                         yafray::paramMap_t mparams;
618                         // when no facetex used, shader_name is created from original material name
619                         char temp[32];
620                         sprintf(temp,"_map%d", m2);
621                         if (facetexname.length()!=0)
622                                 mparams["input"] = yafray::parameter_t(string(matr->id.name) + string(temp));
623                         else
624                                 mparams["input"] = yafray::parameter_t(shader_name + temp);
625                         // blendtype
626                         string ts = "mix";
627                         if (mtex->blendtype==MTEX_MUL) ts="mul";
628                         else if (mtex->blendtype==MTEX_ADD) ts="add";
629                         else if (mtex->blendtype==MTEX_SUB) ts="sub";
630                         mparams["mode"]=yafray::parameter_t(ts);
631
632                         // texture color (for use with MUL and/or no_rgb etc..)
633                         mparams["texcol"]=yafray::parameter_t(yafray::color_t(mtex->r,mtex->g,mtex->b));
634                         // texture contrast, brightness & color adjustment
635                         mparams["filtercolor"]=yafray::parameter_t(yafray::color_t(tex->rfac,tex->gfac,tex->bfac));
636                         mparams["contrast"]=yafray::parameter_t(tex->contrast);
637                         mparams["brightness"]=yafray::parameter_t(tex->bright);
638                         // all texture flags now are switches, having the value 1 or -1 (negative option)
639                         // the negative option only used for the intensity modulation options.
640
641                         // material (diffuse) color, amount controlled by colfac (see below)
642                         if (mtex->mapto & MAP_COL)
643                                 mparams["color"]=yafray::parameter_t(1.0);
644                         // bumpmapping
645                         if ((mtex->mapto & MAP_NORM) || (mtex->maptoneg & MAP_NORM)) 
646                         {
647                                 // for yafray, bump factor is negated (unless negative option of 'Nor', 
648                                 // is not affected by 'Neg')
649                                 // scaled down quite a bit for yafray
650                                 float nf = -mtex->norfac;
651                                 if (mtex->maptoneg & MAP_NORM) nf *= -1.f;
652                                 mparams["normal"] = yafray::parameter_t(nf/60.f);
653                         }
654
655                         // all blender texture modulation as switches, either 1 or -1 (negative state of button)
656                         // Csp, specular color modulation
657                         if (mtex->mapto & MAP_COLSPEC)
658                                 mparams["colspec"]=yafray::parameter_t(1.0);
659                         // CMir, mirror color  modulation
660                         if (mtex->mapto & MAP_COLMIR)
661                                 mparams["colmir"]=yafray::parameter_t(1.0);
662
663                         // Ref, diffuse reflection amount  modulation
664                         if ((mtex->mapto & MAP_REF) || (mtex->maptoneg & MAP_REF)) 
665                         {
666                                 int t = 1;
667                                 if (mtex->maptoneg & MAP_REF) t = -1;
668                                 mparams["difref"]=yafray::parameter_t(t);
669                         }
670
671                         // Spec, specular amount mod
672                         if ((mtex->mapto & MAP_SPEC) || (mtex->maptoneg & MAP_SPEC)) 
673                         {
674                                 int t = 1;
675                                 if (mtex->maptoneg & MAP_SPEC) t = -1;
676                                 mparams["specular"]=yafray::parameter_t(t);
677                         }
678
679                         // hardness modulation
680                         if ((mtex->mapto & MAP_HAR) || (mtex->maptoneg & MAP_HAR)) 
681                         {
682                                 int t = 1;
683                                 if (mtex->maptoneg & MAP_HAR) t = -1;
684                                 mparams["hard"]=yafray::parameter_t(t);
685                         }
686
687                         // alpha modulation
688                         if ((mtex->mapto & MAP_ALPHA) || (mtex->maptoneg & MAP_ALPHA)) 
689                         {
690                                 int t = 1;
691                                 if (mtex->maptoneg & MAP_ALPHA) t = -1;
692                                 mparams["alpha"]=yafray::parameter_t(t);
693                         }
694
695                         // emit modulation
696                         if ((mtex->mapto & MAP_EMIT) || (mtex->maptoneg & MAP_EMIT)) {
697                                 int t = 1;
698                                 if (mtex->maptoneg & MAP_EMIT) t = -1;
699                                 mparams["emit"]=yafray::parameter_t(t);
700                         }
701
702                         // texture flag, combination of strings
703                         if (mtex->texflag & (MTEX_RGBTOINT | MTEX_STENCIL | MTEX_NEGATIVE)) {
704                                 ts = "";
705                                 if (mtex->texflag & MTEX_RGBTOINT) ts += "no_rgb ";
706                                 if (mtex->texflag & MTEX_STENCIL) ts += "stencil ";
707                                 if (mtex->texflag & MTEX_NEGATIVE) ts += "negative";
708                                 mparams["texflag"]=yafray::parameter_t(ts);
709                         }
710
711                         // colfac, controls amount of color modulation
712                         mparams["colfac"]=yafray::parameter_t(mtex->colfac);
713                         // def_var
714                         mparams["def_var"]=yafray::parameter_t(mtex->def_var);
715                         //varfac
716                         mparams["varfac"]=yafray::parameter_t(mtex->varfac);
717
718                         if ((tex->imaflag & (TEX_CALCALPHA | TEX_USEALPHA)) || (tex->flag & TEX_NEGALPHA)) 
719                         {
720                                 ts = "";
721                                 if (tex->imaflag & TEX_CALCALPHA) ts += "calc_alpha ";
722                                 if (tex->imaflag & TEX_USEALPHA) ts += "use_alpha ";
723                                 if (tex->flag & TEX_NEGALPHA) ts += "neg_alpha";
724                                 mparams["alpha_flag"]=yafray::parameter_t(ts);
725                         }
726                         lparams.push_back(mparams);
727                 }
728         }
729         yafrayGate->addShader(params,lparams);
730
731 }
732
733 // write all materials & modulators
734 void yafrayPluginRender_t::writeMaterialsAndModulators()
735 {
736         // shaders/mappers for regular texture (or non-texture) mode
737         // In case material has texface mode, and all faces have an image texture,
738         // this shader will not be used, but still be written
739         yafray::paramMap_t params;
740         list<yafray::paramMap_t> lparams;
741         for (map<string, Material*>::const_iterator blendmat=used_materials.begin();
742                 blendmat!=used_materials.end();++blendmat) 
743         {
744                 Material* matr = blendmat->second;
745                 // mapper(s)
746                 for (int m=0;m<8;m++) 
747                 {
748                         if (matr->septex & (1<<m)) continue;// all active channels
749                         // ignore null mtex
750                         MTex* mtex = matr->mtex[m];
751                         if (mtex==NULL) continue;
752                         // ignore null tex
753                         Tex* tex = mtex->tex;
754                         if (tex==NULL) continue;
755
756                         map<string, MTex*>::const_iterator mtexL = used_textures.find(string(tex->id.name));
757                         if (mtexL!=used_textures.end()) 
758                         {
759                                 params.clear(); //!!!
760                                 lparams.clear();
761                                 char temp[32];
762                                 sprintf(temp, "_map%d", m);
763                                 params["type"] = yafray::parameter_t("blendermapper");
764                                 params["name"] = yafray::parameter_t(blendmat->first + string(temp));
765                                 if ((mtex->texco & TEXCO_OBJECT) || (mtex->texco & TEXCO_REFL))
766                                 {
767                                         // For object & reflection mapping, add the object matrix to the modulator,
768                                         // as in LF script, use camera matrix if no object specified.
769                                         // In this case this means the inverse of that matrix
770                                         float texmat[4][4], itexmat[4][4];
771                                         if ((mtex->texco & TEXCO_OBJECT) && (mtex->object))
772                                                 MTC_Mat4CpyMat4(texmat, mtex->object->obmat);
773                                         else    // also for refl. map
774                                                 MTC_Mat4CpyMat4(texmat, maincam_obj->obmat);
775                                         MTC_Mat4Invert(itexmat, texmat);
776 #define flp yafray::parameter_t
777                                         params["m00"]=flp(itexmat[0][0]);  params["m01"]=flp(itexmat[1][0]);
778                                         params["m02"]=flp(itexmat[2][0]);  params["m03"]=flp(itexmat[3][0]);
779                                         params["m10"]=flp(itexmat[0][1]);  params["m11"]=flp(itexmat[1][1]);
780                                         params["m12"]=flp(itexmat[2][1]);  params["m13"]=flp(itexmat[3][1]);
781                                         params["m20"]=flp(itexmat[0][2]);  params["m21"]=flp(itexmat[1][2]);
782                                         params["m22"]=flp(itexmat[2][2]);  params["m23"]=flp(itexmat[3][2]);
783                                         params["m30"]=flp(itexmat[0][3]);  params["m31"]=flp(itexmat[1][3]);
784                                         params["m32"]=flp(itexmat[2][3]);  params["m33"]=flp(itexmat[3][3]);
785 #undef flp
786                                 }
787                                 // use image name instead of texname when texture is image
788                                 if ((tex->type==TEX_IMAGE) && tex->ima)
789                                         params["input"] = yafray::parameter_t(tex->ima->id.name);
790                                 else if ((tex->flag & TEX_COLORBAND) & (tex->coba!=NULL))
791                                         params["input"] = yafray::parameter_t(mtexL->first + "_coba");
792                                 else
793                                         params["input"] = yafray::parameter_t(mtexL->first);
794
795                                 // texture size
796                                 params["sizex"] = yafray::parameter_t(mtex->size[0]);
797                                 params["sizey"] = yafray::parameter_t(mtex->size[1]);
798                                 params["sizez"] = yafray::parameter_t(mtex->size[2]);
799
800                                 // texture offset
801                                 params["ofsx"] = yafray::parameter_t(mtex->ofs[0]);
802                                 params["ofsy"] = yafray::parameter_t(mtex->ofs[1]);
803                                 params["ofsz"] = yafray::parameter_t(mtex->ofs[2]);
804
805                                 // texture coordinates, have to disable 'sticky' in Blender
806                                 if (mtex->texco & TEXCO_UV)
807                                         params["texco"] = yafray::parameter_t("uv");
808                                 else if ((mtex->texco & TEXCO_GLOB) || (mtex->texco & TEXCO_OBJECT))
809                                         // object mode is also set as global, but the object matrix 
810                                         // was specified above with <modulator..>
811                                         params["texco"] = yafray::parameter_t("global");
812                                 else if (mtex->texco & TEXCO_ORCO)
813                                         params["texco"] = yafray::parameter_t("orco");
814                                 else if (mtex->texco & TEXCO_WINDOW)
815                                         params["texco"] = yafray::parameter_t("window");
816                                 else if (mtex->texco & TEXCO_NORM)
817                                         params["texco"] = yafray::parameter_t("normal");
818                                 else if (mtex->texco & TEXCO_REFL)
819                                         params["texco"] = yafray::parameter_t("reflect");
820
821                                 // texture projection axes, both image & procedural
822                                 string proj = "nxyz";           // 'n' for 'none'
823                                 params["proj_x"] = yafray::parameter_t(string(1,proj[mtex->projx]));
824                                 params["proj_y"] = yafray::parameter_t(string(1,proj[mtex->projy]));
825                                 params["proj_z"] = yafray::parameter_t(string(1,proj[mtex->projz]));
826
827                                 // texture mapping parameters only relevant to image type
828                                 if (tex->type==TEX_IMAGE) 
829                                 {
830                                         if (mtex->mapping==MTEX_FLAT)
831                                                 params["mapping"] = yafray::parameter_t("flat");
832                                         else if (mtex->mapping==MTEX_CUBE)
833                                                 params["mapping"] = yafray::parameter_t("cube");
834                                         else if (mtex->mapping==MTEX_TUBE)
835                                                 params["mapping"] = yafray::parameter_t("tube");
836                                         else if (mtex->mapping==MTEX_SPHERE)
837                                                 params["mapping"] = yafray::parameter_t("sphere");
838
839                                         // repeat
840                                         params["xrepeat"] = yafray::parameter_t(tex->xrepeat);
841                                         params["yrepeat"] = yafray::parameter_t(tex->yrepeat);
842
843                                         // clipping
844                                         if (tex->extend==TEX_EXTEND)
845                                                 params["clipping"] = yafray::parameter_t("extend");
846                                         else if (tex->extend==TEX_CLIP)
847                                                 params["clipping"] = yafray::parameter_t("clip");
848                                         else if (tex->extend==TEX_CLIPCUBE)
849                                                 params["clipping"] = yafray::parameter_t("clipcube");
850                                         else
851                                                 params["clipping"] = yafray::parameter_t("repeat");
852
853                                         // crop min/max
854                                         params["cropmin_x"] = yafray::parameter_t(tex->cropxmin);
855                                         params["cropmin_y"] = yafray::parameter_t(tex->cropymin);
856                                         params["cropmax_x"] = yafray::parameter_t(tex->cropxmax);
857                                         params["cropmax_y"] = yafray::parameter_t(tex->cropymax);
858
859                                         // rot90 flag
860                                         if (tex->imaflag & TEX_IMAROT) 
861                                                 params["rot90"] = yafray::parameter_t("on");
862                                         else
863                                                 params["rot90"] = yafray::parameter_t("off");
864                                 }
865                                 yafrayGate->addShader(params, lparams);
866                         }
867                 }
868
869                 // shader + modulators
870                 writeShader(blendmat->first, matr);
871
872         }
873
874                 // write the mappers & shaders for the TexFace case
875         if (!imagetex.empty()) {
876                 // Yafray doesn't have per-face-textures, only per-face-shaders,
877                 // so create as many mappers/shaders as the images used by the object
878                 params.clear();
879                 lparams.clear();
880                 int snum = 0;
881                 for (map<Image*, Material*>::const_iterator imgtex=imagetex.begin();
882                                 imgtex!=imagetex.end();++imgtex)
883                 {
884                         Material* matr = imgtex->second;
885
886                         // mapper
887                         params["type"] = yafray::parameter_t("blendermapper");
888                         char temp[32];
889                         sprintf(temp, "_ftex_mp%d", snum);
890                         params["name"] = yafray::parameter_t(string(matr->id.name) + string(temp));
891                         params["input"] = yafray::parameter_t(imgtex->first->id.name);
892                         // all yafray default settings, except for texco, so no need to set others
893                         params["texco"] = yafray::parameter_t("uv");
894                         yafrayGate->addShader(params, lparams);
895
896                         // shader, remember name, used later when writing per-face-shaders
897                         sprintf(temp, "_ftex_sh%d", snum);
898                         string shader_name = string(matr->id.name) + string(temp);
899                         imgtex_shader[imgtex->first] = shader_name;
900
901                         sprintf(temp, "_ftex_mp%d", snum++);
902                         string facetexname = string(matr->id.name) + string(temp);
903                         writeShader(shader_name, matr, facetexname);
904
905                 }
906         }
907
908 }
909
910 void yafrayPluginRender_t::genUVcoords(vector<yafray::GFLOAT> &uvcoords, VlakRen *vlr, TFace* uvc, bool comple)
911 {
912         if (uvc) 
913         {
914                 // tri uv split indices
915                 int ui1=0, ui2=1, ui3=2;
916                 if (vlr->flag & R_DIVIDE_24) {
917                         ui3++;
918                         if (vlr->flag & R_FACE_SPLIT) { ui1++;  ui2++; }
919                 }
920                 else if (vlr->flag & R_FACE_SPLIT) { ui2++;  ui3++; }
921                 if (comple) {
922                         ui1 = (ui1+2) & 3;
923                         ui2 = (ui2+2) & 3;
924                         ui3 = (ui3+2) & 3;
925                 }
926                 uvcoords.push_back(uvc->uv[ui1][0]);  uvcoords.push_back(1-uvc->uv[ui1][1]);
927                 uvcoords.push_back(uvc->uv[ui2][0]);  uvcoords.push_back(1-uvc->uv[ui2][1]);
928                 uvcoords.push_back(uvc->uv[ui3][0]);  uvcoords.push_back(1-uvc->uv[ui3][1]);
929         }
930         else
931         {
932                 uvcoords.push_back(0);  uvcoords.push_back(0);
933                 uvcoords.push_back(0);  uvcoords.push_back(0);
934                 uvcoords.push_back(0);  uvcoords.push_back(0);
935         }
936 }
937
938 void yafrayPluginRender_t::genVcol(vector<yafray::CFLOAT> &vcol, VlakRen *vlr, bool comple)
939 {
940         if (vlr->vcol)
941         {
942                 // tri vcol split indices
943                 int ui1=0, ui2=1, ui3=2;
944                 if (vlr->flag & R_DIVIDE_24) {
945                         ui3++;
946                         if (vlr->flag & R_FACE_SPLIT) { ui1++;  ui2++; }
947                 }
948                 else if (vlr->flag & R_FACE_SPLIT) { ui2++;  ui3++; }
949                 if (comple) {
950                         ui1 = (ui1+2) & 3;
951                         ui2 = (ui2+2) & 3;
952                         ui3 = (ui3+2) & 3;
953                 }
954                 float vr = ((vlr->vcol[ui1] >> 24) & 255)/255.0;
955                 float vg = ((vlr->vcol[ui1] >> 16) & 255)/255.0;
956                 float vb = ((vlr->vcol[ui1] >> 8) & 255)/255.0;
957                 vcol.push_back(vr);  vcol.push_back(vg);  vcol.push_back(vb);
958                 vr = ((vlr->vcol[ui2] >> 24) & 255)/255.0;
959                 vg = ((vlr->vcol[ui2] >> 16) & 255)/255.0;
960                 vb = ((vlr->vcol[ui2] >> 8) & 255)/255.0;
961                 vcol.push_back(vr);  vcol.push_back(vg);  vcol.push_back(vb);
962                 vr = ((vlr->vcol[ui3] >> 24) & 255)/255.0;
963                 vg = ((vlr->vcol[ui3] >> 16) & 255)/255.0;
964                 vb = ((vlr->vcol[ui3] >> 8) & 255)/255.0;
965                 vcol.push_back(vr);  vcol.push_back(vg);  vcol.push_back(vb);
966         }
967         else
968         {
969                 vcol.push_back(0);  vcol.push_back(0);  vcol.push_back(0);
970                 vcol.push_back(0);  vcol.push_back(0);  vcol.push_back(0);
971                 vcol.push_back(0);  vcol.push_back(0);  vcol.push_back(0);
972         }
973 }
974
975 void yafrayPluginRender_t::genFace(vector<int> &faces,vector<string> &shaders,vector<int> &faceshader,
976                                                                                                                 vector<yafray::GFLOAT> &uvcoords,vector<yafray::CFLOAT> &vcol,
977                                                                                                                 map<VertRen*, int> &vert_idx,VlakRen *vlr,
978                                                                                                                 bool has_orco,bool has_uv)
979 {
980         Material* fmat = vlr->mat;
981         bool EXPORT_VCOL = ((fmat->mode & (MA_VERTEXCOL|MA_VERTEXCOLP))!=0);
982         string fmatname(fmat->id.name);
983         // use name in imgtex_shader list if 'TexFace' enabled for this face material
984         if (fmat->mode & MA_FACETEXTURE) {
985                 TFace* tface = vlr->tface;
986                 if (tface) {
987                         Image* fimg = (Image*)tface->tpage;
988                         if (fimg) fmatname = imgtex_shader[fimg];
989                 }
990         }
991         else if (fmatname.length()==0) fmatname = "blender_default";
992         bool newmat=true;
993         for(unsigned int i=0;i<shaders.size();++i)
994                 if(shaders[i]==fmatname)
995                 {
996                         newmat=false;
997                         faceshader.push_back(i);
998                         break;
999                 }
1000         if(newmat)
1001         {
1002                 shaders.push_back(fmatname);
1003                 faceshader.push_back(shaders.size()-1);
1004         }
1005         TFace* uvc = vlr->tface;        // possible uvcoords (v upside down)
1006         int idx1, idx2, idx3;
1007
1008         idx1 = vert_idx.find(vlr->v1)->second;
1009         idx2 = vert_idx.find(vlr->v2)->second;
1010         idx3 = vert_idx.find(vlr->v3)->second;
1011
1012         // make sure the indices point to the vertices when orco coords exported
1013         if (has_orco) { idx1*=2;  idx2*=2;  idx3*=2; }
1014
1015         faces.push_back(idx1);  faces.push_back(idx2);  faces.push_back(idx3);
1016
1017         if(has_uv) genUVcoords(uvcoords, vlr, uvc);
1018         if (EXPORT_VCOL) genVcol(vcol, vlr);
1019 }
1020
1021 void yafrayPluginRender_t::genCompleFace(vector<int> &faces,/*vector<string> &shaders,*/vector<int> &faceshader,
1022                                                                                                                 vector<yafray::GFLOAT> &uvcoords,vector<yafray::CFLOAT> &vcol,
1023                                                                                                                 map<VertRen*, int> &vert_idx,VlakRen *vlr,
1024                                                                                                                 bool has_orco,bool has_uv)
1025 {
1026         Material* fmat = vlr->mat;
1027         bool EXPORT_VCOL = ((fmat->mode & (MA_VERTEXCOL|MA_VERTEXCOLP))!=0);
1028
1029         faceshader.push_back(faceshader.back());
1030         TFace* uvc = vlr->tface;        // possible uvcoords (v upside down)
1031         int idx1, idx2, idx3;
1032         idx1 = vert_idx.find(vlr->v3)->second;
1033         idx2 = vert_idx.find(vlr->v4)->second;
1034         idx3 = vert_idx.find(vlr->v1)->second;
1035
1036         // make sure the indices point to the vertices when orco coords exported
1037         if (has_orco) { idx1*=2;  idx2*=2;  idx3*=2; }
1038
1039         faces.push_back(idx1);  faces.push_back(idx2);  faces.push_back(idx3);
1040
1041         if (has_uv) genUVcoords(uvcoords, vlr, uvc, true);
1042         if (EXPORT_VCOL) genVcol(vcol, vlr, true);
1043 }
1044
1045 void yafrayPluginRender_t::genVertices(vector<yafray::point3d_t> &verts, int &vidx,
1046                                                                                                                                                          map<VertRen*, int> &vert_idx, VlakRen* vlr, bool has_orco, Object* obj)
1047 {
1048         VertRen* ver;
1049         float tvec[3];  // for back2world transform
1050         if (vert_idx.find(vlr->v1)==vert_idx.end()) 
1051         {
1052                 vert_idx[vlr->v1] = vidx++;
1053                 ver = vlr->v1;
1054                 MTC_cp3Float(ver->co, tvec);
1055                 MTC_Mat4MulVecfl(obj->imat, tvec);
1056                 verts.push_back(yafray::point3d_t(tvec[0], tvec[1], tvec[2]));
1057                 if (has_orco) 
1058                         verts.push_back(yafray::point3d_t(ver->orco[0],ver->orco[1],ver->orco[2]));
1059         }
1060         if (vert_idx.find(vlr->v2)==vert_idx.end()) 
1061         {
1062                 vert_idx[vlr->v2] = vidx++;
1063                 ver = vlr->v2;
1064                 MTC_cp3Float(ver->co, tvec);
1065                 MTC_Mat4MulVecfl(obj->imat, tvec);
1066                 verts.push_back(yafray::point3d_t(tvec[0], tvec[1], tvec[2]));
1067                 if (has_orco)
1068                         verts.push_back(yafray::point3d_t(ver->orco[0],ver->orco[1],ver->orco[2]));
1069         }
1070         if (vert_idx.find(vlr->v3)==vert_idx.end()) 
1071         {
1072                 vert_idx[vlr->v3] = vidx++;
1073                 ver = vlr->v3;
1074                 MTC_cp3Float(ver->co, tvec);
1075                 MTC_Mat4MulVecfl(obj->imat, tvec);
1076                 verts.push_back(yafray::point3d_t(tvec[0], tvec[1], tvec[2]));
1077                 if (has_orco)
1078                         verts.push_back(yafray::point3d_t(ver->orco[0],ver->orco[1],ver->orco[2]));
1079         }
1080         if ((vlr->v4) && (vert_idx.find(vlr->v4)==vert_idx.end())) 
1081         {
1082                 vert_idx[vlr->v4] = vidx++;
1083                 ver = vlr->v4;
1084                 MTC_cp3Float(ver->co, tvec);
1085                 MTC_Mat4MulVecfl(obj->imat, tvec);
1086                 verts.push_back(yafray::point3d_t(tvec[0], tvec[1], tvec[2]));
1087                 if (has_orco)
1088                         verts.push_back(yafray::point3d_t(ver->orco[0],ver->orco[1],ver->orco[2]));
1089         }
1090 }
1091
1092 void yafrayPluginRender_t::writeObject(Object* obj, const vector<VlakRen*> &VLR_list, const float obmat[4][4])
1093 {
1094         float mtr[4*4];
1095         mtr[0*4+0]=obmat[0][0];  mtr[0*4+1]=obmat[1][0];  mtr[0*4+2]=obmat[2][0];  mtr[0*4+3]=obmat[3][0];
1096         mtr[1*4+0]=obmat[0][1];  mtr[1*4+1]=obmat[1][1];  mtr[1*4+2]=obmat[2][1];  mtr[1*4+3]=obmat[3][1];
1097         mtr[2*4+0]=obmat[0][2];  mtr[2*4+1]=obmat[1][2];  mtr[2*4+2]=obmat[2][2];  mtr[2*4+3]=obmat[3][2];
1098         mtr[3*4+0]=obmat[0][3];  mtr[3*4+1]=obmat[1][3];  mtr[3*4+2]=obmat[2][3];  mtr[3*4+3]=obmat[3][3];
1099         yafrayGate->transformPush(mtr);
1100         
1101         VlakRen* face0 = VLR_list[0];
1102         Material* face0mat = face0->mat;
1103         
1104         bool castShadows = face0mat->mode & MA_TRACEBLE;
1105         float caus_IOR=1.0;
1106         yafray::color_t caus_tcolor(0.0, 0.0, 0.0), caus_rcolor(0.0, 0.0, 0.0);
1107         bool caus = (((face0->mat->mode & MA_RAYTRANSP) | (face0->mat->mode & MA_RAYMIRROR))!=0);
1108         if (caus) {
1109                 caus_IOR = face0mat->ang;
1110                 float tr = 1.0-face0mat->alpha;
1111                 caus_tcolor.set(face0mat->r*tr, face0mat->g*tr, face0mat->b*tr);
1112                 tr = face0mat->ray_mirror;
1113                 caus_rcolor.set(face0mat->mirr*tr, face0mat->mirg*tr, face0mat->mirb*tr);
1114         }
1115         bool has_orco = (face0->v1->orco!=NULL);
1116         bool no_auto = true;    //in case non-mesh, or mesh has no autosmooth
1117         float sm_angle = 0.1f;
1118         if (obj->type==OB_MESH) 
1119         {
1120                 Mesh* mesh = (Mesh*)obj->data;
1121                 if (mesh->flag & ME_AUTOSMOOTH) {
1122                         sm_angle = mesh->smoothresh;
1123                         no_auto = false;
1124                 }
1125         }
1126         // this for non-mesh as well
1127         if (no_auto) {
1128                 // no per face smooth flag in yafray, if AutoSmooth not used, 
1129                 // use smooth flag of the first face instead
1130                 if (face0->flag & ME_SMOOTH) sm_angle=90;
1131         }
1132         vector<yafray::point3d_t> verts;
1133         vector<yafray::CFLOAT> vcol;
1134         // now all vertices
1135         map<VertRen*, int> vert_idx;    // for removing duplicate verts and creating an index list
1136         int vidx = 0;   // vertex index counter
1137         bool has_uv=false;
1138         for (vector<VlakRen*>::const_iterator fci=VLR_list.begin();
1139                                 fci!=VLR_list.end();++fci)
1140         {
1141                 VlakRen* vlr = *fci;
1142                 genVertices(verts, vidx, vert_idx, vlr, has_orco, obj);
1143                 if(vlr->tface) has_uv=true;
1144         }
1145         // all faces using the index list created above
1146         vector<int> faces;
1147         vector<string> shaders;
1148         vector<int> faceshader;
1149         vector<yafray::GFLOAT> uvcoords;
1150         for (vector<VlakRen*>::const_iterator fci2=VLR_list.begin();
1151                                 fci2!=VLR_list.end();++fci2)
1152         {
1153                 VlakRen* vlr = *fci2;
1154                 genFace(faces, shaders, faceshader, uvcoords, vcol, vert_idx, vlr, has_orco, has_uv);
1155                 if (vlr->v4) 
1156                         genCompleFace(faces, faceshader, uvcoords, vcol, vert_idx, vlr, has_orco, has_uv);
1157         }
1158
1159         yafrayGate->addObject_trimesh(string(obj->id.name), verts, faces, uvcoords, vcol,
1160                         shaders, faceshader, sm_angle, castShadows, true, true, caus, has_orco,
1161                         caus_rcolor, caus_tcolor, caus_IOR);
1162         yafrayGate->transformPop();
1163 }
1164
1165
1166 // write all objects
1167 void yafrayPluginRender_t::writeAllObjects()
1168 {
1169
1170         // first all objects except dupliverts (and main instance object for dups)
1171         for (map<Object*, vector<VlakRen*> >::const_iterator obi=all_objects.begin();
1172                         obi!=all_objects.end(); ++obi)
1173         {
1174           // skip main duplivert object if in dupliMtx_list, written later
1175                 Object* obj = obi->first;
1176                 if (dupliMtx_list.find(string(obj->id.name))!=dupliMtx_list.end()) continue;
1177                 writeObject(obj, obi->second, obj->obmat);
1178         }
1179
1180         // Now all duplivert objects (if any) as instances of main object
1181         // The original object has been included in the VlakRen renderlist above (see convertBlenderScene.c)
1182         // but is written here which all other duplis are instances of.
1183         float obmat[4][4], cmat[4][4], imat[4][4], nmat[4][4];
1184         for (map<string, vector<float> >::const_iterator dupMtx=dupliMtx_list.begin();
1185                 dupMtx!=dupliMtx_list.end();++dupMtx) {
1186
1187                 // original inverse matrix, not actual matrix of object, but first duplivert.
1188                 for (int i=0;i<4;i++)
1189                         for (int j=0;j<4;j++)
1190                                 obmat[i][j] = dupMtx->second[(i<<2)+j];
1191                 MTC_Mat4Invert(imat, obmat);
1192
1193                 // first object written as normal (but with transform of first duplivert)
1194                 Object* obj = dup_srcob[dupMtx->first];
1195                 writeObject(obj, all_objects[obj], obmat);
1196
1197                 // all others instances of first
1198                 for (unsigned int curmtx=16;curmtx<dupMtx->second.size();curmtx+=16) 
1199                 {       // number of 4x4 matrices
1200                         // new mtx
1201                         for (int i=0;i<4;i++)
1202                                 for (int j=0;j<4;j++)
1203                                         nmat[i][j] = dupMtx->second[curmtx+(i<<2)+j];
1204
1205                         MTC_Mat4MulMat4(cmat, imat, nmat);      // transform with respect to original = inverse_original * new
1206
1207                         float mtr[4*4];
1208                         mtr[0*4+0]=cmat[0][0];  mtr[0*4+1]=cmat[1][0];  mtr[0*4+2]=cmat[2][0];  mtr[0*4+3]=cmat[3][0];
1209                         mtr[1*4+0]=cmat[0][1];  mtr[1*4+1]=cmat[1][1];  mtr[1*4+2]=cmat[2][1];  mtr[1*4+3]=cmat[3][1];
1210                         mtr[2*4+0]=cmat[0][2];  mtr[2*4+1]=cmat[1][2];  mtr[2*4+2]=cmat[2][2];  mtr[2*4+3]=cmat[3][2];
1211                         mtr[3*4+0]=cmat[0][3];  mtr[3*4+1]=cmat[1][3];  mtr[3*4+2]=cmat[2][3];  mtr[3*4+3]=cmat[3][3];
1212                         yafrayGate->transformPush(mtr);
1213
1214                         // new name from original
1215                         string name=(obj->id.name);
1216                         char temp[16];
1217                         sprintf(temp,"_dup%d",(curmtx>>4));
1218                         name+=temp;
1219                         yafrayGate->addObject_reference(name,obj->id.name);
1220                         yafrayGate->transformPop();
1221                 }
1222
1223         }
1224
1225 }
1226
1227 void yafrayPluginRender_t::writeAreaLamp(LampRen* lamp, int num, float iview[4][4])
1228 {
1229         yafray::paramMap_t params;
1230         
1231         if (lamp->area_shape!=LA_AREA_SQUARE) return;
1232         float *a=lamp->area[0], *b=lamp->area[1], *c=lamp->area[2], *d=lamp->area[3];
1233         float power=lamp->energy;
1234         
1235         string md = "off";
1236         // if no GI used, the GIphotons flag can still be set, so only use when 'full' selected
1237         if ((R.r.GImethod==2) && (R.r.GIphotons)) { md="on";  power*=R.r.GIpower; }
1238         params["type"]=yafray::parameter_t("arealight");
1239         char temp[16];
1240         sprintf(temp,"LAMP%d",num+1);
1241         params["name"]=yafray::parameter_t(temp);
1242         params["dummy"]=yafray::parameter_t(md);
1243         params["power"]=yafray::parameter_t(power);
1244         // samples not used for GI with photons, can still be exported, is ignored
1245         int psm=0, sm = lamp->ray_totsamp;
1246         if (sm>=25) psm = sm/5;
1247         params["samples"]=yafray::parameter_t(sm);
1248         params["psamples"]=yafray::parameter_t(psm);
1249         
1250         // transform area lamp coords back to world
1251         float lpco[4][3];
1252         MTC_Mat4Invert(iview, R.viewmat);
1253         MTC_cp3Float(a, lpco[0]);
1254         MTC_Mat4MulVecfl(iview, lpco[0]);
1255         MTC_cp3Float(b, lpco[1]);
1256         MTC_Mat4MulVecfl(iview, lpco[1]);
1257         MTC_cp3Float(c, lpco[2]);
1258         MTC_Mat4MulVecfl(iview, lpco[2]);
1259         MTC_cp3Float(d, lpco[3]);
1260         MTC_Mat4MulVecfl(iview, lpco[3]);       
1261         params["a"] = yafray::parameter_t(yafray::point3d_t(lpco[0][0], lpco[0][1], lpco[0][2]));
1262         params["b"] = yafray::parameter_t(yafray::point3d_t(lpco[1][0], lpco[1][1], lpco[1][2]));
1263         params["c"] = yafray::parameter_t(yafray::point3d_t(lpco[2][0], lpco[2][1], lpco[2][2]));
1264         params["d"] = yafray::parameter_t(yafray::point3d_t(lpco[3][0], lpco[3][1], lpco[3][2]));
1265         
1266         params["color"]=yafray::parameter_t(yafray::color_t(lamp->r,lamp->g,lamp->b));
1267         yafrayGate->addLight(params);
1268 }
1269
1270 void yafrayPluginRender_t::writeLamps()
1271 {
1272         // inver viewmatrix needed for back2world transform
1273         float iview[4][4];
1274         // R.viewinv != inv.R.viewmat because of possible ortho mode (see convertBlenderScene.c)
1275         // have to invert it here
1276         MTC_Mat4Invert(iview, R.viewmat);
1277
1278         // all lamps
1279         for (int i=0;i<R.totlamp;i++)
1280         {
1281                 yafray::paramMap_t params;
1282                 string type="";
1283                 LampRen* lamp = R.la[i];
1284                 
1285                 if (lamp->type==LA_AREA) { writeAreaLamp(lamp, i, iview);  continue; }
1286                 
1287                 // TODO: add decay setting in yafray
1288                 bool is_softL=false, is_sphereL=false;
1289                 if (lamp->type==LA_LOCAL) {
1290                         if (lamp->mode & LA_YF_SOFT) {
1291                                 // shadowmapped omnidirectional light
1292                                 params["type"] = yafray::parameter_t("softlight");
1293                                 is_softL = true;
1294                         }
1295                         else if ((lamp->mode & LA_SHAD_RAY) && (lamp->YF_ltradius>0.0)) {
1296                                 // area sphere, only when ray shadows enabled and radius>0.0
1297                                 params["type"] = yafray::parameter_t("spherelight");
1298                                 is_sphereL = true;
1299                         }
1300                         else params["type"] = yafray::parameter_t("pointlight");
1301                 }
1302                 else if (lamp->type==LA_SPOT)
1303                         params["type"] = yafray::parameter_t("spotlight");
1304                 else if ((lamp->type==LA_SUN) || (lamp->type==LA_HEMI)) // hemi exported as sun
1305                         params["type"] = yafray::parameter_t("sunlight");
1306                 else if (lamp->type==LA_YF_PHOTON)
1307                         params["type"] = yafray::parameter_t("photonlight");
1308                 else {
1309                         // possibly unknown type, ignore
1310                         cout << "Unknown Blender lamp type: " << lamp->type << endl;
1311                         continue;
1312                 }
1313                 
1314                 //no name available here, create one
1315                 char temp[16];
1316                 sprintf(temp,"LAMP%d",i+1);
1317                 params["name"] = yafray::parameter_t(temp);
1318                 // color already premultiplied by energy, so only need distance here
1319                 float pwr = 1;  // default for sun/hemi, distance irrelevant
1320                 if ((lamp->type!=LA_SUN) && (lamp->type!=LA_HEMI)) {
1321                         if (lamp->mode & LA_SPHERE) {
1322                                 // best approx. as used in LFexport script (LF d.f.m. 4pi?)
1323                                 pwr = lamp->dist*(lamp->dist+1)*(0.25/M_PI);
1324                                 //decay = 2;
1325                         }
1326                         else {
1327                                 pwr = lamp->dist;
1328                                 //decay = 1;
1329                         }
1330                 }
1331
1332                 if (is_sphereL) {
1333                         // 'dummy' mode for spherelight when used with gpm
1334                         string md = "off";
1335                         // if no GI used, the GIphotons flag can still be set, so only use when 'full' selected
1336                         if ((R.r.GImethod==2) && (R.r.GIphotons)) { md="on";  pwr*=R.r.GIpower; }
1337                         params["power"] = yafray::parameter_t(pwr);
1338                         params["dummy"] = yafray::parameter_t(md);
1339                 }
1340                 else params["power"] = yafray::parameter_t(pwr);
1341                 
1342                 // cast_shadows flag not used with softlight, spherelight or photonlight
1343                 if ((!is_softL) && (!is_sphereL) && (lamp->type!=LA_YF_PHOTON)) {
1344                         string lpmode="off";
1345                         // Shadows only when Blender has shadow button enabled, only spots use LA_SHAD flag.
1346                         // Also blender hemilights exported as sunlights which might have shadow flag set
1347                         // should have cast_shadows set to off (reported by varuag)
1348                         if (lamp->type!=LA_HEMI) {
1349                                 if (R.r.mode & R_SHADOW)
1350                                         if (((lamp->type==LA_SPOT) && (lamp->mode & LA_SHAD)) || (lamp->mode & LA_SHAD_RAY)) lpmode="on";
1351                         }
1352                         params["cast_shadows"] = yafray::parameter_t(lpmode);
1353                 }
1354                 
1355                 // spot specific stuff
1356                 bool has_halo = ((lamp->type==LA_SPOT) && (lamp->mode & LA_HALO) && (lamp->haint>0.0));
1357                 if (lamp->type==LA_SPOT) {
1358                         // conversion already changed spotsize to cosine of half angle
1359                         float ld = 1-lamp->spotsi;      //convert back to blender slider setting
1360                         if (ld!=0) ld = 1.f/ld;
1361                         params["size"] = yafray::parameter_t(acos(lamp->spotsi)*180.0/M_PI);
1362                         params["blend"] = yafray::parameter_t(lamp->spotbl*ld);
1363                         params["beam_falloff"] = yafray::parameter_t(2.0);
1364                         // halo params
1365                         if (has_halo) {
1366                                 params["halo"] = yafray::parameter_t("on");
1367                                 params["res"] = yafray::parameter_t(lamp->YF_bufsize);
1368                                 int hsmp = ((12-lamp->shadhalostep)*16)/12;
1369                                 hsmp = (hsmp+1)*16;     // makes range (16, 272) for halostep(12, 0), good enough?
1370                                 params["samples"] = yafray::parameter_t(hsmp);
1371                                 params["shadow_samples"] = yafray::parameter_t(lamp->samp*lamp->samp);
1372                                 params["halo_blur"] = yafray::parameter_t(0.0);
1373                                 params["shadow_blur"] = yafray::parameter_t(lamp->soft*0.01f);
1374                                 params["fog_density"] = yafray::parameter_t(lamp->haint*0.2f);
1375                         }
1376                 }
1377                 else if (is_softL) {
1378                         // softlight
1379                         params["res"] = yafray::parameter_t(lamp->YF_bufsize);
1380                         params["radius"] = yafray::parameter_t(lamp->soft);
1381                         params["bias"] = yafray::parameter_t(lamp->bias);
1382                 }
1383                 else if (is_sphereL) {
1384                         // spherelight
1385                         int psm=0, sm = lamp->ray_samp*lamp->ray_samp;
1386                         if (sm>=25) psm = sm/5;
1387                         params["radius"] = yafray::parameter_t(lamp->YF_ltradius);
1388                         params["samples"] = yafray::parameter_t(sm);
1389                         params["psamples"] = yafray::parameter_t(psm);
1390                         params["qmc_method"] = yafray::parameter_t(1);
1391                 }
1392                 else if (lamp->type==LA_YF_PHOTON) {
1393                         string qmc="off";
1394                         if (lamp->YF_useqmc) qmc="on";
1395                         params["photons"] = yafray::parameter_t(lamp->YF_numphotons);
1396                         params["search"] = yafray::parameter_t(lamp->YF_numsearch);
1397                         params["depth"] = yafray::parameter_t(lamp->YF_phdepth);
1398                         params["use_QMC"] = yafray::parameter_t(qmc);
1399                         params["angle"] = yafray::parameter_t(acos(lamp->spotsi)*180.0/M_PI);
1400                         float cl = lamp->YF_causticblur/sqrt((float)lamp->YF_numsearch);
1401                         params["fixedradius"] = yafray::parameter_t(lamp->YF_causticblur);
1402                         params["cluster"] = yafray::parameter_t(cl);
1403                 }
1404
1405                 // transform lamp co & vec back to world
1406                 float lpco[3], lpvec[3];
1407                 MTC_cp3Float(lamp->co, lpco);
1408                 MTC_Mat4MulVecfl(iview, lpco);
1409                 MTC_cp3Float(lamp->vec, lpvec);
1410                 MTC_Mat4Mul3Vecfl(iview, lpvec);
1411
1412                 // position, (==-blendir for sun/hemi)
1413                 if ((lamp->type==LA_SUN) || (lamp->type==LA_HEMI))
1414                         params["from"] = yafray::parameter_t(yafray::point3d_t(-lpvec[0], -lpvec[1], -lpvec[2]));
1415                 else
1416                         params["from"] = yafray::parameter_t(yafray::point3d_t(lpco[0], lpco[1], lpco[2]));
1417                 // 'to' for spot/photonlight, already calculated by Blender
1418                 if ((lamp->type==LA_SPOT) || (lamp->type==LA_YF_PHOTON)) {
1419                         params["to"] = yafray::parameter_t(yafray::point3d_t(lpco[0] + lpvec[0],
1420                                                                                                                                                                                                                                          lpco[1] + lpvec[1],
1421                                                                                                                                                                                                                                          lpco[2] + lpvec[2]));
1422                         if (has_halo) params["fog"] = yafray::parameter_t(yafray::color_t(1.0, 1.0, 1.0));
1423                 }
1424                 
1425                 // color
1426                 // rgb in LampRen is premultiplied by energy, power is compensated for that above
1427                 params["color"] = yafray::parameter_t(yafray::color_t(lamp->r, lamp->g, lamp->b));
1428                 yafrayGate->addLight(params);
1429         }
1430 }
1431
1432 // write main camera
1433 void yafrayPluginRender_t::writeCamera()
1434 {
1435         yafray::paramMap_t params;
1436         params["name"]=yafray::parameter_t("MAINCAM");
1437         if (R.r.mode & R_ORTHO)
1438                 params["type"] = yafray::parameter_t("ortho");
1439         else
1440                 params["type"] = yafray::parameter_t("perspective");
1441         params["resx"]=yafray::parameter_t(R.r.xsch);
1442         params["resy"]=yafray::parameter_t(R.r.ysch);
1443
1444         float f_aspect = 1;
1445         if ((R.r.xsch*R.r.xasp)<=(R.r.ysch*R.r.yasp)) f_aspect = float(R.r.xsch*R.r.xasp)/float(R.r.ysch*R.r.yasp);
1446         params["focal"] = yafray::parameter_t(mainCamLens/(f_aspect*32.f));
1447         params["aspect_ratio"] = yafray::parameter_t(R.ycor);
1448
1449         // dof params, only valid for real camera
1450         if (maincam_obj->type==OB_CAMERA) {
1451                 Camera* cam = (Camera*)maincam_obj->data;
1452                 params["dof_distance"] = yafray::parameter_t(cam->YF_dofdist);
1453                 params["aperture"] = yafray::parameter_t(cam->YF_aperture);
1454                 if (cam->flag & CAM_YF_NO_QMC)
1455                         params["use_qmc"] = yafray::parameter_t("off");
1456                 else
1457                         params["use_qmc"] = yafray::parameter_t("on");
1458                 // bokeh params
1459                 string st = "disk1";
1460                 if (cam->YF_bkhtype==1)
1461                         st = "disk2";
1462                 else if (cam->YF_bkhtype==2)
1463                         st = "triangle";
1464                 else if (cam->YF_bkhtype==3)
1465                         st = "square";
1466                 else if (cam->YF_bkhtype==4)
1467                         st = "pentagon";
1468                 else if (cam->YF_bkhtype==5)
1469                         st = "hexagon";
1470                 else if (cam->YF_bkhtype==6)
1471                         st = "ring";
1472                 params["bokeh_type"] = yafray::parameter_t(st);
1473                 st = "uniform";
1474                 if (cam->YF_bkhbias==1)
1475                         st = "center";
1476                 else if (cam->YF_bkhbias==2)
1477                         st = "edge";
1478                 params["bokeh_bias"] = yafray::parameter_t(st);
1479                 params["bokeh_rotation"] = yafray::parameter_t(cam->YF_bkhrot);
1480         }
1481
1482         params["from"]=yafray::parameter_t(
1483                         yafray::point3d_t(maincam_obj->obmat[3][0], maincam_obj->obmat[3][1], maincam_obj->obmat[3][2]));
1484         float fdist = fabs(R.viewmat[3][2]);
1485         if (R.r.mode & R_ORTHO) fdist *= 0.01f;
1486         params["to"]=yafray::parameter_t(
1487                         yafray::point3d_t(maincam_obj->obmat[3][0] - fdist * R.viewmat[0][2],
1488                                                                                                 maincam_obj->obmat[3][1] - fdist * R.viewmat[1][2],
1489                                                                                                 maincam_obj->obmat[3][2] - fdist * R.viewmat[2][2]));
1490         params["up"]=yafray::parameter_t(
1491                         yafray::point3d_t(maincam_obj->obmat[3][0] + R.viewmat[0][1],
1492                                                                                                 maincam_obj->obmat[3][1] + R.viewmat[1][1],
1493                                                                                                 maincam_obj->obmat[3][2] + R.viewmat[2][1]));
1494
1495         yafrayGate->addCamera(params);
1496 }
1497
1498 void yafrayPluginRender_t::writeHemilight()
1499 {
1500         yafray::paramMap_t params;
1501         params["type"] = yafray::parameter_t("hemilight");
1502         params["name"] = yafray::parameter_t("hemi_LT");
1503         params["power"] = yafray::parameter_t(R.r.GIpower);
1504         switch (R.r.GIquality)
1505         {
1506                 case 1 :
1507                 case 2 : params["samples"]=yafray::parameter_t(16);  break;
1508                 case 3 : params["samples"]=yafray::parameter_t(36);  break;
1509                 case 4 : params["samples"]=yafray::parameter_t(64);  break;
1510                 case 5 : params["samples"]=yafray::parameter_t(128);  break;
1511                 default: params["samples"]=yafray::parameter_t(25);
1512         }
1513         yafrayGate->addLight(params);
1514 }
1515
1516 void yafrayPluginRender_t::writePathlight()
1517 {
1518         if (R.r.GIphotons)
1519         {
1520                 yafray::paramMap_t params;
1521                 params["type"]=yafray::parameter_t("globalphotonlight");
1522                 params["name"]=yafray::parameter_t("gpm");
1523                 params["photons"]=yafray::parameter_t(R.r.GIphotoncount);
1524                 params["radius"]=yafray::parameter_t(R.r.GIphotonradius);
1525                 params["depth"]=yafray::parameter_t(((R.r.GIdepth>2) ? (R.r.GIdepth-1) : 1));
1526                 params["caus_depth"]=yafray::parameter_t(R.r.GIcausdepth);
1527                 params["search"]=yafray::parameter_t(R.r.GImixphotons);
1528                 yafrayGate->addLight(params);
1529         }
1530         yafray::paramMap_t params;
1531         params["type"]=yafray::parameter_t("pathlight");
1532         params["name"]=yafray::parameter_t("path_LT");
1533         params["power"]=yafray::parameter_t(R.r.GIindirpower);
1534         params["depth"]=yafray::parameter_t(((R.r.GIphotons) ? 1 : R.r.GIdepth));
1535         params["caus_depth"]=yafray::parameter_t(R.r.GIcausdepth);
1536         if(R.r.GIdirect && R.r.GIphotons) params["direct"]=yafray::parameter_t("on");
1537         if (R.r.GIcache && ! (R.r.GIdirect && R.r.GIphotons))
1538         {
1539                 switch (R.r.GIquality)
1540                 {
1541                         case 1 : params["samples"]=yafray::parameter_t(128);break;
1542                         case 2 : params["samples"]=yafray::parameter_t(256);break;
1543                         case 3 : params["samples"]=yafray::parameter_t(512);break;
1544                         case 4 : params["samples"]=yafray::parameter_t(1024);break;
1545                         case 5 : params["samples"]=yafray::parameter_t(2048);break;
1546                         default: params["samples"]=yafray::parameter_t(256);
1547                 }
1548                 float aspect = 1;
1549                 if (R.r.xsch < R.r.ysch) aspect = float(R.r.xsch)/float(R.r.ysch);
1550                 float sbase = 2.0/float(R.r.xsch);
1551                 params["cache"]=yafray::parameter_t("on");
1552                 params["use_QMC"]=yafray::parameter_t("on");
1553                 params["threshold"]=yafray::parameter_t(R.r.GIrefinement);
1554                 params["cache_size"]=yafray::parameter_t(sbase*R.r.GIpixelspersample);
1555                 params["shadow_threshold"]=yafray::parameter_t(1.0 - R.r.GIshadowquality);
1556                 params["grid"]=yafray::parameter_t(82);
1557                 params["search"]=yafray::parameter_t(35);
1558         }
1559         else
1560         {
1561                 switch (R.r.GIquality)
1562                 {
1563                         case 1 : params["samples"]=yafray::parameter_t(16);break;
1564                         case 2 : params["samples"]=yafray::parameter_t(36);break;
1565                         case 3 : params["samples"]=yafray::parameter_t(64);break;
1566                         case 4 : params["samples"]=yafray::parameter_t(128);break;
1567                         case 5 : params["samples"]=yafray::parameter_t(256);break;
1568                         default: params["samples"]=yafray::parameter_t(25);break;
1569                 }
1570         }
1571         yafrayGate->addLight(params);
1572 }
1573
1574 bool yafrayPluginRender_t::writeWorld()
1575 {
1576         World *world = G.scene->world;
1577         if (R.r.GIquality!=0) {
1578                 if (R.r.GImethod==1) {
1579                         if (world==NULL) cout << "WARNING: need world background for skydome!\n";
1580                         writeHemilight();
1581                 }
1582                 else if (R.r.GImethod==2) writePathlight();
1583         }
1584
1585         if (world==NULL) return false;
1586
1587         yafray::paramMap_t params;
1588         for (int i=0;i<6;i++) {
1589                 MTex* wtex = world->mtex[i];
1590                 if (!wtex) continue;
1591                 Image* wimg = wtex->tex->ima;
1592                 if ((wtex->tex->type==TEX_IMAGE) && (wimg!=NULL)) {
1593                         string wt_path = wimg->name;
1594                         adjustPath(wt_path);
1595                         if (BLI_testextensie(wimg->name, ".hdr")) {
1596                                 params["type"] = yafray::parameter_t("HDRI");
1597                                 params["name"] = yafray::parameter_t("world_background");
1598                                 // since exposure adjust is an integer, using the texbri slider isn't actually very useful here (result either -1/0/1)
1599                                 params["exposure_adjust"] = yafray::parameter_t(int(world->mtex[i]->tex->bright-1));
1600                                 params["mapping"] = yafray::parameter_t("probe");
1601                                 params["filename"] = yafray::parameter_t(wt_path);
1602                                 yafrayGate->addBackground(params);
1603                                 return true;
1604                         }
1605                         else if (BLI_testextensie(wimg->name, ".jpg") || BLI_testextensie(wimg->name, ".jpeg") || BLI_testextensie(wimg->name, ".tga")) {
1606                                 params["type"] = yafray::parameter_t("image");
1607                                 params["name"] = yafray::parameter_t("world_background");
1608                                 /*
1609                                 // not yet in yafray, always assumes spheremap for now, not the same as in Blender,
1610                                 // which for some reason is scaled by 2 in Blender???
1611                                 if (wtex->texco & TEXCO_ANGMAP)
1612                                         params["mapping"] = yafray::parameter_t("probe");
1613                                 else
1614                                         params["mapping"] = yafray::parameter_t("sphere");
1615                                 */
1616                                 params["filename"] = yafray::parameter_t(wt_path);
1617                                 yafrayGate->addBackground(params);
1618                                 return true;
1619                         }
1620                 }
1621         }
1622
1623         params.clear();
1624         params["type"] = yafray::parameter_t("constant");
1625         params["name"] = yafray::parameter_t("world_background");
1626         // if no GI used, the GIpower parameter is not always initialized, so in that case ignore it
1627         // (have to change method to init yafray vars in Blender)
1628         float bg_mult = (R.r.GImethod==0) ? 1 : R.r.GIpower;
1629         params["color"]=yafray::parameter_t(yafray::color_t(world->horr * bg_mult,
1630                                                                                                                                                                                                                         world->horg * bg_mult,
1631                                                                                                                                                                                                                         world->horb * bg_mult));
1632         yafrayGate->addBackground(params);
1633         return true;
1634 }
1635
1636 #include "RE_callbacks.h"
1637
1638 bool blenderYafrayOutput_t::putPixel(int x, int y,const yafray::color_t &c, 
1639                 yafray::CFLOAT alpha,yafray::PFLOAT depth)
1640 {
1641         unsigned char* bpt = (unsigned char*)R.rectot + ((((R.recty-1)-y)*R.rectx)<<2);
1642         int temp=(int)(c.R*255.0+0.5);
1643         if(temp>255) temp=255;
1644         bpt[4*x]=temp;
1645         temp=(int)(c.G*255.0+0.5);
1646         if(temp>255) temp=255;
1647         bpt[4*x+1]=temp;
1648         temp=(int)(c.B*255.0+0.5);
1649         if(temp>255) temp=255;
1650         bpt[4*x+2]=temp;
1651         temp=(int)(alpha*255.0+0.5);
1652         if(temp>255) temp=255;
1653         bpt[4*x+3]=temp;
1654         out++;
1655         if(out==4096)
1656         {
1657                 RE_local_render_display(0,R.recty-1, R.rectx, R.recty, R.rectot);
1658                 out=0;
1659         }
1660         if(RE_local_test_break())
1661                 return false;
1662         return true;
1663 }