New export through plugin scheme for yafray. It is working on linux and mac os x
[blender.git] / source / blender / yafray / intern / export_Plugin.cpp
1 #include"export_Plugin.h"
2
3 #include <math.h>
4
5 using namespace std;
6
7
8 #ifdef WIN32 
9
10 #include<windows.h>
11
12 #ifndef FILE_MAXDIR
13 #define FILE_MAXDIR  160
14 #endif
15
16 #ifndef FILE_MAXFILE
17 #define FILE_MAXFILE 80
18 #endif
19
20
21 static string find_path()
22 {
23         HKEY    hkey;
24         DWORD dwType, dwSize;
25
26         if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,"Software\\YafRay Team\\YafRay",0,KEY_READ,&hkey)==ERROR_SUCCESS)
27         {
28                 dwType = REG_EXPAND_SZ;
29                 dwSize = MAX_PATH;
30                 DWORD dwStat;
31
32                 char *pInstallDir=new char[MAX_PATH];
33
34                 dwStat=RegQueryValueEx(hkey, TEXT("InstallDir"), 
35                         NULL, NULL,(LPBYTE)pInstallDir, &dwSize);
36                 
37                 if (dwStat == NO_ERROR)
38                 {
39                         string res=pInstallDir;
40                         delete [] pInstallDir;
41                         return res;
42                 }
43                 else
44                         cout << "Couldn't READ \'InstallDir\' value. Is yafray correctly installed?\n";
45                 delete [] pInstallDir;
46
47                 RegCloseKey(hkey);
48         }       
49         else
50                 cout << "Couldn't FIND registry key for yafray, is it installed?\n";
51
52         return string("");
53
54 }
55
56 static int createDir(char* name)
57 {
58         if (BLI_exists(name))
59                 return 2;       //exists
60         if (CreateDirectory((LPCTSTR)(name), NULL)) {
61                 cout << "Directory: " << name << " created\n";
62                 return 1;       // created
63         }
64         else    {
65                 cout << "Could not create directory: " << name << endl;
66                 return 0;       // fail
67         }
68 }
69
70 extern "C" { extern char bprogname[]; }
71
72 // add drive character if not in path string, using blender executable location as reference
73 static void addDrive(string &path)
74 {
75         int sp = path.find_first_of(":");
76         if (sp==-1) {
77                 string blpath = bprogname;
78                 sp = blpath.find_first_of(":");
79                 if (sp!=-1) path = blpath.substr(0, sp+1) + path;
80         }
81 }
82
83 #else
84
85 #include <sys/stat.h>
86 #include <sys/types.h>
87 #include <sys/wait.h>
88 #include <signal.h>
89 #include <stdlib.h>
90 #include <unistd.h>
91 #endif
92
93 static string YafrayPath()
94 {
95 #ifdef WIN32
96         string path=find_path();
97         return path+"\\libyafrayplugin.dll";
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_IXOTH) return fp;
112         }
113         return "";
114 #endif
115 }
116
117 static string YafrayPluginPath()
118 {
119 #ifdef WIN32
120         return find_path();
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 }
146
147 bool yafrayPluginRender_t::initExport()
148 {
149         imgout="YBPtest.tga";
150         if(handle==NULL)
151         {
152                 string location=YafrayPath();
153                 //handle=dlopen(location.c_str(),RTLD_NOW);
154                 handle=PIL_dynlib_open((char *)location.c_str());
155                  if(handle==NULL)
156                 {
157                         //cerr<<"Error loading yafray plugin: "<<dlerror()<<endl;
158                         cerr<<"Error loading yafray plugin: "<<PIL_dynlib_get_error_as_string(handle)<<endl;
159                         return false;
160                 }
161         }
162         yafray::yafrayConstructor *constructor;
163         //constructor=(yafray::yafrayConstructor *)dlsym(handle,YAFRAY_SYMBOL);
164         constructor=(yafray::yafrayConstructor *)PIL_dynlib_find_symbol(handle,YAFRAY_SYMBOL);
165         if(constructor==NULL)
166         {
167                 cerr<<"Error loading yafray plugin: "<<PIL_dynlib_get_error_as_string(handle)<<endl;
168                 return false;
169         }
170         if(yafrayGate!=NULL) delete yafrayGate;
171         yafrayGate=constructor(1,YafrayPluginPath());
172         
173         cout<<"YafRay plugin loaded"<<endl;
174         
175         if(R.rectot == NULL)
176                 R.rectot = (unsigned int *)MEM_callocN(sizeof(int)*R.rectx*R.recty, "rectot");
177
178         for (unsigned short y=0;y<R.recty;y++) {
179                 unsigned char* bpt = (unsigned char*)R.rectot + ((((R.recty-1)-y)*R.rectx)<<2);
180                 for (unsigned short x=0;x<R.rectx;x++) {
181                         bpt[2] = 128;
182                         bpt[1] = 0;
183                         bpt[0] = 0;
184                         bpt[3] = 255;
185                         bpt += 4;
186                 }
187         }
188         
189         cout<<"Image allocated"<<endl;
190         return true;
191 }
192
193 bool yafrayPluginRender_t::writeRender()
194 {
195         yafray::paramMap_t params;
196         params["camera_name"]=yafray::parameter_t("MAINCAM");
197         params["raydepth"]=yafray::parameter_t(R.r.YF_raydepth);
198         params["gamma"]=yafray::parameter_t(R.r.YF_gamma);
199         params["exposure"]=yafray::parameter_t(R.r.YF_exposure);
200         if(R.r.YF_AA)
201         {
202                 params["AA_passes"]=yafray::parameter_t(R.r.YF_AApasses);
203                 params["AA_minsamples"]=yafray::parameter_t(R.r.YF_AAsamples);
204         }
205         else
206         {
207                 if ((R.r.GImethod!=0) && (R.r.GIquality>1) && (!R.r.GIcache))
208                 {
209                         params["AA_passes"]=yafray::parameter_t(5);
210                         params["AA_minsamples"]=yafray::parameter_t(5);
211                 }
212                 else if ((R.r.mode & R_OSA) && (R.r.osa)) 
213                 {
214                         params["AA_passes"]=yafray::parameter_t((R.r.osa%4)==0 ? R.r.osa/4 : 1);
215                         params["AA_minsamples"]=yafray::parameter_t((R.r.osa%4)==0 ? 4 : R.r.osa);
216                 }
217                 else 
218                 {
219                         params["AA_passes"]=yafray::parameter_t(0);
220                         params["AA_minsamples"]=yafray::parameter_t(1);
221                 }
222         }
223         if (hasworld) params["background_name"]=yafray::parameter_t("world_background");
224         params["AA_pixelwidth"]=yafray::parameter_t(1.5);
225         params["AA_threshold"]=yafray::parameter_t(0.05);
226         params["bias"]=yafray::parameter_t(R.r.YF_raybias);
227         //params["outfile"]=yafray::parameter_t(imgout);
228         blenderYafrayOutput_t output;
229         yafrayGate->render(params,output);
230         cout<<"render finished"<<endl;
231         yafrayGate->clear();
232         return true;
233 }
234
235 bool yafrayPluginRender_t::finishExport()
236 {
237         //displayImage();
238         return true;
239 }
240
241 // displays the image rendered with xml export
242 // Now loads rendered image into blender renderbuf.
243 void yafrayPluginRender_t::displayImage()
244 {
245         // although it is possible to load the image using blender,
246         // maybe it is best to just do a read here, for now the yafray output is always a raw tga anyway
247
248         // rectot already freed in initrender
249         R.rectot = (unsigned int *)MEM_callocN(sizeof(int)*R.rectx*R.recty, "rectot");
250
251         FILE* fp = fopen(imgout.c_str(), "rb");
252         if (fp==NULL) {
253                 cout << "YAF_displayImage(): Could not open image file\n";
254                 return;
255         }
256
257         unsigned char header[18];
258         fread(&header, 1, 18, fp);
259         unsigned short width = (unsigned short)(header[12] + (header[13]<<8));
260         unsigned short height = (unsigned short)(header[14] + (header[15]<<8));
261         unsigned char byte_per_pix = (unsigned char)(header[16]>>3);
262         // read past any id (none in this case though)
263         unsigned int idlen = (unsigned int)header[0];
264         if (idlen) fseek(fp, idlen, SEEK_CUR);
265
266         // read data directly into buffer, picture is upside down
267         for (unsigned short y=0;y<height;y++) {
268                 unsigned char* bpt = (unsigned char*)R.rectot + ((((height-1)-y)*width)<<2);
269                 for (unsigned short x=0;x<width;x++) {
270                         bpt[2] = (unsigned char)fgetc(fp);
271                         bpt[1] = (unsigned char)fgetc(fp);
272                         bpt[0] = (unsigned char)fgetc(fp);
273                         if (byte_per_pix==4)
274                                 bpt[3] = (unsigned char)fgetc(fp);
275                         else
276                                 bpt[3] = 255;
277                         bpt += 4;
278                 }
279         }
280
281         fclose(fp);
282         fp = NULL;
283 }
284
285
286 void yafrayPluginRender_t::writeTextures()
287 {
288         for (map<string, pair<Material*, MTex*> >::const_iterator blendtex=used_textures.begin();
289                                                 blendtex!=used_textures.end();++blendtex) 
290         {
291                 yafray::paramMap_t params;
292                 list<yafray::paramMap_t> lparams;
293                 MTex* mtex = blendtex->second.second;
294                 Tex* tex = mtex->tex;
295                 params["name"]=yafray::parameter_t(blendtex->first);
296                 switch (tex->type) {
297                         case TEX_STUCCI:
298                                 // stucci is clouds as bump, but could be added to yafray to handle both wall in/out as well.
299                                 // noisedepth must be at least 1 in yafray
300                         case TEX_CLOUDS: 
301                                 params["type"]=yafray::parameter_t("clouds");
302                                 params["depth"]=yafray::parameter_t(tex->noisedepth+1);
303                                 break;
304                         case TEX_WOOD:
305                         {
306                                 params["type"]=yafray::parameter_t("wood");
307                                 params["depth"]=yafray::parameter_t(tex->noisedepth+1);
308                                 params["turbulence"]=yafray::parameter_t(tex->turbul);
309                                 params["ringscale_x"]=yafray::parameter_t(mtex->size[0]);
310                                 params["ringscale_y"]=yafray::parameter_t(mtex->size[1]);
311                                 string ts = "on";
312                                 if (tex->noisetype==TEX_NOISESOFT) ts = "off";
313                                 params["hard"]=yafray::parameter_t(ts);
314                                 break;
315                         }
316                         case TEX_MARBLE: 
317                         {
318                                 params["type"]=yafray::parameter_t("marble");
319                                 params["depth"]=yafray::parameter_t(tex->noisedepth+1);
320                                 params["turbulence"]=yafray::parameter_t(tex->turbul);
321                                 string ts = "on";
322                                 if (tex->noisetype==TEX_NOISESOFT) ts = "off";
323                                 params["hard"]=yafray::parameter_t(ts);
324                                 if (tex->stype==1)
325                                         params["sharpness"]=yafray::parameter_t(5);
326                                 else if (tex->stype==2)
327                                         params["sharpness"]=yafray::parameter_t(10);
328                                 else
329                                         params["sharpness"]=yafray::parameter_t(1);
330                                 break;
331                         }
332                         case TEX_IMAGE: 
333                         {
334                                 Image* ima = tex->ima;
335                                 if (ima) {
336                                         params["type"]=yafray::parameter_t("image");
337                                         // image->name is full path
338                                         string texpath = ima->name;
339 #ifdef WIN32
340                                         // add drive char if not there
341                                         addDrive(texpath);
342 #endif
343                                         params["filename"]=yafray::parameter_t(texpath);
344                                 }
345                                 break;
346                         }
347                         default:
348                                 cout << "Unsupported texture type\n";
349                 }
350                 yafrayGate->addShader(params,lparams);
351                 // colorbands
352                 if (tex->flag & TEX_COLORBAND) 
353                 {
354                         ColorBand* cb = tex->coba;
355                         if (cb) 
356                         {
357                                 params.clear();
358                                 params["type"]=yafray::parameter_t("colorband");
359                                 params["name"]=yafray::parameter_t(blendtex->first + "_coba");
360                                 params["input"]=yafray::parameter_t(blendtex->first);
361                                 for (int i=0;i<cb->tot;i++) 
362                                 {
363                                         yafray::paramMap_t mparams;
364                                         mparams["value"]=yafray::parameter_t(cb->data[i].pos);
365                                         mparams["color"]=yafray::parameter_t(yafray::colorA_t(cb->data[i].r,
366                                                                                                                                                                                                                                                                 cb->data[i].g,
367                                                                                                                                                                                                                                                                 cb->data[i].b,
368                                                                                                                                                                                                                                                                 cb->data[i].a));
369                                         lparams.push_back(mparams);
370                                 }
371                                 yafrayGate->addShader(params,lparams);
372                         }
373                 }
374
375         }
376 }
377
378
379 // write all materials & modulators
380 void yafrayPluginRender_t::writeMaterialsAndModulators()
381 {
382           
383         for (map<string, Material*>::const_iterator blendmat=used_materials.begin();
384                 blendmat!=used_materials.end();++blendmat) 
385         {
386                 Material* matr = blendmat->second;
387                 // blendermappers
388                 for (int m=0;m<8;m++) 
389                 {
390                         if (matr->septex & (1<<m)) continue;// all active channels
391                         // ignore null mtex
392                         MTex* mtex = matr->mtex[m];
393                         if (mtex==NULL) continue;
394                         // ignore null tex
395                         Tex* tex = mtex->tex;
396                         if (tex==NULL) continue;
397
398                         // now included the full name
399                         map<string, pair<Material*, MTex*> >::const_iterator mtexL = used_textures.find(string(tex->id.name));
400                         if (mtexL!=used_textures.end()) 
401                         {
402                                 yafray::paramMap_t params;
403                                 list<yafray::paramMap_t> lparams;
404                                 //params.clear();
405                                 //lparams.clear();
406                                 char temp[16];
407                                 sprintf(temp,"%d",m);
408                                 params["type"]=yafray::parameter_t("blendermapper");
409                                 params["name"]=yafray::parameter_t(blendmat->first + "_map"+temp);
410                                 if ((mtex->texco & TEXCO_OBJECT) || (mtex->texco & TEXCO_REFL))
411                                 {
412                                         // For object & reflection mapping, add the object matrix to the modulator,
413                                         // as in LF script, use camera matrix if no object specified.
414                                         // In this case this means the inverse of that matrix
415                                         float texmat[4][4], itexmat[4][4];
416                                         if ((mtex->texco & TEXCO_OBJECT) && (mtex->object))
417                                                 MTC_Mat4CpyMat4(texmat, mtex->object->obmat);
418                                         else    // also for refl. map
419                                                 MTC_Mat4CpyMat4(texmat, maincam_obj->obmat);
420                                         MTC_Mat4Invert(itexmat, texmat);
421 #define flp yafray::parameter_t
422                                         params["m00"]=flp(itexmat[0][0]);params["m01"]=flp(itexmat[1][0]);
423                                         params["m02"]=flp(itexmat[2][0]);params["m03"]=flp(itexmat[3][0]);
424                                         params["m10"]=flp(itexmat[0][1]);params["m11"]=flp(itexmat[1][1]);
425                                         params["m12"]=flp(itexmat[2][1]);params["m13"]=flp(itexmat[3][1]);
426                                         params["m20"]=flp(itexmat[0][2]);params["m21"]=flp(itexmat[1][2]);
427                                         params["m22"]=flp(itexmat[2][2]);params["m23"]=flp(itexmat[3][2]);
428                                         params["m30"]=flp(itexmat[0][3]);params["m31"]=flp(itexmat[1][3]);
429                                         params["m32"]=flp(itexmat[2][3]);params["m33"]=flp(itexmat[3][3]);
430 #undef flp
431                                 }
432                                 if ((tex->flag & TEX_COLORBAND) & (tex->coba!=NULL))
433                                         params["input"]=yafray::parameter_t(mtexL->first + "_coba");
434                                 else
435                                         params["input"]=yafray::parameter_t(mtexL->first);
436
437                                 // size, if the texturetype is clouds/marble/wood, also take noisesize into account
438                                 float sc = 1;
439                                 if ((tex->type==TEX_CLOUDS) || (tex->type==TEX_MARBLE) || (tex->type==TEX_WOOD)) 
440                                 {
441                                         sc = tex->noisesize;
442                                         if (sc!=0) sc = 1.f/sc;
443                                 }
444                                 // texture size
445                                 params["sizex"]=yafray::parameter_t(mtex->size[0]*sc);
446                                 params["sizey"]=yafray::parameter_t(mtex->size[1]*sc);
447                                 params["sizez"]=yafray::parameter_t(mtex->size[2]*sc);
448
449                                 // texture offset
450                                 params["ofsx"]=yafray::parameter_t(mtex->ofs[0]*sc);
451                                 params["ofsy"]=yafray::parameter_t(mtex->ofs[1]*sc);
452                                 params["ofsz"]=yafray::parameter_t(mtex->ofs[2]*sc);
453
454                                 // texture coordinates, have to disable 'sticky' in Blender
455                                 if ((mtex->texco & TEXCO_UV) || (matr->mode & MA_FACETEXTURE))
456                                         params["texco"]=yafray::parameter_t("uv");
457                                 else if ((mtex->texco & TEXCO_GLOB) || (mtex->texco & TEXCO_OBJECT))
458                                         // object mode is also set as global, but the object matrix 
459                                         // was specified above with <modulator..>
460                                         params["texco"]=yafray::parameter_t("global");
461                                 else if (mtex->texco & TEXCO_ORCO)
462                                         params["texco"]=yafray::parameter_t("orco");
463                                 else if (mtex->texco & TEXCO_WINDOW)
464                                         params["texco"]=yafray::parameter_t("window");
465                                 else if (mtex->texco & TEXCO_NORM)
466                                         params["texco"]=yafray::parameter_t("normal");
467                                 else if (mtex->texco & TEXCO_REFL)
468                                         params["texco"]=yafray::parameter_t("reflect");
469
470                                 // texture mapping parameters only relevant to image type
471                                 if (tex->type==TEX_IMAGE) 
472                                 {
473                                         if (mtex->mapping==MTEX_FLAT)
474                                                 params["mapping"]=yafray::parameter_t("flat");
475                                         else if (mtex->mapping==MTEX_CUBE)
476                                                 params["mapping"]=yafray::parameter_t("cube");
477                                         else if (mtex->mapping==MTEX_TUBE)
478                                                 params["mapping"]=yafray::parameter_t("tube");
479                                         else if (mtex->mapping==MTEX_SPHERE)
480                                                 params["mapping"]=yafray::parameter_t("sphere");
481
482                                         // texture projection axes
483                                         string proj = "nxyz";           // 'n' for 'none'
484                                         params["proj_x"]=yafray::parameter_t(string(1,proj[mtex->projx]));
485                                         params["proj_y"]=yafray::parameter_t(string(1,proj[mtex->projy]));
486                                         params["proj_z"]=yafray::parameter_t(string(1,proj[mtex->projz]));
487
488                                         // repeat
489                                         params["xrepeat"]=yafray::parameter_t(tex->xrepeat);
490                                         params["yrepeat"]=yafray::parameter_t(tex->yrepeat);
491
492                                         // clipping
493                                         if (tex->extend==TEX_EXTEND)
494                                                 params["clipping"]=yafray::parameter_t("extend");
495                                         else if (tex->extend==TEX_CLIP)
496                                                 params["clipping"]=yafray::parameter_t("clip");
497                                         else if (tex->extend==TEX_CLIPCUBE)
498                                                 params["clipping"]=yafray::parameter_t("clipcube");
499                                         else
500                                                 params["clipping"]=yafray::parameter_t("repeat");
501
502                                         // crop min/max
503                                         params["cropmin_x"]=yafray::parameter_t(tex->cropxmin);
504                                         params["cropmin_y"]=yafray::parameter_t(tex->cropymin);
505                                         params["cropmax_x"]=yafray::parameter_t(tex->cropxmax);
506                                         params["cropmax_y"]=yafray::parameter_t(tex->cropymax);
507
508                                         // rot90 flag
509                                         if (tex->imaflag & TEX_IMAROT) 
510                                                 params["rot90"]=yafray::parameter_t("on");
511                                         else
512                                                 params["rot90"]=yafray::parameter_t("off");
513                                 }
514                                 yafrayGate->addShader(params,lparams);
515                         }
516                 }
517                 yafray::paramMap_t params;
518                 // blendershaders + modulators
519                 params["type"]=yafray::parameter_t("blendershader");
520                 params["name"]=yafray::parameter_t(blendmat->first);
521                 float diff=matr->alpha;
522                 params["color"]=yafray::parameter_t(yafray::color_t(matr->r*diff,matr->g*diff,matr->b*diff));
523                 params["specular_color"]=yafray::parameter_t(yafray::color_t(matr->specr,
524                                                                                                                                                                                                                                                                  matr->specg,
525                                                                                                                                                                                                                                                                  matr->specb));
526                 params["mirror_color"]=yafray::parameter_t(yafray::color_t(matr->mirr, matr->mirg,matr->mirb));
527                 params["diffuse_reflect"]=yafray::parameter_t(matr->ref);
528                 params["specular_amount"]=yafray::parameter_t(matr->spec);
529                 params["hard"]=yafray::parameter_t(matr->har);
530                 params["alpha"]=yafray::parameter_t(matr->alpha);
531                 params["emit"]=yafray::parameter_t(matr->emit * R.r.GIpower);
532
533                 // reflection/refraction
534                 if ( (matr->mode & MA_RAYMIRROR) || (matr->mode & MA_RAYTRANSP) )
535                         params["IOR"]=yafray::parameter_t(matr->ang);
536                 if (matr->mode & MA_RAYMIRROR) 
537                 {
538                         float rf = matr->ray_mirror;
539                         // blender uses mir color for reflection as well
540                         params["reflected"]=yafray::parameter_t(yafray::color_t(matr->mirr, matr->mirg,matr->mirb));
541                         params["min_refle"]=yafray::parameter_t(rf);
542                         if (matr->ray_depth>maxraydepth) maxraydepth = matr->ray_depth;
543                 }
544                 if (matr->mode & MA_RAYTRANSP) 
545                 {
546                         float tr=1.0-matr->alpha;
547                         params["transmitted"]=yafray::parameter_t(yafray::color_t(matr->r*tr,matr->g*tr,matr->b*tr));
548                         // tir on by default
549                         params["tir"]=yafray::parameter_t("on");
550                         if (matr->ray_depth_tra>maxraydepth) maxraydepth = matr->ray_depth_tra;
551                 }
552
553                 string Mmode = "";
554                 if (matr->mode & MA_TRACEBLE) Mmode += "traceable";
555                 if (matr->mode & MA_SHADOW) Mmode += " shadow";
556                 if (matr->mode & MA_SHLESS) Mmode += " shadeless";
557                 if (matr->mode & MA_VERTEXCOL) Mmode += " vcol_light";
558                 if (matr->mode & MA_VERTEXCOLP) Mmode += " vcol_paint";
559                 if (matr->mode & MA_ZTRA) Mmode += " ztransp";
560                 if (matr->mode & MA_ONLYSHADOW) Mmode += " onlyshadow";
561                 if (Mmode!="") params["matmodes"]=yafray::parameter_t(Mmode);
562
563                 // modulators
564                 list<yafray::paramMap_t> lparams;
565                 for (int m2=0;m2<8;m2++) 
566                 {
567                         if (matr->septex & (1<<m2)) continue;// all active channels
568                         // ignore null mtex
569                         MTex* mtex = matr->mtex[m2];
570                         if (mtex==NULL) continue;
571                         // ignore null tex
572                         Tex* tex = mtex->tex;
573                         if (tex==NULL) continue;
574
575                         map<string, pair<Material*, MTex*> >::const_iterator mtexL = used_textures.find(string(tex->id.name));
576                         if (mtexL!=used_textures.end()) 
577                         {
578                                 yafray::paramMap_t mparams;
579                                 char temp[16];
580                                 sprintf(temp,"%d",m2);
581                                 mparams["input"]=yafray::parameter_t(blendmat->first + "_map" + temp);
582                                 // blendtype
583                                 string ts = "mix";
584                                 if (mtex->blendtype==MTEX_MUL) ts="mul";
585                                 else if (mtex->blendtype==MTEX_ADD) ts="add";
586                                 else if (mtex->blendtype==MTEX_SUB) ts="sub";
587                                 mparams["mode"]=yafray::parameter_t(ts);
588
589                                 // texture color (for use with MUL and/or no_rgb etc..)
590                                 mparams["texcol"]=yafray::parameter_t(yafray::color_t(mtex->r,mtex->g,mtex->b));
591                                 // texture contrast, brightness & color adjustment
592                                 mparams["filtercolor"]=yafray::parameter_t(yafray::color_t(tex->rfac,tex->gfac,tex->bfac));
593                                 mparams["contrast"]=yafray::parameter_t(tex->contrast);
594                                 mparams["brightness"]=yafray::parameter_t(tex->bright);
595                                 // all texture flags now are switches, having the value 1 or -1 (negative option)
596                                 // the negative option only used for the intensity modulation options.
597
598                                 // material (diffuse) color, amount controlled by colfac (see below)
599                                 if (mtex->mapto & MAP_COL)
600                                         mparams["color"]=yafray::parameter_t(1.0);
601                                 // bumpmapping
602                                 if ((mtex->mapto & MAP_NORM) || (mtex->maptoneg & MAP_NORM)) 
603                                 {
604                                         // for yafray, bump factor is negated (unless negative option of 'Nor', 
605                                         // is not affected by 'Neg')
606                                         // scaled down quite a bit for yafray when image type, otherwise used directly
607                                         float nf = -mtex->norfac;
608                                         if (mtex->maptoneg & MAP_NORM) nf *= -1.f;
609                                         if (tex->type==TEX_IMAGE) nf *= 2e-3f;
610                                         mparams["normal"]=yafray::parameter_t(nf);
611                                 }
612
613                                 // all blender texture modulation as switches, either 1 or -1 (negative state of button)
614                                 // Csp, specular color modulation
615                                 if (mtex->mapto & MAP_COLSPEC)
616                                         mparams["colspec"]=yafray::parameter_t(1.0);
617                                 // CMir, mirror color  modulation
618                                 if (mtex->mapto & MAP_COLMIR)
619                                         mparams["colmir"]=yafray::parameter_t(1.0);
620
621                                 // Ref, diffuse reflection amount  modulation
622                                 if ((mtex->mapto & MAP_REF) || (mtex->maptoneg & MAP_REF)) 
623                                 {
624                                         int t = 1;
625                                         if (mtex->maptoneg & MAP_REF) t = -1;
626                                         mparams["difref"]=yafray::parameter_t(t);
627                                 }
628
629                                 // Spec, specular amount mod
630                                 if ((mtex->mapto & MAP_SPEC) || (mtex->maptoneg & MAP_SPEC)) 
631                                 {
632                                         int t = 1;
633                                         if (mtex->maptoneg & MAP_SPEC) t = -1;
634                                         mparams["specular"]=yafray::parameter_t(t);
635                                 }
636
637                                 // hardness modulation
638                                 if ((mtex->mapto & MAP_HAR) || (mtex->maptoneg & MAP_HAR)) 
639                                 {
640                                         int t = 1;
641                                         if (mtex->maptoneg & MAP_HAR) t = -1;
642                                         mparams["hard"]=yafray::parameter_t(t);
643                                 }
644  
645                                 // alpha modulation
646                                 if ((mtex->mapto & MAP_ALPHA) || (mtex->maptoneg & MAP_ALPHA)) 
647                                 {
648                                         int t = 1;
649                                         if (mtex->maptoneg & MAP_ALPHA) t = -1;
650                                         mparams["alpha"]=yafray::parameter_t(t);
651                                 }
652
653                                 // emit modulation
654                                 if ((mtex->mapto & MAP_EMIT) || (mtex->maptoneg & MAP_EMIT)) {
655                                         int t = 1;
656                                         if (mtex->maptoneg & MAP_EMIT) t = -1;
657                                         mparams["emit"]=yafray::parameter_t(t);
658                                 }
659
660                                 // texture flag, combination of strings
661                                 if (mtex->texflag & (MTEX_RGBTOINT | MTEX_STENCIL | MTEX_NEGATIVE)) {
662                                         ts = "";
663                                         if (mtex->texflag & MTEX_RGBTOINT) ts += "no_rgb ";
664                                         if (mtex->texflag & MTEX_STENCIL) ts += "stencil ";
665                                         if (mtex->texflag & MTEX_NEGATIVE) ts += "negative";
666                                         mparams["texflag"]=yafray::parameter_t(ts);
667                                 }
668
669                                 // colfac, controls amount of color modulation
670                                 mparams["colfac"]=yafray::parameter_t(mtex->colfac);
671                                 // def_var
672                                 mparams["def_var"]=yafray::parameter_t(mtex->def_var);
673                                 //varfac
674                                 mparams["varfac"]=yafray::parameter_t(mtex->varfac);
675
676                                 if ((tex->imaflag & (TEX_CALCALPHA | TEX_USEALPHA)) || (tex->flag & TEX_NEGALPHA)) 
677                                 {
678                                         ts = "";
679                                         if (tex->imaflag & TEX_CALCALPHA) ts += "calc_alpha ";
680                                         if (tex->imaflag & TEX_USEALPHA) ts += "use_alpha ";
681                                         if (tex->flag & TEX_NEGALPHA) ts += "neg_alpha";
682                                         mparams["alpha_flag"]=yafray::parameter_t(ts);
683                                 }
684                                 lparams.push_back(mparams);
685                         }
686                 }
687                 yafrayGate->addShader(params,lparams);
688         }
689 }
690
691 void yafrayPluginRender_t::genUVcoords(vector<yafray::GFLOAT> *uvcoords,VlakRen *vlr,TFace* uvc)
692 {
693         if (uvc) 
694         {
695         // use correct uv coords for this triangle
696                 if (vlr->flag & R_FACE_SPLIT) 
697                 {
698                         uvcoords->push_back(uvc->uv[0][0]);uvcoords->push_back(1-uvc->uv[0][1]);
699                         uvcoords->push_back(uvc->uv[2][0]);uvcoords->push_back(1-uvc->uv[2][1]);
700                         uvcoords->push_back(uvc->uv[3][0]);uvcoords->push_back(1-uvc->uv[3][1]);
701                 }
702                 else 
703                 {
704                         uvcoords->push_back(uvc->uv[0][0]);uvcoords->push_back(1-uvc->uv[0][1]);
705                         uvcoords->push_back(uvc->uv[1][0]);uvcoords->push_back(1-uvc->uv[1][1]);
706                         uvcoords->push_back(uvc->uv[2][0]);uvcoords->push_back(1-uvc->uv[2][1]);
707                 }
708         }
709         else
710         {
711                 uvcoords->push_back(0);uvcoords->push_back(0);
712                 uvcoords->push_back(0);uvcoords->push_back(0);
713                 uvcoords->push_back(0);uvcoords->push_back(0);
714         }
715 }
716
717 void yafrayPluginRender_t::genCompleUVcoords(vector<yafray::GFLOAT> *uvcoords,/*VlakRen *vlr,*/TFace* uvc)
718 {
719         if (uvc) 
720         {
721         // use correct uv coords for this triangle
722                 uvcoords->push_back(uvc->uv[2][0]);uvcoords->push_back(1-uvc->uv[2][1]);
723                 uvcoords->push_back(uvc->uv[3][0]);uvcoords->push_back(1-uvc->uv[3][1]);
724                 uvcoords->push_back(uvc->uv[0][0]);uvcoords->push_back(1-uvc->uv[0][1]);
725         }
726         else
727         {
728                 uvcoords->push_back(0);uvcoords->push_back(0);
729                 uvcoords->push_back(0);uvcoords->push_back(0);
730                 uvcoords->push_back(0);uvcoords->push_back(0);
731         }
732 }
733
734 void yafrayPluginRender_t::genVcol(vector<yafray::CFLOAT> *vcol,VlakRen *vlr,
735                                                                                                                                                 int p1,int p2,int p3,bool EXPORT_VCOL)
736 {
737         if ((EXPORT_VCOL) && (vlr->vcol)) 
738         {
739                 // vertex colors
740                 float vr, vg, vb;
741                 vr = ((vlr->vcol[p1] >> 24) & 255)/255.0;
742                 vg = ((vlr->vcol[p1] >> 16) & 255)/255.0;
743                 vb = ((vlr->vcol[p1] >> 8) & 255)/255.0;
744                 vcol->push_back(vr);vcol->push_back(vg);vcol->push_back(vb);
745                 vr = ((vlr->vcol[p2] >> 24) & 255)/255.0;
746                 vg = ((vlr->vcol[p2] >> 16) & 255)/255.0;
747                 vb = ((vlr->vcol[p2] >> 8) & 255)/255.0;
748                 vcol->push_back(vr);vcol->push_back(vg);vcol->push_back(vb);
749                 vr = ((vlr->vcol[p3] >> 24) & 255)/255.0;
750                 vg = ((vlr->vcol[p3] >> 16) & 255)/255.0;
751                 vb = ((vlr->vcol[p3] >> 8) & 255)/255.0;
752                 vcol->push_back(vr);vcol->push_back(vg);vcol->push_back(vb);
753         }
754         else
755         {
756                 vcol->push_back(0);vcol->push_back(0);vcol->push_back(0);
757                 vcol->push_back(0);vcol->push_back(0);vcol->push_back(0);
758                 vcol->push_back(0);vcol->push_back(0);vcol->push_back(0);
759         }
760 }
761
762 void yafrayPluginRender_t::genFace(vector<int> &faces,vector<string> &shaders,vector<int> &faceshader,
763                                                                                                                 vector<yafray::GFLOAT> *uvcoords,vector<yafray::CFLOAT> *vcol,
764                                                                                                                 map<VertRen*, int> &vert_idx,VlakRen *vlr,
765                                                                                                                 bool has_orco,bool has_uv,bool has_vcol)
766 {
767         Material* fmat = vlr->mat;
768         bool EXPORT_VCOL = ((fmat->mode & (MA_VERTEXCOL|MA_VERTEXCOLP))!=0);
769         string fmatname = fmat->id.name;
770         if (fmatname=="") fmatname = "blender_default";
771         bool newmat=true;
772         for(unsigned int i=0;i<shaders.size();++i)
773                 if(shaders[i]==fmatname)
774                 {
775                         newmat=false;
776                         faceshader.push_back(i);
777                         break;
778                 }
779         if(newmat)
780         {
781                 shaders.push_back(fmatname);
782                 faceshader.push_back(shaders.size()-1);
783         }
784         //else fmatname+=2;     //skip MA id
785         TFace* uvc = vlr->tface;        // possible uvcoords (v upside down)
786         int idx1, idx2, idx3;
787
788         idx1 = vert_idx.find(vlr->v1)->second;
789         idx2 = vert_idx.find(vlr->v2)->second;
790         idx3 = vert_idx.find(vlr->v3)->second;
791
792         // make sure the indices point to the vertices when orco coords exported
793         if (has_orco) { idx1*=2;  idx2*=2;  idx3*=2; }
794
795         faces.push_back(idx1);faces.push_back(idx2);faces.push_back(idx3);
796
797         if(has_uv) genUVcoords(uvcoords,vlr,uvc);
798
799         // since Blender seems to need vcols when uvs are used, for yafray only export when the material actually uses vcols
800         if(has_vcol) genVcol(vcol,vlr,0,1,2,EXPORT_VCOL);
801 }
802
803 void yafrayPluginRender_t::genCompleFace(vector<int> &faces,/*vector<string> &shaders,*/vector<int> &faceshader,
804                                                                                                                 vector<yafray::GFLOAT> *uvcoords,vector<yafray::CFLOAT> *vcol,
805                                                                                                                 map<VertRen*, int> &vert_idx,VlakRen *vlr,
806                                                                                                                 bool has_orco,bool has_uv,bool has_vcol)
807 {
808         Material* fmat = vlr->mat;
809         bool EXPORT_VCOL = ((fmat->mode & (MA_VERTEXCOL|MA_VERTEXCOLP))!=0);
810
811         faceshader.push_back(faceshader.back());
812         TFace* uvc = vlr->tface;        // possible uvcoords (v upside down)
813         int idx1, idx2, idx3;
814         idx1 = vert_idx.find(vlr->v3)->second;
815         idx2 = vert_idx.find(vlr->v4)->second;
816         idx3 = vert_idx.find(vlr->v1)->second;
817
818         // make sure the indices point to the vertices when orco coords exported
819         if (has_orco) { idx1*=2;  idx2*=2;  idx3*=2; }
820
821         faces.push_back(idx1);faces.push_back(idx2);faces.push_back(idx3);
822
823         if(has_uv) genCompleUVcoords(uvcoords,/*vlr,*/uvc);
824         if(has_vcol) genVcol(vcol,vlr,2,3,0,EXPORT_VCOL);
825 }
826
827 void yafrayPluginRender_t::genVertices(vector<yafray::point3d_t> *verts,int &vidx,
828                                                                                                                                                          map<VertRen*, int> &vert_idx,VlakRen* vlr,bool has_orco)
829 {
830         VertRen* ver;
831         if (vert_idx.find(vlr->v1)==vert_idx.end()) 
832         {
833                 vert_idx[vlr->v1] = vidx++;
834                 ver = vlr->v1;
835                 verts->push_back(yafray::point3d_t(ver->co[0],ver->co[1],ver->co[2]));
836                 if (has_orco) 
837                         verts->push_back(yafray::point3d_t(ver->orco[0],ver->orco[1],ver->orco[2]));
838         }
839         if (vert_idx.find(vlr->v2)==vert_idx.end()) 
840         {
841                 vert_idx[vlr->v2] = vidx++;
842                 ver = vlr->v2;
843                 verts->push_back(yafray::point3d_t(ver->co[0],ver->co[1],ver->co[2]));
844                 if (has_orco)
845                         verts->push_back(yafray::point3d_t(ver->orco[0],ver->orco[1],ver->orco[2]));
846         }
847         if (vert_idx.find(vlr->v3)==vert_idx.end()) 
848         {
849                 vert_idx[vlr->v3] = vidx++;
850                 ver = vlr->v3;
851                 verts->push_back(yafray::point3d_t(ver->co[0],ver->co[1],ver->co[2]));
852                 if (has_orco)
853                         verts->push_back(yafray::point3d_t(ver->orco[0],ver->orco[1],ver->orco[2]));
854         }
855         if ((vlr->v4) && (vert_idx.find(vlr->v4)==vert_idx.end())) 
856         {
857                 vert_idx[vlr->v4] = vidx++;
858                 ver = vlr->v4;
859                 verts->push_back(yafray::point3d_t(ver->co[0],ver->co[1],ver->co[2]));
860                 if (has_orco)
861                         verts->push_back(yafray::point3d_t(ver->orco[0],ver->orco[1],ver->orco[2]));
862         }
863 }
864
865 void yafrayPluginRender_t::writeObject(Object* obj, const vector<VlakRen*> &VLR_list, const float obmat[4][4])
866 {
867         float mtr[4*4];
868         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];
869         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];
870         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];
871         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];
872         yafrayGate->transformPush(mtr);
873         string name=string(obj->id.name+2);
874         bool castShadows=VLR_list[0]->mat->mode & MA_TRACEBLE;
875         float caus_IOR=1.0;
876         yafray::color_t caus_tcolor(0.0,0.0,0.0),caus_rcolor(0.0,0.0,0.0);
877         bool caus=false;
878         if (VLR_list[0]->mat->mode & MA_RAYTRANSP) 
879         {
880                 caus_IOR=VLR_list[0]->mat->ang;
881                 float tr=1.0-VLR_list[0]->mat->alpha;
882                 caus_tcolor.set(VLR_list[0]->mat->r * tr,VLR_list[0]->mat->g * tr,VLR_list[0]->mat->b * tr);
883                 caus=true;
884         }
885         bool has_orco=(VLR_list[0]->v1->orco!=NULL);
886         float sm_angle=0.1;
887         if (obj->type==OB_MESH) 
888         {
889                 Mesh* mesh = (Mesh*)obj->data;
890                 if (mesh->flag & ME_AUTOSMOOTH) 
891                         sm_angle=mesh->smoothresh;
892                 else
893                         if (VLR_list[0]->flag & ME_SMOOTH)      sm_angle=90;
894         }
895         // Guess if we need to set vertex colors Could be faster? sure
896         bool has_vcol=false;
897         for(int i=0;i<obj->totcol;++i)
898         {
899                 Material *fmat=obj->mat[i];
900                 if(fmat==NULL) continue;
901                 if((fmat->mode & (MA_VERTEXCOL|MA_VERTEXCOLP))!=0) {has_vcol=true;break;};
902         }
903         vector<yafray::point3d_t> *verts=new vector<yafray::point3d_t>;
904         vector<yafray::CFLOAT> *vcol=NULL;
905         if(has_vcol) vcol=new vector<yafray::CFLOAT>;
906         // now all vertices
907         map<VertRen*, int> vert_idx;    // for removing duplicate verts and creating an index list
908         int vidx = 0;   // vertex index counter
909         bool has_uv=false;
910         for (vector<VlakRen*>::const_iterator fci=VLR_list.begin();
911                                 fci!=VLR_list.end();++fci)
912         {
913                 VlakRen* vlr = *fci;
914                 genVertices(verts,vidx,vert_idx,vlr,has_orco);
915                 if(vlr->tface) has_uv=true;
916         }
917         // all faces using the index list created above
918         vector<int> faces;
919         vector<string> shaders;
920         vector<int> faceshader;
921         vector<yafray::GFLOAT> *uvcoords=NULL;
922         if(has_uv)
923                 uvcoords=new vector<yafray::GFLOAT>;
924         for (vector<VlakRen*>::const_iterator fci2=VLR_list.begin();
925                                 fci2!=VLR_list.end();++fci2)
926         {
927                 VlakRen* vlr = *fci2;
928                 genFace(faces,shaders,faceshader,uvcoords,vcol,vert_idx,vlr,has_orco,has_uv,has_vcol);
929                 if (vlr->v4) 
930                         genCompleFace(faces,/*shaders,*/faceshader,uvcoords,vcol,vert_idx,vlr,has_orco,has_uv,has_vcol);
931         }
932
933         yafrayGate->addObject_trimesh(name,verts,faces,uvcoords,vcol,
934                         shaders,faceshader,sm_angle,castShadows,true,true,caus,has_orco,
935                         caus_rcolor,caus_tcolor,caus_IOR);
936         yafrayGate->transformPop();
937 }
938
939
940 // write all objects
941 void yafrayPluginRender_t::writeAllObjects()
942 {
943
944         // first all objects except dupliverts (and main instance object for dups)
945         for (map<Object*, vector<VlakRen*> >::const_iterator obi=all_objects.begin();
946                         obi!=all_objects.end(); ++obi)
947         {
948           // skip main duplivert object if in dupliMtx_list, written later
949                 Object* obj = obi->first;
950                 if (dupliMtx_list.find(string(obj->id.name))!=dupliMtx_list.end()) continue;
951                 writeObject(obj, obi->second, obi->first->obmat);
952         }
953
954         // Now all duplivert objects (if any) as instances of main object
955         // The original object has been included in the VlakRen renderlist above (see convertBlenderScene.c)
956         // but is written here which all other duplis are instances of.
957         float obmat[4][4], cmat[4][4], imat[4][4], nmat[4][4];
958         for (map<string, vector<float> >::const_iterator dupMtx=dupliMtx_list.begin();
959                 dupMtx!=dupliMtx_list.end();++dupMtx) {
960
961                 // original inverse matrix, not actual matrix of object, but first duplivert.
962                 for (int i=0;i<4;i++)
963                         for (int j=0;j<4;j++)
964                                 obmat[i][j] = dupMtx->second[(i<<2)+j];
965                 MTC_Mat4Invert(imat, obmat);
966
967                 // first object written as normal (but with transform of first duplivert)
968                 Object* obj = dup_srcob[dupMtx->first];
969                 writeObject(obj, all_objects[obj], obmat);
970
971                 // all others instances of first
972                 for (unsigned int curmtx=16;curmtx<dupMtx->second.size();curmtx+=16) 
973                 {       // number of 4x4 matrices
974                         // new mtx
975                         for (int i=0;i<4;i++)
976                                 for (int j=0;j<4;j++)
977                                         nmat[i][j] = dupMtx->second[curmtx+(i<<2)+j];
978
979                         MTC_Mat4MulMat4(cmat, imat, nmat);      // transform with respect to original = inverse_original * new
980
981                         float mtr[4*4];
982                         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];
983                         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];
984                         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];
985                         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];
986                         yafrayGate->transformPush(mtr);
987
988                         // new name from original
989                         string name=(obj->id.name+2);
990                         char temp[16];
991                         sprintf(temp,"_dup%d",(curmtx>>4));
992                         name+=temp;
993                         yafrayGate->addObject_reference(name,obj->id.name+2);
994                         yafrayGate->transformPop();
995                 }
996
997         }
998
999 }
1000
1001 void yafrayPluginRender_t::writeAreaLamp(LampRen* lamp, int num)
1002 {
1003         yafray::paramMap_t params;
1004         
1005         if (lamp->area_shape!=LA_AREA_SQUARE) return;
1006         float *a=lamp->area[0], *b=lamp->area[1], *c=lamp->area[2], *d=lamp->area[3];
1007         float power=lamp->energy;
1008         
1009         string md = "off";
1010         if (R.r.GIphotons) {md = "on";power*=R.r.GIpower;}
1011         params["type"]=yafray::parameter_t("arealight");
1012         char temp[16];
1013         sprintf(temp,"LAMP%d",num+1);
1014         params["name"]=yafray::parameter_t(temp);
1015         params["dummy"]=yafray::parameter_t(md);
1016         params["power"]=yafray::parameter_t(power);
1017         if (!R.r.GIphotons) 
1018         {
1019                 int psm=0, sm = lamp->ray_totsamp;
1020                 if (sm>=64) psm = sm/4;
1021                 params["samples"]=yafray::parameter_t(sm);
1022                 params["psamples"]=yafray::parameter_t(psm);
1023         }
1024         params["a"]=yafray::parameter_t(yafray::point3d_t(a[0],a[1],a[2]));
1025         params["b"]=yafray::parameter_t(yafray::point3d_t(b[0],b[1],b[2]));
1026         params["c"]=yafray::parameter_t(yafray::point3d_t(c[0],c[1],c[2]));
1027         params["d"]=yafray::parameter_t(yafray::point3d_t(d[0],d[1],d[2]));
1028         params["color"]=yafray::parameter_t(yafray::color_t(lamp->r,lamp->g,lamp->b));
1029         yafrayGate->addLight(params);
1030 }
1031
1032 void yafrayPluginRender_t::writeLamps()
1033 {
1034         // all lamps
1035         for (int i=0;i<R.totlamp;i++)
1036         {
1037                 yafray::paramMap_t params;
1038                 string type="";
1039                 LampRen* lamp = R.la[i];
1040                 if (lamp->type==LA_AREA) { writeAreaLamp(lamp, i);  continue; }
1041                 // TODO: add decay setting in yafray
1042                 if (lamp->type==LA_LOCAL)
1043                         params["type"]=yafray::parameter_t("pointlight");
1044                 else if (lamp->type==LA_SPOT)
1045                         params["type"]=yafray::parameter_t("spotlight");
1046                 else if ((lamp->type==LA_SUN) || (lamp->type==LA_HEMI)) // for now, hemi same as sun
1047                         params["type"]=yafray::parameter_t("sunlight");
1048                 else 
1049                 {
1050                         // possibly unknown type, ignore
1051                         cout << "Unknown Blender lamp type: " << lamp->type << endl;
1052                         continue;
1053                 }
1054                 //no name available here, create one
1055                 char temp[16];
1056                 sprintf(temp,"LAMP%d",i+1);
1057                 params["name"]=yafray::parameter_t(temp);
1058                 // color already premultiplied by energy, so only need distance here
1059                 float pwr;
1060                 if (lamp->mode & LA_SPHERE) 
1061                 {
1062                         // best approx. as used in LFexport script (LF d.f.m. 4pi?)
1063                         pwr = lamp->dist*(lamp->dist+1)*(0.25/M_PI);
1064                         //decay = 2;
1065                 }
1066                 else 
1067                 {
1068                         if ((lamp->type==LA_LOCAL) || (lamp->type==LA_SPOT)) 
1069                                 pwr = lamp->dist;
1070                         else pwr = 1;   // sun/hemi distance irrelevent.
1071                 }
1072                 params["power"]=yafray::parameter_t(pwr);
1073                 string lpmode="off";
1074                 // shadows only when Blender has shadow button enabled, only spots use LA_SHAD flag
1075                 if (R.r.mode & R_SHADOW)
1076                         params["cast_shadows"]=yafray::parameter_t("on");
1077                 else
1078                         params["cast_shadows"]=yafray::parameter_t("off");
1079                 // spot specific stuff
1080                 if (lamp->type==LA_SPOT) 
1081                 {
1082                         // conversion already changed spotsize to cosine of half angle
1083                         float ld = 1-lamp->spotsi;      //convert back to blender slider setting
1084                         if (ld!=0) ld = 1.f/ld;
1085                         params["size"]=yafray::parameter_t(acos(lamp->spotsi)*180.0/M_PI);
1086                         params["blend"]=yafray::parameter_t(lamp->spotbl*ld);
1087                         params["beam_falloff"]=yafray::parameter_t(2.0);
1088                 }
1089                 params["from"]=yafray::parameter_t(yafray::point3d_t(lamp->co[0],lamp->co[1],lamp->co[2]));
1090                 // position
1091                 // 'to' for spot, already calculated by Blender
1092                 if (lamp->type==LA_SPOT)
1093                         params["to"]=yafray::parameter_t(yafray::point3d_t(lamp->co[0]+lamp->vec[0],
1094                                                                                                                                                                                                                                          lamp->co[1]+lamp->vec[1],
1095                                                                                                                                                                                                                                          lamp->co[2]+lamp->vec[2]));
1096                 // color
1097                 // rgb in LampRen is premultiplied by energy, power is compensated for that above
1098                 params["color"]=yafray::parameter_t(yafray::color_t(lamp->r,lamp->g,lamp->b));
1099                 yafrayGate->addLight(params);
1100         }
1101 }
1102
1103
1104 // write main camera
1105 void yafrayPluginRender_t::writeCamera()
1106 {
1107         yafray::paramMap_t params;
1108         params["name"]=yafray::parameter_t("MAINCAM");
1109         params["resx"]=yafray::parameter_t(R.r.xsch);
1110         params["resy"]=yafray::parameter_t(R.r.ysch);
1111         float aspect = 1;
1112         if (R.r.xsch < R.r.ysch) aspect = float(R.r.xsch)/float(R.r.ysch);
1113
1114         params["focal"]=yafray::parameter_t(mainCamLens/(aspect*32.0));
1115         float camtx[4][4];
1116         MTC_Mat4CpyMat4(camtx, maincam_obj->obmat);
1117         MTC_normalise3DF(camtx[1]);     //up
1118         MTC_normalise3DF(camtx[2]);     //dir
1119         params["from"]=yafray::parameter_t(
1120                         yafray::point3d_t(camtx[3][0],camtx[3][1],camtx[3][2]));
1121         Object* dofob = findObject("OBFOCUS");
1122         float fdist=1;
1123         if (dofob) {
1124                 // dof empty found, modify lookat point accordingly
1125                 // location from matrix, in case animated
1126                 float fdx = dofob->obmat[3][0] - camtx[3][0];
1127                 float fdy = dofob->obmat[3][1] - camtx[3][1];
1128                 float fdz = dofob->obmat[3][2] - camtx[3][2];
1129                 fdist = sqrt(fdx*fdx + fdy*fdy + fdz*fdz);
1130                 cout << "FOCUS object found, distance is: " << fdist << endl;
1131         }
1132         params["to"]=yafray::parameter_t(
1133                         yafray::point3d_t(camtx[3][0] - fdist*camtx[2][0],
1134                                                                                                 camtx[3][1] - fdist*camtx[2][1],
1135                                                                                                 camtx[3][2] - fdist*camtx[2][2]));
1136         params["up"]=yafray::parameter_t(
1137                         yafray::point3d_t(camtx[3][0] + camtx[1][0],
1138                                                                                                 camtx[3][1] + camtx[1][1],
1139                                                                                                 camtx[3][2] + camtx[1][2]));
1140         yafrayGate->addCamera(params);
1141 }
1142
1143 void yafrayPluginRender_t::writeHemilight()
1144 {
1145         yafray::paramMap_t params;
1146         params["type"]=yafray::parameter_t("hemilight");
1147         params["name"]=yafray::parameter_t("hemi_LT");
1148         params["power"]=yafray::parameter_t(1.0);
1149         switch (R.r.GIquality)
1150         {
1151                 case 1 :
1152                 case 2 : params["samples"]=yafray::parameter_t(16);  break;
1153                 case 3 : params["samples"]=yafray::parameter_t(36);  break;
1154                 case 4 : params["samples"]=yafray::parameter_t(64);  break;
1155                 case 5 : params["samples"]=yafray::parameter_t(128);  break;
1156                 default: params["samples"]=yafray::parameter_t(25);
1157         }
1158         yafrayGate->addLight(params);
1159 }
1160
1161 void yafrayPluginRender_t::writePathlight()
1162 {
1163         if(R.r.GIphotons)
1164         {
1165                 yafray::paramMap_t params;
1166                 params["type"]=yafray::parameter_t("globalphotonlight");
1167                 params["name"]=yafray::parameter_t("gpm");
1168                 params["photons"]=yafray::parameter_t(R.r.GIphotoncount);
1169                 params["radius"]=yafray::parameter_t(R.r.GIphotonradius);
1170                 params["depth"]=yafray::parameter_t(((R.r.GIdepth>2) ? (R.r.GIdepth-1) : 1));
1171                 params["caus_depth"]=yafray::parameter_t(R.r.GIcausdepth);
1172                 params["search"]=yafray::parameter_t(R.r.GImixphotons);
1173                 yafrayGate->addLight(params);
1174         }
1175         yafray::paramMap_t params;
1176         params["type"]=yafray::parameter_t("pathlight");
1177         params["name"]=yafray::parameter_t("path_LT");
1178         params["power"]=yafray::parameter_t(1.0);
1179         params["depth"]=yafray::parameter_t(((R.r.GIphotons) ? 1 : R.r.GIdepth));
1180         params["caus_depth"]=yafray::parameter_t(R.r.GIcausdepth);
1181         if(R.r.GIdirect && R.r.GIphotons) params["direct"]=yafray::parameter_t("on");
1182         if (R.r.GIcache && ! (R.r.GIdirect && R.r.GIphotons))
1183         {
1184                 switch (R.r.GIquality)
1185                 {
1186                         case 1 : params["samples"]=yafray::parameter_t(128);break;
1187                         case 2 : params["samples"]=yafray::parameter_t(256);break;
1188                         case 3 : params["samples"]=yafray::parameter_t(512);break;
1189                         case 4 : params["samples"]=yafray::parameter_t(1024);break;
1190                         case 5 : params["samples"]=yafray::parameter_t(2048);break;
1191                         default: params["samples"]=yafray::parameter_t(256);
1192                 }
1193                 float aspect = 1;
1194                 if (R.r.xsch < R.r.ysch) aspect = float(R.r.xsch)/float(R.r.ysch);
1195                 float sbase = 2.0*atan(0.5/(mainCamLens/(aspect*32.0)))/float(R.r.xsch);
1196                 params["cache"]=yafray::parameter_t("on");
1197                 params["use_QMC"]=yafray::parameter_t("on");
1198                 params["threshold"]=yafray::parameter_t(R.r.GIrefinement);
1199                 params["cache_size"]=yafray::parameter_t(sbase*R.r.GIpixelspersample);
1200                 params["shadow_threshold"]=yafray::parameter_t(1.0 - R.r.GIshadowquality);
1201                 params["grid"]=yafray::parameter_t(82);
1202                 params["search"]=yafray::parameter_t(35);
1203                 //params["gradient"]=yafray::parameter_t("off");
1204         }
1205         else
1206         {
1207                 switch (R.r.GIquality)
1208                 {
1209                         case 1 : params["samples"]=yafray::parameter_t(16);break;
1210                         case 2 : params["samples"]=yafray::parameter_t(36);break;
1211                         case 3 : params["samples"]=yafray::parameter_t(64);break;
1212                         case 4 : params["samples"]=yafray::parameter_t(128);break;
1213                         case 5 : params["samples"]=yafray::parameter_t(256);break;
1214                         default: params["samples"]=yafray::parameter_t(25);break;
1215                 }
1216         }
1217         yafrayGate->addLight(params);
1218 }
1219
1220 bool yafrayPluginRender_t::writeWorld()
1221 {
1222         World *world = G.scene->world;
1223         short i=0,j=0;
1224         if (R.r.GIquality!=0) {
1225                 if (R.r.GImethod==1) {
1226                         if (world==NULL) cout << "WARNING: need world background for skydome!\n";
1227                         writeHemilight();
1228                 }
1229                 else if (R.r.GImethod==2) writePathlight();
1230         }
1231
1232         if (world==NULL) return false;
1233
1234         for(i=0;i<8;i++){
1235                 if(world->mtex[i] != NULL)
1236                 {
1237                         if(world->mtex[i]->tex->type == TEX_IMAGE && world->mtex[i]->tex->ima != NULL){
1238                                 
1239                                 for(j=0;j<160;j++){
1240                                         if(world->mtex[i]->tex->ima->name[j] == '\0' && j > 3){
1241                                                 if(
1242                                                         (world->mtex[i]->tex->ima->name[j-3] == 'h' || world->mtex[i]->tex->ima->name[j-3] == 'H' ) &&
1243                                                         (world->mtex[i]->tex->ima->name[j-2] == 'd' || world->mtex[i]->tex->ima->name[j-2] == 'D' ) &&
1244                                                         (world->mtex[i]->tex->ima->name[j-1] == 'r' || world->mtex[i]->tex->ima->name[j-1] == 'R' )
1245                                                         )
1246                                                 {
1247                                                                 yafray::paramMap_t params;
1248                                                                 params["type"]=yafray::parameter_t("HDRI");
1249                                                                 params["name"]=yafray::parameter_t("world_background");
1250                                                                 params["exposure_adjust"]=yafray::parameter_t(world->mtex[i]->tex->bright-1);
1251                                                                 params["mapping"]=yafray::parameter_t("probe");
1252                                                                 params["filename"]=yafray::parameter_t(world->mtex[i]->tex->ima->name);
1253                                                                 yafrayGate->addBackground(params);
1254                                                                 return true;                                            
1255                                                 }
1256                                         }
1257                                 }
1258
1259                                 yafray::paramMap_t params;
1260                                 params["type"]=yafray::parameter_t("image");
1261                                 params["name"]=yafray::parameter_t("world_background");
1262                                 params["power"]=yafray::parameter_t(world->mtex[i]->tex->bright);
1263                                 params["filename"]=yafray::parameter_t(world->mtex[i]->tex->ima->name);
1264                                 yafrayGate->addBackground(params);
1265                                 return true;
1266                         }
1267                 }
1268         }
1269
1270         yafray::paramMap_t params;
1271         params["type"]=yafray::parameter_t("constant");
1272         params["name"]=yafray::parameter_t("world_background");
1273         // if no GI used, the GIpower parameter is not always initialized, so in that case ignore it  (have to change method to init yafray vars in Blender)
1274         float bg_mult;
1275         if (R.r.GImethod==0) bg_mult=1; else bg_mult=R.r.GIpower;
1276         params["color"]=yafray::parameter_t(yafray::color_t(world->horr * bg_mult,
1277                                                                                                                                                                                                                         world->horg * bg_mult,
1278                                                                                                                                                                                                                         world->horb * bg_mult));
1279         yafrayGate->addBackground(params);
1280         return true;
1281 }
1282
1283 #include "RE_callbacks.h"
1284
1285 bool blenderYafrayOutput_t::putPixel(int x, int y,const yafray::color_t &c, 
1286                 yafray::CFLOAT alpha,yafray::PFLOAT depth)
1287 {
1288         unsigned char* bpt = (unsigned char*)R.rectot + ((((R.recty-1)-y)*R.rectx)<<2);
1289         int temp=(int)(c.R*255.0+0.5);
1290         if(temp>255) temp=255;
1291         bpt[4*x]=temp;
1292         temp=(int)(c.G*255.0+0.5);
1293         if(temp>255) temp=255;
1294         bpt[4*x+1]=temp;
1295         temp=(int)(c.B*255.0+0.5);
1296         if(temp>255) temp=255;
1297         bpt[4*x+2]=temp;
1298         temp=(int)(alpha*255.0+0.5);
1299         if(temp>255) temp=255;
1300         bpt[4*x+3]=temp;
1301         out++;
1302         if(out==4096)
1303         {
1304                 RE_local_render_display(0,R.recty-1, R.rectx, R.recty, R.rectot);
1305                 out=0;
1306         }
1307         if(RE_local_test_break())
1308                 return false;
1309         return true;
1310 }