94afe696a3b91cb78d75e475fa8b3306fdf9255d
[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                                 char temp[32];
760                                 sprintf(temp, "_map%d", m);
761                                 params["type"] = yafray::parameter_t("blendermapper");
762                                 params["name"] = yafray::parameter_t(blendmat->first + string(temp));
763                                 if ((mtex->texco & TEXCO_OBJECT) || (mtex->texco & TEXCO_REFL))
764                                 {
765                                         // For object & reflection mapping, add the object matrix to the modulator,
766                                         // as in LF script, use camera matrix if no object specified.
767                                         // In this case this means the inverse of that matrix
768                                         float texmat[4][4], itexmat[4][4];
769                                         if ((mtex->texco & TEXCO_OBJECT) && (mtex->object))
770                                                 MTC_Mat4CpyMat4(texmat, mtex->object->obmat);
771                                         else    // also for refl. map
772                                                 MTC_Mat4CpyMat4(texmat, maincam_obj->obmat);
773                                         MTC_Mat4Invert(itexmat, texmat);
774 #define flp yafray::parameter_t
775                                         params["m00"]=flp(itexmat[0][0]);  params["m01"]=flp(itexmat[1][0]);
776                                         params["m02"]=flp(itexmat[2][0]);  params["m03"]=flp(itexmat[3][0]);
777                                         params["m10"]=flp(itexmat[0][1]);  params["m11"]=flp(itexmat[1][1]);
778                                         params["m12"]=flp(itexmat[2][1]);  params["m13"]=flp(itexmat[3][1]);
779                                         params["m20"]=flp(itexmat[0][2]);  params["m21"]=flp(itexmat[1][2]);
780                                         params["m22"]=flp(itexmat[2][2]);  params["m23"]=flp(itexmat[3][2]);
781                                         params["m30"]=flp(itexmat[0][3]);  params["m31"]=flp(itexmat[1][3]);
782                                         params["m32"]=flp(itexmat[2][3]);  params["m33"]=flp(itexmat[3][3]);
783 #undef flp
784                                 }
785                                 // use image name instead of texname when texture is image
786                                 if ((tex->type==TEX_IMAGE) && tex->ima)
787                                         params["input"] = yafray::parameter_t(tex->ima->id.name);
788                                 else if ((tex->flag & TEX_COLORBAND) & (tex->coba!=NULL))
789                                         params["input"] = yafray::parameter_t(mtexL->first + "_coba");
790                                 else
791                                         params["input"] = yafray::parameter_t(mtexL->first);
792
793                                 // texture size
794                                 params["sizex"] = yafray::parameter_t(mtex->size[0]);
795                                 params["sizey"] = yafray::parameter_t(mtex->size[1]);
796                                 params["sizez"] = yafray::parameter_t(mtex->size[2]);
797
798                                 // texture offset
799                                 params["ofsx"] = yafray::parameter_t(mtex->ofs[0]);
800                                 params["ofsy"] = yafray::parameter_t(mtex->ofs[1]);
801                                 params["ofsz"] = yafray::parameter_t(mtex->ofs[2]);
802
803                                 // texture coordinates, have to disable 'sticky' in Blender
804                                 if (mtex->texco & TEXCO_UV)
805                                         params["texco"] = yafray::parameter_t("uv");
806                                 else if ((mtex->texco & TEXCO_GLOB) || (mtex->texco & TEXCO_OBJECT))
807                                         // object mode is also set as global, but the object matrix 
808                                         // was specified above with <modulator..>
809                                         params["texco"] = yafray::parameter_t("global");
810                                 else if (mtex->texco & TEXCO_ORCO)
811                                         params["texco"] = yafray::parameter_t("orco");
812                                 else if (mtex->texco & TEXCO_WINDOW)
813                                         params["texco"] = yafray::parameter_t("window");
814                                 else if (mtex->texco & TEXCO_NORM)
815                                         params["texco"] = yafray::parameter_t("normal");
816                                 else if (mtex->texco & TEXCO_REFL)
817                                         params["texco"] = yafray::parameter_t("reflect");
818
819                                 // texture projection axes, both image & procedural
820                                 string proj = "nxyz";           // 'n' for 'none'
821                                 params["proj_x"] = yafray::parameter_t(string(1,proj[mtex->projx]));
822                                 params["proj_y"] = yafray::parameter_t(string(1,proj[mtex->projy]));
823                                 params["proj_z"] = yafray::parameter_t(string(1,proj[mtex->projz]));
824
825                                 // texture mapping parameters only relevant to image type
826                                 if (tex->type==TEX_IMAGE) 
827                                 {
828                                         if (mtex->mapping==MTEX_FLAT)
829                                                 params["mapping"] = yafray::parameter_t("flat");
830                                         else if (mtex->mapping==MTEX_CUBE)
831                                                 params["mapping"] = yafray::parameter_t("cube");
832                                         else if (mtex->mapping==MTEX_TUBE)
833                                                 params["mapping"] = yafray::parameter_t("tube");
834                                         else if (mtex->mapping==MTEX_SPHERE)
835                                                 params["mapping"] = yafray::parameter_t("sphere");
836
837                                         // repeat
838                                         params["xrepeat"] = yafray::parameter_t(tex->xrepeat);
839                                         params["yrepeat"] = yafray::parameter_t(tex->yrepeat);
840
841                                         // clipping
842                                         if (tex->extend==TEX_EXTEND)
843                                                 params["clipping"] = yafray::parameter_t("extend");
844                                         else if (tex->extend==TEX_CLIP)
845                                                 params["clipping"] = yafray::parameter_t("clip");
846                                         else if (tex->extend==TEX_CLIPCUBE)
847                                                 params["clipping"] = yafray::parameter_t("clipcube");
848                                         else
849                                                 params["clipping"] = yafray::parameter_t("repeat");
850
851                                         // crop min/max
852                                         params["cropmin_x"] = yafray::parameter_t(tex->cropxmin);
853                                         params["cropmin_y"] = yafray::parameter_t(tex->cropymin);
854                                         params["cropmax_x"] = yafray::parameter_t(tex->cropxmax);
855                                         params["cropmax_y"] = yafray::parameter_t(tex->cropymax);
856
857                                         // rot90 flag
858                                         if (tex->imaflag & TEX_IMAROT) 
859                                                 params["rot90"] = yafray::parameter_t("on");
860                                         else
861                                                 params["rot90"] = yafray::parameter_t("off");
862                                 }
863                                 yafrayGate->addShader(params, lparams);
864                         }
865                 }
866
867                 // shader + modulators
868                 writeShader(blendmat->first, matr);
869
870         }
871
872                 // write the mappers & shaders for the TexFace case
873         if (!imagetex.empty()) {
874                 // Yafray doesn't have per-face-textures, only per-face-shaders,
875                 // so create as many mappers/shaders as the images used by the object
876                 params.clear();
877                 lparams.clear();
878                 int snum = 0;
879                 for (map<Image*, Material*>::const_iterator imgtex=imagetex.begin();
880                                 imgtex!=imagetex.end();++imgtex)
881                 {
882                         Material* matr = imgtex->second;
883
884                         // mapper
885                         params["type"] = yafray::parameter_t("blendermapper");
886                         char temp[32];
887                         sprintf(temp, "_ftex_mp%d", snum);
888                         params["name"] = yafray::parameter_t(string(matr->id.name) + string(temp));
889                         params["input"] = yafray::parameter_t(imgtex->first->id.name);
890                         // all yafray default settings, except for texco, so no need to set others
891                         params["texco"] = yafray::parameter_t("uv");
892                         yafrayGate->addShader(params, lparams);
893
894                         // shader, remember name, used later when writing per-face-shaders
895                         sprintf(temp, "_ftex_sh%d", snum);
896                         string shader_name = string(matr->id.name) + string(temp);
897                         imgtex_shader[imgtex->first] = shader_name;
898
899                         sprintf(temp, "_ftex_mp%d", snum++);
900                         string facetexname = string(matr->id.name) + string(temp);
901                         writeShader(shader_name, matr, facetexname);
902
903                 }
904         }
905
906 }
907
908 void yafrayPluginRender_t::genUVcoords(vector<yafray::GFLOAT> &uvcoords, VlakRen *vlr, TFace* uvc, bool comple)
909 {
910         if (uvc) 
911         {
912                 // use correct uv coords for this triangle
913                 int ui1=0, ui2=1, ui3=2;
914                 if (vlr->flag & R_DIVIDE_24) {
915                         ui3++;
916                         if (vlr->flag & R_FACE_SPLIT) { ui1++;  ui2++; }
917                 }
918                 else if (vlr->flag & R_FACE_SPLIT) { ui2++;  ui3++; }
919                 if (comple) {
920                         ui1 = (ui1+2) & 3;
921                         ui2 = (ui2+2) & 3;
922                         ui3 = (ui3+2) & 3;
923                 }
924                 uvcoords.push_back(uvc->uv[ui1][0]);  uvcoords.push_back(1-uvc->uv[ui1][1]);
925                 uvcoords.push_back(uvc->uv[ui2][0]);  uvcoords.push_back(1-uvc->uv[ui2][1]);
926                 uvcoords.push_back(uvc->uv[ui3][0]);  uvcoords.push_back(1-uvc->uv[ui3][1]);
927         }
928         else
929         {
930                 uvcoords.push_back(0);  uvcoords.push_back(0);
931                 uvcoords.push_back(0);  uvcoords.push_back(0);
932                 uvcoords.push_back(0);  uvcoords.push_back(0);
933         }
934 }
935
936 void yafrayPluginRender_t::genVcol(vector<yafray::CFLOAT> &vcol,VlakRen *vlr,
937                                                                                                                                                 int p1,int p2,int p3)
938 {
939         if (vlr->vcol)
940         {
941                 // vertex colors
942                 float vr, vg, vb;
943                 vr = ((vlr->vcol[p1] >> 24) & 255)/255.0;
944                 vg = ((vlr->vcol[p1] >> 16) & 255)/255.0;
945                 vb = ((vlr->vcol[p1] >> 8) & 255)/255.0;
946                 vcol.push_back(vr);  vcol.push_back(vg);  vcol.push_back(vb);
947                 vr = ((vlr->vcol[p2] >> 24) & 255)/255.0;
948                 vg = ((vlr->vcol[p2] >> 16) & 255)/255.0;
949                 vb = ((vlr->vcol[p2] >> 8) & 255)/255.0;
950                 vcol.push_back(vr);  vcol.push_back(vg);  vcol.push_back(vb);
951                 vr = ((vlr->vcol[p3] >> 24) & 255)/255.0;
952                 vg = ((vlr->vcol[p3] >> 16) & 255)/255.0;
953                 vb = ((vlr->vcol[p3] >> 8) & 255)/255.0;
954                 vcol.push_back(vr);  vcol.push_back(vg);  vcol.push_back(vb);
955         }
956         else
957         {
958                 vcol.push_back(0);  vcol.push_back(0);  vcol.push_back(0);
959                 vcol.push_back(0);  vcol.push_back(0);  vcol.push_back(0);
960                 vcol.push_back(0);  vcol.push_back(0);  vcol.push_back(0);
961         }
962 }
963
964 void yafrayPluginRender_t::genFace(vector<int> &faces,vector<string> &shaders,vector<int> &faceshader,
965                                                                                                                 vector<yafray::GFLOAT> &uvcoords,vector<yafray::CFLOAT> &vcol,
966                                                                                                                 map<VertRen*, int> &vert_idx,VlakRen *vlr,
967                                                                                                                 bool has_orco,bool has_uv)
968 {
969         Material* fmat = vlr->mat;
970         bool EXPORT_VCOL = ((fmat->mode & (MA_VERTEXCOL|MA_VERTEXCOLP))!=0);
971         string fmatname(fmat->id.name);
972         // use name in imgtex_shader list if 'TexFace' enabled for this face material
973         if (fmat->mode & MA_FACETEXTURE) {
974                 TFace* tface = vlr->tface;
975                 if (tface) {
976                         Image* fimg = (Image*)tface->tpage;
977                         if (fimg) fmatname = imgtex_shader[fimg];
978                 }
979         }
980         else if (fmatname.length()==0) fmatname = "blender_default";
981         bool newmat=true;
982         for(unsigned int i=0;i<shaders.size();++i)
983                 if(shaders[i]==fmatname)
984                 {
985                         newmat=false;
986                         faceshader.push_back(i);
987                         break;
988                 }
989         if(newmat)
990         {
991                 shaders.push_back(fmatname);
992                 faceshader.push_back(shaders.size()-1);
993         }
994         TFace* uvc = vlr->tface;        // possible uvcoords (v upside down)
995         int idx1, idx2, idx3;
996
997         idx1 = vert_idx.find(vlr->v1)->second;
998         idx2 = vert_idx.find(vlr->v2)->second;
999         idx3 = vert_idx.find(vlr->v3)->second;
1000
1001         // make sure the indices point to the vertices when orco coords exported
1002         if (has_orco) { idx1*=2;  idx2*=2;  idx3*=2; }
1003
1004         faces.push_back(idx1);  faces.push_back(idx2);  faces.push_back(idx3);
1005
1006         if(has_uv) genUVcoords(uvcoords,vlr,uvc);
1007
1008         // since Blender seems to need vcols when uvs are used, for yafray only export when the material actually uses vcols
1009         if (EXPORT_VCOL) genVcol(vcol, vlr, 0, 1, 2);
1010 }
1011
1012 void yafrayPluginRender_t::genCompleFace(vector<int> &faces,/*vector<string> &shaders,*/vector<int> &faceshader,
1013                                                                                                                 vector<yafray::GFLOAT> &uvcoords,vector<yafray::CFLOAT> &vcol,
1014                                                                                                                 map<VertRen*, int> &vert_idx,VlakRen *vlr,
1015                                                                                                                 bool has_orco,bool has_uv)
1016 {
1017         Material* fmat = vlr->mat;
1018         bool EXPORT_VCOL = ((fmat->mode & (MA_VERTEXCOL|MA_VERTEXCOLP))!=0);
1019
1020         faceshader.push_back(faceshader.back());
1021         TFace* uvc = vlr->tface;        // possible uvcoords (v upside down)
1022         int idx1, idx2, idx3;
1023         idx1 = vert_idx.find(vlr->v3)->second;
1024         idx2 = vert_idx.find(vlr->v4)->second;
1025         idx3 = vert_idx.find(vlr->v1)->second;
1026
1027         // make sure the indices point to the vertices when orco coords exported
1028         if (has_orco) { idx1*=2;  idx2*=2;  idx3*=2; }
1029
1030         faces.push_back(idx1);  faces.push_back(idx2);  faces.push_back(idx3);
1031
1032         if (has_uv) genUVcoords(uvcoords, vlr, uvc, true);
1033         if (EXPORT_VCOL) genVcol(vcol, vlr, 2, 3, 0);
1034 }
1035
1036 void yafrayPluginRender_t::genVertices(vector<yafray::point3d_t> &verts, int &vidx,
1037                                                                                                                                                          map<VertRen*, int> &vert_idx, VlakRen* vlr, bool has_orco, Object* obj)
1038 {
1039         VertRen* ver;
1040         float tvec[3];  // for back2world transform
1041         if (vert_idx.find(vlr->v1)==vert_idx.end()) 
1042         {
1043                 vert_idx[vlr->v1] = vidx++;
1044                 ver = vlr->v1;
1045                 MTC_cp3Float(ver->co, tvec);
1046                 MTC_Mat4MulVecfl(obj->imat, tvec);
1047                 verts.push_back(yafray::point3d_t(tvec[0], tvec[1], tvec[2]));
1048                 if (has_orco) 
1049                         verts.push_back(yafray::point3d_t(ver->orco[0],ver->orco[1],ver->orco[2]));
1050         }
1051         if (vert_idx.find(vlr->v2)==vert_idx.end()) 
1052         {
1053                 vert_idx[vlr->v2] = vidx++;
1054                 ver = vlr->v2;
1055                 MTC_cp3Float(ver->co, tvec);
1056                 MTC_Mat4MulVecfl(obj->imat, tvec);
1057                 verts.push_back(yafray::point3d_t(tvec[0], tvec[1], tvec[2]));
1058                 if (has_orco)
1059                         verts.push_back(yafray::point3d_t(ver->orco[0],ver->orco[1],ver->orco[2]));
1060         }
1061         if (vert_idx.find(vlr->v3)==vert_idx.end()) 
1062         {
1063                 vert_idx[vlr->v3] = vidx++;
1064                 ver = vlr->v3;
1065                 MTC_cp3Float(ver->co, tvec);
1066                 MTC_Mat4MulVecfl(obj->imat, tvec);
1067                 verts.push_back(yafray::point3d_t(tvec[0], tvec[1], tvec[2]));
1068                 if (has_orco)
1069                         verts.push_back(yafray::point3d_t(ver->orco[0],ver->orco[1],ver->orco[2]));
1070         }
1071         if ((vlr->v4) && (vert_idx.find(vlr->v4)==vert_idx.end())) 
1072         {
1073                 vert_idx[vlr->v4] = vidx++;
1074                 ver = vlr->v4;
1075                 MTC_cp3Float(ver->co, tvec);
1076                 MTC_Mat4MulVecfl(obj->imat, tvec);
1077                 verts.push_back(yafray::point3d_t(tvec[0], tvec[1], tvec[2]));
1078                 if (has_orco)
1079                         verts.push_back(yafray::point3d_t(ver->orco[0],ver->orco[1],ver->orco[2]));
1080         }
1081 }
1082
1083 void yafrayPluginRender_t::writeObject(Object* obj, const vector<VlakRen*> &VLR_list, const float obmat[4][4])
1084 {
1085         float mtr[4*4];
1086         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];
1087         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];
1088         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];
1089         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];
1090         yafrayGate->transformPush(mtr);
1091         
1092         VlakRen* face0 = VLR_list[0];
1093         Material* face0mat = face0->mat;
1094         
1095         bool castShadows = face0mat->mode & MA_TRACEBLE;
1096         float caus_IOR=1.0;
1097         yafray::color_t caus_tcolor(0.0, 0.0, 0.0), caus_rcolor(0.0, 0.0, 0.0);
1098         bool caus = (((face0->mat->mode & MA_RAYTRANSP) | (face0->mat->mode & MA_RAYMIRROR))!=0);
1099         if (caus) {
1100                 caus_IOR = face0mat->ang;
1101                 float tr = 1.0-face0mat->alpha;
1102                 caus_tcolor.set(face0mat->r*tr, face0mat->g*tr, face0mat->b*tr);
1103                 tr = face0mat->ray_mirror;
1104                 caus_rcolor.set(face0mat->mirr*tr, face0mat->mirg*tr, face0mat->mirb*tr);
1105         }
1106         bool has_orco = (face0->v1->orco!=NULL);
1107         bool no_auto = true;    //in case non-mesh, or mesh has no autosmooth
1108         float sm_angle = 0.1f;
1109         if (obj->type==OB_MESH) 
1110         {
1111                 Mesh* mesh = (Mesh*)obj->data;
1112                 if (mesh->flag & ME_AUTOSMOOTH) {
1113                         sm_angle = mesh->smoothresh;
1114                         no_auto = false;
1115                 }
1116         }
1117         // this for non-mesh as well
1118         if (no_auto) {
1119                 // no per face smooth flag in yafray, if AutoSmooth not used, 
1120                 // use smooth flag of the first face instead
1121                 if (face0->flag & ME_SMOOTH) sm_angle=90;
1122         }
1123         vector<yafray::point3d_t> verts;
1124         vector<yafray::CFLOAT> vcol;
1125         // now all vertices
1126         map<VertRen*, int> vert_idx;    // for removing duplicate verts and creating an index list
1127         int vidx = 0;   // vertex index counter
1128         bool has_uv=false;
1129         for (vector<VlakRen*>::const_iterator fci=VLR_list.begin();
1130                                 fci!=VLR_list.end();++fci)
1131         {
1132                 VlakRen* vlr = *fci;
1133                 genVertices(verts, vidx, vert_idx, vlr, has_orco, obj);
1134                 if(vlr->tface) has_uv=true;
1135         }
1136         // all faces using the index list created above
1137         vector<int> faces;
1138         vector<string> shaders;
1139         vector<int> faceshader;
1140         vector<yafray::GFLOAT> uvcoords;
1141         for (vector<VlakRen*>::const_iterator fci2=VLR_list.begin();
1142                                 fci2!=VLR_list.end();++fci2)
1143         {
1144                 VlakRen* vlr = *fci2;
1145                 genFace(faces, shaders, faceshader, uvcoords, vcol, vert_idx, vlr, has_orco, has_uv);
1146                 if (vlr->v4) 
1147                         genCompleFace(faces, faceshader, uvcoords, vcol, vert_idx, vlr, has_orco, has_uv);
1148         }
1149
1150         yafrayGate->addObject_trimesh(string(obj->id.name), verts, faces, uvcoords, vcol,
1151                         shaders, faceshader, sm_angle, castShadows, true, true, caus, has_orco,
1152                         caus_rcolor, caus_tcolor, caus_IOR);
1153         yafrayGate->transformPop();
1154 }
1155
1156
1157 // write all objects
1158 void yafrayPluginRender_t::writeAllObjects()
1159 {
1160
1161         // first all objects except dupliverts (and main instance object for dups)
1162         for (map<Object*, vector<VlakRen*> >::const_iterator obi=all_objects.begin();
1163                         obi!=all_objects.end(); ++obi)
1164         {
1165           // skip main duplivert object if in dupliMtx_list, written later
1166                 Object* obj = obi->first;
1167                 if (dupliMtx_list.find(string(obj->id.name))!=dupliMtx_list.end()) continue;
1168                 writeObject(obj, obi->second, obj->obmat);
1169         }
1170
1171         // Now all duplivert objects (if any) as instances of main object
1172         // The original object has been included in the VlakRen renderlist above (see convertBlenderScene.c)
1173         // but is written here which all other duplis are instances of.
1174         float obmat[4][4], cmat[4][4], imat[4][4], nmat[4][4];
1175         for (map<string, vector<float> >::const_iterator dupMtx=dupliMtx_list.begin();
1176                 dupMtx!=dupliMtx_list.end();++dupMtx) {
1177
1178                 // original inverse matrix, not actual matrix of object, but first duplivert.
1179                 for (int i=0;i<4;i++)
1180                         for (int j=0;j<4;j++)
1181                                 obmat[i][j] = dupMtx->second[(i<<2)+j];
1182                 MTC_Mat4Invert(imat, obmat);
1183
1184                 // first object written as normal (but with transform of first duplivert)
1185                 Object* obj = dup_srcob[dupMtx->first];
1186                 writeObject(obj, all_objects[obj], obmat);
1187
1188                 // all others instances of first
1189                 for (unsigned int curmtx=16;curmtx<dupMtx->second.size();curmtx+=16) 
1190                 {       // number of 4x4 matrices
1191                         // new mtx
1192                         for (int i=0;i<4;i++)
1193                                 for (int j=0;j<4;j++)
1194                                         nmat[i][j] = dupMtx->second[curmtx+(i<<2)+j];
1195
1196                         MTC_Mat4MulMat4(cmat, imat, nmat);      // transform with respect to original = inverse_original * new
1197
1198                         float mtr[4*4];
1199                         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];
1200                         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];
1201                         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];
1202                         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];
1203                         yafrayGate->transformPush(mtr);
1204
1205                         // new name from original
1206                         string name=(obj->id.name);
1207                         char temp[16];
1208                         sprintf(temp,"_dup%d",(curmtx>>4));
1209                         name+=temp;
1210                         yafrayGate->addObject_reference(name,obj->id.name);
1211                         yafrayGate->transformPop();
1212                 }
1213
1214         }
1215
1216 }
1217
1218 void yafrayPluginRender_t::writeAreaLamp(LampRen* lamp, int num, float iview[4][4])
1219 {
1220         yafray::paramMap_t params;
1221         
1222         if (lamp->area_shape!=LA_AREA_SQUARE) return;
1223         float *a=lamp->area[0], *b=lamp->area[1], *c=lamp->area[2], *d=lamp->area[3];
1224         float power=lamp->energy;
1225         
1226         string md = "off";
1227         // if no GI used, the GIphotons flag can still be set, so only use when 'full' selected
1228         if ((R.r.GImethod==2) && (R.r.GIphotons)) { md="on";  power*=R.r.GIpower; }
1229         params["type"]=yafray::parameter_t("arealight");
1230         char temp[16];
1231         sprintf(temp,"LAMP%d",num+1);
1232         params["name"]=yafray::parameter_t(temp);
1233         params["dummy"]=yafray::parameter_t(md);
1234         params["power"]=yafray::parameter_t(power);
1235         // samples not used for GI with photons, can still be exported, is ignored
1236         int psm=0, sm = lamp->ray_totsamp;
1237         if (sm>=25) psm = sm/5;
1238         params["samples"]=yafray::parameter_t(sm);
1239         params["psamples"]=yafray::parameter_t(psm);
1240         
1241         // transform area lamp coords back to world
1242         float lpco[4][3];
1243         MTC_Mat4Invert(iview, R.viewmat);
1244         MTC_cp3Float(a, lpco[0]);
1245         MTC_Mat4MulVecfl(iview, lpco[0]);
1246         MTC_cp3Float(b, lpco[1]);
1247         MTC_Mat4MulVecfl(iview, lpco[1]);
1248         MTC_cp3Float(c, lpco[2]);
1249         MTC_Mat4MulVecfl(iview, lpco[2]);
1250         MTC_cp3Float(d, lpco[3]);
1251         MTC_Mat4MulVecfl(iview, lpco[3]);       
1252         params["a"] = yafray::parameter_t(yafray::point3d_t(lpco[0][0], lpco[0][1], lpco[0][2]));
1253         params["b"] = yafray::parameter_t(yafray::point3d_t(lpco[1][0], lpco[1][1], lpco[1][2]));
1254         params["c"] = yafray::parameter_t(yafray::point3d_t(lpco[2][0], lpco[2][1], lpco[2][2]));
1255         params["d"] = yafray::parameter_t(yafray::point3d_t(lpco[3][0], lpco[3][1], lpco[3][2]));
1256         
1257         params["color"]=yafray::parameter_t(yafray::color_t(lamp->r,lamp->g,lamp->b));
1258         yafrayGate->addLight(params);
1259 }
1260
1261 void yafrayPluginRender_t::writeLamps()
1262 {
1263         // inver viewmatrix needed for back2world transform
1264         float iview[4][4];
1265         // R.viewinv != inv.R.viewmat because of possible ortho mode (see convertBlenderScene.c)
1266         // have to invert it here
1267         MTC_Mat4Invert(iview, R.viewmat);
1268
1269         // all lamps
1270         for (int i=0;i<R.totlamp;i++)
1271         {
1272                 yafray::paramMap_t params;
1273                 string type="";
1274                 LampRen* lamp = R.la[i];
1275                 
1276                 if (lamp->type==LA_AREA) { writeAreaLamp(lamp, i, iview);  continue; }
1277                 
1278                 // TODO: add decay setting in yafray
1279                 bool is_softL=false, is_sphereL=false;
1280                 if (lamp->type==LA_LOCAL) {
1281                         if (lamp->mode & LA_YF_SOFT) {
1282                                 // shadowmapped omnidirectional light
1283                                 params["type"] = yafray::parameter_t("softlight");
1284                                 is_softL = true;
1285                         }
1286                         else if ((lamp->mode & LA_SHAD_RAY) && (lamp->YF_ltradius>0.0)) {
1287                                 // area sphere, only when ray shadows enabled and radius>0.0
1288                                 params["type"] = yafray::parameter_t("spherelight");
1289                                 is_sphereL = true;
1290                         }
1291                         else params["type"] = yafray::parameter_t("pointlight");
1292                 }
1293                 else if (lamp->type==LA_SPOT)
1294                         params["type"] = yafray::parameter_t("spotlight");
1295                 else if ((lamp->type==LA_SUN) || (lamp->type==LA_HEMI)) // hemi exported as sun
1296                         params["type"] = yafray::parameter_t("sunlight");
1297                 else if (lamp->type==LA_YF_PHOTON)
1298                         params["type"] = yafray::parameter_t("photonlight");
1299                 else {
1300                         // possibly unknown type, ignore
1301                         cout << "Unknown Blender lamp type: " << lamp->type << endl;
1302                         continue;
1303                 }
1304                 
1305                 //no name available here, create one
1306                 char temp[16];
1307                 sprintf(temp,"LAMP%d",i+1);
1308                 params["name"] = yafray::parameter_t(temp);
1309                 // color already premultiplied by energy, so only need distance here
1310                 float pwr = 1;  // default for sun/hemi, distance irrelevant
1311                 if ((lamp->type!=LA_SUN) && (lamp->type!=LA_HEMI)) {
1312                         if (lamp->mode & LA_SPHERE) {
1313                                 // best approx. as used in LFexport script (LF d.f.m. 4pi?)
1314                                 pwr = lamp->dist*(lamp->dist+1)*(0.25/M_PI);
1315                                 //decay = 2;
1316                         }
1317                         else {
1318                                 pwr = lamp->dist;
1319                                 //decay = 1;
1320                         }
1321                 }
1322
1323                 if (is_sphereL) {
1324                         // 'dummy' mode for spherelight when used with gpm
1325                         string md = "off";
1326                         // if no GI used, the GIphotons flag can still be set, so only use when 'full' selected
1327                         if ((R.r.GImethod==2) && (R.r.GIphotons)) { md="on";  pwr*=R.r.GIpower; }
1328                         params["power"] = yafray::parameter_t(pwr);
1329                         params["dummy"] = yafray::parameter_t(md);
1330                 }
1331                 else params["power"] = yafray::parameter_t(pwr);
1332                 
1333                 // cast_shadows flag not used with softlight, spherelight or photonlight
1334                 if ((!is_softL) && (!is_sphereL) && (lamp->type!=LA_YF_PHOTON)) {
1335                         string lpmode="off";
1336                         // Shadows only when Blender has shadow button enabled, only spots use LA_SHAD flag.
1337                         // Also blender hemilights exported as sunlights which might have shadow flag set
1338                         // should have cast_shadows set to off (reported by varuag)
1339                         if (lamp->type!=LA_HEMI) {
1340                                 if (R.r.mode & R_SHADOW)
1341                                         if (((lamp->type==LA_SPOT) && (lamp->mode & LA_SHAD)) || (lamp->mode & LA_SHAD_RAY)) lpmode="on";
1342                         }
1343                         params["cast_shadows"] = yafray::parameter_t(lpmode);
1344                 }
1345                 
1346                 // spot specific stuff
1347                 bool has_halo = ((lamp->type==LA_SPOT) && (lamp->mode & LA_HALO) && (lamp->haint>0.0));
1348                 if (lamp->type==LA_SPOT) {
1349                         // conversion already changed spotsize to cosine of half angle
1350                         float ld = 1-lamp->spotsi;      //convert back to blender slider setting
1351                         if (ld!=0) ld = 1.f/ld;
1352                         params["size"] = yafray::parameter_t(acos(lamp->spotsi)*180.0/M_PI);
1353                         params["blend"] = yafray::parameter_t(lamp->spotbl*ld);
1354                         params["beam_falloff"] = yafray::parameter_t(2.0);
1355                         // halo params
1356                         if (has_halo) {
1357                                 params["halo"] = yafray::parameter_t("on");
1358                                 params["res"] = yafray::parameter_t(lamp->YF_bufsize);
1359                                 int hsmp = ((12-lamp->shadhalostep)*16)/12;
1360                                 hsmp = (hsmp+1)*16;     // makes range (16, 272) for halostep(12, 0), good enough?
1361                                 params["samples"] = yafray::parameter_t(hsmp);
1362                                 params["shadow_samples"] = yafray::parameter_t(lamp->samp*lamp->samp);
1363                                 params["halo_blur"] = yafray::parameter_t(0.0);
1364                                 params["shadow_blur"] = yafray::parameter_t(lamp->soft*0.01f);
1365                                 params["fog_density"] = yafray::parameter_t(lamp->haint*0.2f);
1366                         }
1367                 }
1368                 else if (is_softL) {
1369                         // softlight
1370                         params["res"] = yafray::parameter_t(lamp->YF_bufsize);
1371                         params["radius"] = yafray::parameter_t(lamp->soft);
1372                         params["bias"] = yafray::parameter_t(lamp->bias);
1373                 }
1374                 else if (is_sphereL) {
1375                         // spherelight
1376                         int psm=0, sm = lamp->ray_samp*lamp->ray_samp;
1377                         if (sm>=25) psm = sm/5;
1378                         params["radius"] = yafray::parameter_t(lamp->YF_ltradius);
1379                         params["samples"] = yafray::parameter_t(sm);
1380                         params["psamples"] = yafray::parameter_t(psm);
1381                         params["qmc_method"] = yafray::parameter_t(1);
1382                 }
1383                 else if (lamp->type==LA_YF_PHOTON) {
1384                         string qmc="off";
1385                         if (lamp->YF_useqmc) qmc="on";
1386                         params["photons"] = yafray::parameter_t(lamp->YF_numphotons);
1387                         params["search"] = yafray::parameter_t(lamp->YF_numsearch);
1388                         params["depth"] = yafray::parameter_t(lamp->YF_phdepth);
1389                         params["use_QMC"] = yafray::parameter_t(qmc);
1390                         params["angle"] = yafray::parameter_t(acos(lamp->spotsi)*180.0/M_PI);
1391                         float cl = lamp->YF_causticblur/sqrt((float)lamp->YF_numsearch);
1392                         params["fixedradius"] = yafray::parameter_t(lamp->YF_causticblur);
1393                         params["cluster"] = yafray::parameter_t(cl);
1394                 }
1395
1396                 // transform lamp co & vec back to world
1397                 float lpco[3], lpvec[3];
1398                 MTC_cp3Float(lamp->co, lpco);
1399                 MTC_Mat4MulVecfl(iview, lpco);
1400                 MTC_cp3Float(lamp->vec, lpvec);
1401                 MTC_Mat4Mul3Vecfl(iview, lpvec);
1402
1403                 // position, (==-blendir for sun/hemi)
1404                 if ((lamp->type==LA_SUN) || (lamp->type==LA_HEMI))
1405                         params["from"] = yafray::parameter_t(yafray::point3d_t(-lpvec[0], -lpvec[1], -lpvec[2]));
1406                 else
1407                         params["from"] = yafray::parameter_t(yafray::point3d_t(lpco[0], lpco[1], lpco[2]));
1408                 // 'to' for spot/photonlight, already calculated by Blender
1409                 if ((lamp->type==LA_SPOT) || (lamp->type==LA_YF_PHOTON)) {
1410                         params["to"] = yafray::parameter_t(yafray::point3d_t(lpco[0] + lpvec[0],
1411                                                                                                                                                                                                                                          lpco[1] + lpvec[1],
1412                                                                                                                                                                                                                                          lpco[2] + lpvec[2]));
1413                         if (has_halo) params["fog"] = yafray::parameter_t(yafray::color_t(1.0, 1.0, 1.0));
1414                 }
1415                 
1416                 // color
1417                 // rgb in LampRen is premultiplied by energy, power is compensated for that above
1418                 params["color"] = yafray::parameter_t(yafray::color_t(lamp->r, lamp->g, lamp->b));
1419                 yafrayGate->addLight(params);
1420         }
1421 }
1422
1423
1424 // write main camera
1425 void yafrayPluginRender_t::writeCamera()
1426 {
1427         yafray::paramMap_t params;
1428         params["name"]=yafray::parameter_t("MAINCAM");
1429         if (R.r.mode & R_ORTHO)
1430                 params["type"] = yafray::parameter_t("ortho");
1431         else
1432                 params["type"] = yafray::parameter_t("perspective");
1433         params["resx"]=yafray::parameter_t(R.r.xsch);
1434         params["resy"]=yafray::parameter_t(R.r.ysch);
1435         float aspect = 1;
1436         if (R.r.xsch < R.r.ysch) aspect = float(R.r.xsch)/float(R.r.ysch);      
1437
1438         params["focal"]=yafray::parameter_t(mainCamLens/(aspect*32.0));
1439
1440         // dof params, only valid for real camera
1441         if (maincam_obj->type==OB_CAMERA) {
1442                 Camera* cam = (Camera*)maincam_obj->data;
1443                 params["dof_distance"] = yafray::parameter_t(cam->YF_dofdist);
1444                 params["aperture"] = yafray::parameter_t(cam->YF_aperture);
1445                 if (cam->flag & CAM_YF_NO_QMC)
1446                         params["use_qmc"] = yafray::parameter_t("off");
1447                 else
1448                         params["use_qmc"] = yafray::parameter_t("on");
1449         }
1450
1451         params["from"]=yafray::parameter_t(
1452                         yafray::point3d_t(maincam_obj->obmat[3][0], maincam_obj->obmat[3][1], maincam_obj->obmat[3][2]));
1453         float fdist = fabs(R.viewmat[3][2]);
1454         if (R.r.mode & R_ORTHO) fdist *= 0.01f;
1455         params["to"]=yafray::parameter_t(
1456                         yafray::point3d_t(maincam_obj->obmat[3][0] - fdist * R.viewmat[0][2],
1457                                                                                                 maincam_obj->obmat[3][1] - fdist * R.viewmat[1][2],
1458                                                                                                 maincam_obj->obmat[3][2] - fdist * R.viewmat[2][2]));
1459         params["up"]=yafray::parameter_t(
1460                         yafray::point3d_t(maincam_obj->obmat[3][0] + R.viewmat[0][1],
1461                                                                                                 maincam_obj->obmat[3][1] + R.viewmat[1][1],
1462                                                                                                 maincam_obj->obmat[3][2] + R.viewmat[2][1]));
1463
1464         yafrayGate->addCamera(params);
1465 }
1466
1467 void yafrayPluginRender_t::writeHemilight()
1468 {
1469         yafray::paramMap_t params;
1470         params["type"] = yafray::parameter_t("hemilight");
1471         params["name"] = yafray::parameter_t("hemi_LT");
1472         params["power"] = yafray::parameter_t(R.r.GIpower);
1473         switch (R.r.GIquality)
1474         {
1475                 case 1 :
1476                 case 2 : params["samples"]=yafray::parameter_t(16);  break;
1477                 case 3 : params["samples"]=yafray::parameter_t(36);  break;
1478                 case 4 : params["samples"]=yafray::parameter_t(64);  break;
1479                 case 5 : params["samples"]=yafray::parameter_t(128);  break;
1480                 default: params["samples"]=yafray::parameter_t(25);
1481         }
1482         yafrayGate->addLight(params);
1483 }
1484
1485 void yafrayPluginRender_t::writePathlight()
1486 {
1487         if (R.r.GIphotons)
1488         {
1489                 yafray::paramMap_t params;
1490                 params["type"]=yafray::parameter_t("globalphotonlight");
1491                 params["name"]=yafray::parameter_t("gpm");
1492                 params["photons"]=yafray::parameter_t(R.r.GIphotoncount);
1493                 params["radius"]=yafray::parameter_t(R.r.GIphotonradius);
1494                 params["depth"]=yafray::parameter_t(((R.r.GIdepth>2) ? (R.r.GIdepth-1) : 1));
1495                 params["caus_depth"]=yafray::parameter_t(R.r.GIcausdepth);
1496                 params["search"]=yafray::parameter_t(R.r.GImixphotons);
1497                 yafrayGate->addLight(params);
1498         }
1499         yafray::paramMap_t params;
1500         params["type"]=yafray::parameter_t("pathlight");
1501         params["name"]=yafray::parameter_t("path_LT");
1502         params["power"]=yafray::parameter_t(R.r.GIindirpower);
1503         params["depth"]=yafray::parameter_t(((R.r.GIphotons) ? 1 : R.r.GIdepth));
1504         params["caus_depth"]=yafray::parameter_t(R.r.GIcausdepth);
1505         if(R.r.GIdirect && R.r.GIphotons) params["direct"]=yafray::parameter_t("on");
1506         if (R.r.GIcache && ! (R.r.GIdirect && R.r.GIphotons))
1507         {
1508                 switch (R.r.GIquality)
1509                 {
1510                         case 1 : params["samples"]=yafray::parameter_t(128);break;
1511                         case 2 : params["samples"]=yafray::parameter_t(256);break;
1512                         case 3 : params["samples"]=yafray::parameter_t(512);break;
1513                         case 4 : params["samples"]=yafray::parameter_t(1024);break;
1514                         case 5 : params["samples"]=yafray::parameter_t(2048);break;
1515                         default: params["samples"]=yafray::parameter_t(256);
1516                 }
1517                 float aspect = 1;
1518                 if (R.r.xsch < R.r.ysch) aspect = float(R.r.xsch)/float(R.r.ysch);
1519                 float sbase = 2.0/float(R.r.xsch);
1520                 params["cache"]=yafray::parameter_t("on");
1521                 params["use_QMC"]=yafray::parameter_t("on");
1522                 params["threshold"]=yafray::parameter_t(R.r.GIrefinement);
1523                 params["cache_size"]=yafray::parameter_t(sbase*R.r.GIpixelspersample);
1524                 params["shadow_threshold"]=yafray::parameter_t(1.0 - R.r.GIshadowquality);
1525                 params["grid"]=yafray::parameter_t(82);
1526                 params["search"]=yafray::parameter_t(35);
1527         }
1528         else
1529         {
1530                 switch (R.r.GIquality)
1531                 {
1532                         case 1 : params["samples"]=yafray::parameter_t(16);break;
1533                         case 2 : params["samples"]=yafray::parameter_t(36);break;
1534                         case 3 : params["samples"]=yafray::parameter_t(64);break;
1535                         case 4 : params["samples"]=yafray::parameter_t(128);break;
1536                         case 5 : params["samples"]=yafray::parameter_t(256);break;
1537                         default: params["samples"]=yafray::parameter_t(25);break;
1538                 }
1539         }
1540         yafrayGate->addLight(params);
1541 }
1542
1543 bool yafrayPluginRender_t::writeWorld()
1544 {
1545         World *world = G.scene->world;
1546         if (R.r.GIquality!=0) {
1547                 if (R.r.GImethod==1) {
1548                         if (world==NULL) cout << "WARNING: need world background for skydome!\n";
1549                         writeHemilight();
1550                 }
1551                 else if (R.r.GImethod==2) writePathlight();
1552         }
1553
1554         if (world==NULL) return false;
1555
1556         yafray::paramMap_t params;
1557         for (int i=0;i<6;i++) {
1558                 MTex* wtex = world->mtex[i];
1559                 if (!wtex) continue;
1560                 Image* wimg = wtex->tex->ima;
1561                 if ((wtex->tex->type==TEX_IMAGE) && (wimg!=NULL)) {
1562                         string wt_path = wimg->name;
1563                         adjustPath(wt_path);
1564                         if (BLI_testextensie(wimg->name, ".hdr")) {
1565                                 params["type"] = yafray::parameter_t("HDRI");
1566                                 params["name"] = yafray::parameter_t("world_background");
1567                                 // since exposure adjust is an integer, using the texbri slider isn't actually very useful here (result either -1/0/1)
1568                                 params["exposure_adjust"] = yafray::parameter_t(int(world->mtex[i]->tex->bright-1));
1569                                 params["mapping"] = yafray::parameter_t("probe");
1570                                 params["filename"] = yafray::parameter_t(wt_path);
1571                                 yafrayGate->addBackground(params);
1572                                 return true;
1573                         }
1574                         else if (BLI_testextensie(wimg->name, ".jpg") || BLI_testextensie(wimg->name, ".jpeg") || BLI_testextensie(wimg->name, ".tga")) {
1575                                 params["type"] = yafray::parameter_t("image");
1576                                 params["name"] = yafray::parameter_t("world_background");
1577                                 /*
1578                                 // not yet in yafray, always assumes spheremap for now, not the same as in Blender,
1579                                 // which for some reason is scaled by 2 in Blender???
1580                                 if (wtex->texco & TEXCO_ANGMAP)
1581                                         params["mapping"] = yafray::parameter_t("probe");
1582                                 else
1583                                         params["mapping"] = yafray::parameter_t("sphere");
1584                                 */
1585                                 params["filename"] = yafray::parameter_t(wt_path);
1586                                 yafrayGate->addBackground(params);
1587                                 return true;
1588                         }
1589                 }
1590         }
1591
1592         params.clear();
1593         params["type"] = yafray::parameter_t("constant");
1594         params["name"] = yafray::parameter_t("world_background");
1595         // if no GI used, the GIpower parameter is not always initialized, so in that case ignore it
1596         // (have to change method to init yafray vars in Blender)
1597         float bg_mult = (R.r.GImethod==0) ? 1 : R.r.GIpower;
1598         params["color"]=yafray::parameter_t(yafray::color_t(world->horr * bg_mult,
1599                                                                                                                                                                                                                         world->horg * bg_mult,
1600                                                                                                                                                                                                                         world->horb * bg_mult));
1601         yafrayGate->addBackground(params);
1602         return true;
1603 }
1604
1605 #include "RE_callbacks.h"
1606
1607 bool blenderYafrayOutput_t::putPixel(int x, int y,const yafray::color_t &c, 
1608                 yafray::CFLOAT alpha,yafray::PFLOAT depth)
1609 {
1610         unsigned char* bpt = (unsigned char*)R.rectot + ((((R.recty-1)-y)*R.rectx)<<2);
1611         int temp=(int)(c.R*255.0+0.5);
1612         if(temp>255) temp=255;
1613         bpt[4*x]=temp;
1614         temp=(int)(c.G*255.0+0.5);
1615         if(temp>255) temp=255;
1616         bpt[4*x+1]=temp;
1617         temp=(int)(c.B*255.0+0.5);
1618         if(temp>255) temp=255;
1619         bpt[4*x+2]=temp;
1620         temp=(int)(alpha*255.0+0.5);
1621         if(temp>255) temp=255;
1622         bpt[4*x+3]=temp;
1623         out++;
1624         if(out==4096)
1625         {
1626                 RE_local_render_display(0,R.recty-1, R.rectx, R.recty, R.rectot);
1627                 out=0;
1628         }
1629         if(RE_local_test_break())
1630                 return false;
1631         return true;
1632 }