ea7009658261d86e4651e0094d94edb2322ff935
[blender.git] / source / blender / yafray / intern / export_File.cpp
1 #include "export_File.h"
2
3 #include <math.h>
4
5 #include <cstring>
6
7 using namespace std;
8
9 static string command_path = "";
10
11 #ifdef WIN32 
12 #define WIN32_SKIP_HKEY_PROTECTION
13 #include "BLI_winstuff.h"
14
15 #ifndef FILE_MAXDIR
16 #define FILE_MAXDIR  160
17 #endif
18
19 #ifndef FILE_MAXFILE
20 #define FILE_MAXFILE 80
21 #endif
22
23
24 static string find_path()
25 {
26         HKEY    hkey;
27         DWORD dwType, dwSize;
28
29         if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,"Software\\YafRay Team\\YafRay",0,KEY_READ,&hkey)==ERROR_SUCCESS)
30         {
31                 dwType = REG_EXPAND_SZ;
32                 dwSize = MAX_PATH;
33                 DWORD dwStat;
34
35                 char *pInstallDir=new char[MAX_PATH];
36
37                 dwStat=RegQueryValueEx(hkey, TEXT("InstallDir"), 
38                         NULL, NULL,(LPBYTE)pInstallDir, &dwSize);
39                 
40                 if (dwStat == NO_ERROR)
41                 {
42                         string res=pInstallDir;
43                         delete [] pInstallDir;
44                         return res;
45                 }
46                 else
47                         cout << "Couldn't READ \'InstallDir\' value. Is yafray correctly installed?\n";
48                 delete [] pInstallDir;
49
50                 RegCloseKey(hkey);
51         }       
52         else
53                 cout << "Couldn't FIND registry key for yafray, is it installed?\n";
54
55         return string("");
56
57 }
58
59 static int createDir(char* name)
60 {
61         if (BLI_exists(name))
62                 return 2;       //exists
63         if (CreateDirectory((LPCTSTR)(name), NULL)) {
64                 cout << "Directory: " << name << " created\n";
65                 return 1;       // created
66         }
67         else    {
68                 cout << "Could not create directory: " << name << endl;
69                 return 0;       // fail
70         }
71 }
72
73 extern "C" { extern char bprogname[]; }
74
75 // add drive character if not in path string, using blender executable location as reference
76 // later added note: doesn't make much sense actually,
77 // the intended file might not be located on the same drive as where blender is located...
78 static void addDrive(string &path)
79 {
80         int sp = path.find_first_of(":");
81         if (sp==-1) {
82                 string blpath = bprogname;
83                 sp = blpath.find_first_of(":");
84                 if (sp!=-1) path = blpath.substr(0, sp+1) + path;
85         }
86 }
87
88 #else
89
90 #include <sys/stat.h>
91 #include <sys/types.h>
92 #include <sys/wait.h>
93 #include <signal.h>
94 #include <stdlib.h>
95 #include <unistd.h>
96
97 static string unixYafrayPath()
98 {
99         static const char *alternative[]=
100         {
101                 "/usr/local/bin/",
102                 "/usr/bin/",
103                 "/bin/",
104                 NULL
105         };
106
107         for(int i=0;alternative[i]!=NULL;++i)
108         {
109                 string fp=string(alternative[i])+"yafray";
110                 struct stat st;
111                 if(stat(fp.c_str(),&st)<0) continue;
112                 if(st.st_mode&S_IXOTH) return alternative[i];
113         }
114         return "";
115 }
116
117 #endif
118
119 #ifdef WIN32
120 #define MAXPATHLEN MAX_PATH
121 #else
122 #include <sys/param.h>
123 #endif
124 static void adjustPath(string &path)
125 {
126         // if relative, expand to full path
127         char cpath[MAXPATHLEN];
128         strcpy(cpath, path.c_str());
129         BLI_convertstringcode(cpath, G.sce);
130         path = cpath;
131 #ifdef WIN32
132         // add drive char if not there
133         addDrive(path);
134 #endif
135 }
136
137 bool yafrayFileRender_t::initExport()
138 {
139         xmlpath = "";
140         bool dir_failed = false;
141         // try the user setting setting first, export dir must be set and exist
142         if (strlen(U.yfexportdir)==0) 
143         {
144                 cout << "No export directory set in user defaults!" << endl;
145                 char* temp = getenv("TEMP");
146                 // if no envar, use /tmp
147                 xmlpath = temp ? temp : "/tmp";
148                 cout << "Will try TEMP instead: " << xmlpath << endl;
149                 // no fail here, but might fail when opening file...
150         }
151         else 
152         {
153                 xmlpath = U.yfexportdir;
154                 adjustPath(xmlpath);    // possibly relative
155                 cout << "YFexport path is: " << xmlpath << endl;
156                 // check if it exists
157                 if (!BLI_exists(const_cast<char*>(xmlpath.c_str()))) {
158                         cout << "YafRay temporary xml export directory:\n" << U.yfexportdir << "\ndoes not exist!\n";
159 #ifdef WIN32
160                         // try to create it
161                         cout << "Trying to create...\n";
162                         if (createDir(const_cast<char*>(xmlpath.c_str()))==0) dir_failed=true; else dir_failed=false;
163 #else
164                         dir_failed = true;
165 #endif
166                 }
167         }
168
169 #ifdef WIN32
170         // for windows try to get the path to the yafray binary from the registry, only done once
171         if (command_path=="") 
172         {
173                 char path[FILE_MAXDIR+FILE_MAXFILE];
174                 string yafray_path = find_path();
175                 if (yafray_path=="") 
176                 {
177                         // error already printed in find_path()
178                         clearAll();
179                         return false;
180                 }
181                 GetShortPathName((LPCTSTR)(yafray_path.c_str()), path, FILE_MAXDIR+FILE_MAXFILE);
182                 command_path = string(path) + "\\";
183                 cout << "Yafray found at : " << command_path << endl;
184         }
185         // if no export dir set, or could not create, try to create one in the yafray dir, unless it already exists
186         if (dir_failed) 
187         {
188                 string ybdir = command_path + "YBtest";
189                 if (createDir(const_cast<char*>(ybdir.c_str()))==0) dir_failed=true; else dir_failed=false;
190                 xmlpath = ybdir;
191         }
192 #else
193         if (command_path=="")
194         {
195                 command_path = unixYafrayPath();
196                 if (command_path.size()) cout << "Yafray found at : " << command_path << endl;
197         }
198 #endif
199
200         // for all
201         if (dir_failed) return false;
202
203 #ifdef WIN32
204         string DLM = "\\";
205 #else
206         string DLM = "/";
207 #endif
208         // remove trailing slash if needed
209         if (xmlpath.find_last_of(DLM)!=(xmlpath.length()-1)) xmlpath += DLM;
210
211         imgout = xmlpath + "YBtest.tga";
212         xmlpath += "YBtest.xml";
213         xmlfile.open(xmlpath.c_str());
214         if (xmlfile.fail()) 
215         {
216                 cout << "Could not open file\n";
217                 return false;
218         }
219         ostr << setiosflags(ios::showpoint | ios::fixed);
220         xmlfile << "<scene>\n\n";
221         return true;
222 }
223
224 bool yafrayFileRender_t::writeRender()
225 {
226         // finally export render block
227         ostr.str("");
228         ostr << "<render camera_name=\"MAINCAM\"\n";
229         ostr << "\traydepth=\"" << re->r.YF_raydepth << "\" gamma=\"" << re->r.YF_gamma << "\" exposure=\"" << re->r.YF_exposure << "\"\n";
230
231         if(re->r.YF_AA) {
232                 ostr << "\tAA_passes=\"" << re->r.YF_AApasses << "\" AA_minsamples=\"" << re->r.YF_AAsamples << "\"\n";
233                 ostr << "\tAA_pixelwidth=\"" << re->r.YF_AApixelsize << "\" AA_threshold=\"" << re->r.YF_AAthreshold << "\"\n";
234         }
235         else {
236                 // removed the default AA settings for midquality GI, better leave it to user
237                 if ((re->r.mode & R_OSA) && (re->r.osa)) {
238                         int passes = (re->r.osa & 3)==0 ? (re->r.osa >> 2) : 1;
239                         int minsamples=(re->r.osa & 3)==0 ? 4 : re->r.osa;
240                         ostr << "\tAA_passes=\"" << passes << "\" AA_minsamples=\"" << minsamples << "\"\n";
241                 }
242                 else ostr << "\tAA_passes=\"0\" AA_minsamples=\"1\"\n";
243                 ostr << "\tAA_pixelwidth=\"1.5\" AA_threshold=\"0.05\" bias=\"" << re->r.YF_raybias
244                                  << "\" clamp_rgb=\"" << ((re->r.YF_clamprgb==0) ? "on" : "off") << "\"\n";
245         }
246
247         World *world = G.scene->world;
248         if (world) ostr << "\tbackground_name=\"world_background\"\n";
249  
250         // alpha channel render when RGBA button enabled
251         if (re->r.planes==R_PLANES32) ostr << "\n\tsave_alpha=\"on\"";
252         ostr << " >\n";
253
254         // basic fog
255         if (world && (world->mode & WO_MIST)) {
256                 float fd = world->mistdist;
257                 if (fd>0) fd=1.f/fd; else fd=1;
258                 ostr << "\t<fog_density value=\"" << fd << "\" />\n";
259                 ostr << "\t<fog_color r=\"" << world->horr << "\" g=\"" << world->horg << "\" b=\"" << world->horb << "\" />\n";
260         }
261         ostr << "\t<outfile value=\"" << imgout << "\" />\n";
262
263         ostr << "</render>\n\n";
264         xmlfile << ostr.str();
265         return true;
266 }
267
268 bool yafrayFileRender_t::finishExport()
269 {
270         xmlfile << "</scene>\n";
271         xmlfile.close();
272
273         // file exported, now render
274         if (executeYafray(xmlpath))
275                 displayImage();
276         else 
277         {
278                 cout << "Could not execute yafray. Is it in path?" << endl;
279                 return false;
280         }
281         return true;
282 }
283
284 // displays the image rendered with xml export
285 // Now loads rendered image into blender renderbuf.
286 void yafrayFileRender_t::displayImage()
287 {
288         // although it is possible to load the image using blender,
289         // maybe it is best to just do a read here, for now the yafray output is always a raw tga anyway
290
291         FILE* fp = fopen(imgout.c_str(), "rb");
292         if (fp==NULL) {
293                 cout << "YAF_displayImage(): Could not open image file\n";
294                 return;
295         }
296
297         unsigned char header[18];
298         fread(&header, 1, 18, fp);
299         unsigned short width = (unsigned short)(header[12] + (header[13]<<8));
300         unsigned short height = (unsigned short)(header[14] + (header[15]<<8));
301         // don't do anything if resolution doesn't match that of rectot
302         if ((width!=re->winx) || (height!=re->winy)) {
303                 cout << "Wrong image width/height: " << width << "/" << height <<
304                         " expected " << re->winx << "/" << re->winy << endl;
305                 fclose(fp);
306                 fp = NULL;
307                 return;
308         }
309         unsigned char byte_per_pix = (unsigned char)(header[16]>>3);
310         // read past any id (none in this case though)
311         unsigned int idlen = (unsigned int)header[0];
312         if (idlen) fseek(fp, idlen, SEEK_CUR);
313
314         /* XXX how to get the image from Blender and write to it. This call doesn't allow to change buffer rects */
315         RenderResult rres;
316         RE_GetResultImage(re, &rres);
317         // rres.rectx, rres.recty is width/height
318         // rres.rectf is float buffer, scanlines starting in bottom
319         // rres.rectz is zbuffer, available when associated pass is set
320         
321         // read data directly into buffer, picture is upside down
322         const float btf = 1.f/255.f;
323         if (re->r.mode & R_BORDER) {
324                 // border render, yafray is full size render, blender at this point only wants the region
325                 unsigned int xs = (unsigned int)(re->r.border.xmin * re->winx),
326                              ys = (unsigned int)((1.f-re->r.border.ymax) * re->winy);
327                 for (unsigned short y=0; y<height; y++) {
328                         for (unsigned short x=0; x<width; x++) {
329                                 char r = fgetc(fp);
330                                 char g = fgetc(fp);
331                                 char b = fgetc(fp);
332                                 char a = (byte_per_pix==4) ? fgetc(fp) : 255;
333                                 int bx = x-xs, by = y-ys;
334                                 if ((bx >= 0) && (bx < (int)re->rectx) && (by >= 0) && (by < re->recty)) {
335                                         float* bpt = (float*)rres.rectf + (bx + (((re->recty-1) - by)*re->rectx) << 2);
336                                         bpt[2] = (float)r * btf;
337                                         bpt[1] = (float)g * btf;
338                                         bpt[0] = (float)b * btf;
339                                         bpt[3] = (float)a * btf;
340                                         bpt += 4;
341                                 }
342                         }
343                 }
344         }
345         else {
346                 for (unsigned short y=0; y<height; y++) {
347                         float* bpt = (float*)rres.rectf + ((((height-1)-y)*width) << 2);
348                         for (unsigned short x=0; x<width; x++) {
349                                 bpt[2] = ((float)fgetc(fp) * btf);
350                                 bpt[1] = ((float)fgetc(fp) * btf);
351                                 bpt[0] = ((float)fgetc(fp) * btf);
352                                 bpt[3] = (byte_per_pix==4) ? ((float)fgetc(fp) * btf) : 1.f;
353                                 bpt += 4;
354                         }
355                 }
356         }
357
358         fclose(fp);
359         fp = NULL;
360
361         // based on another assumption of ogl errors on my system, forgot to actually draw it...
362         re->result->renlay = render_get_active_layer(re, re->result);
363         re->display_draw(re->result, NULL);
364
365 }
366
367 static string noise2string(short nbtype)
368 {
369         switch (nbtype) {
370                 case TEX_BLENDER:
371                         return "blender";
372                 case TEX_STDPERLIN:
373                         return "stdperlin";
374                 case TEX_VORONOI_F1:
375                         return "voronoi_f1";
376                 case TEX_VORONOI_F2:
377                         return "voronoi_f2";
378                 case TEX_VORONOI_F3:
379                         return "voronoi_f3";
380                 case TEX_VORONOI_F4:
381                         return "voronoi_f4";
382                 case TEX_VORONOI_F2F1:
383                         return "voronoi_f2f1";
384                 case TEX_VORONOI_CRACKLE:
385                         return "voronoi_crackle";
386                 case TEX_CELLNOISE:
387                         return "cellnoise";
388                 default:
389                 case TEX_NEWPERLIN:
390                         return "newperlin";
391         }
392 }
393
394 void yafrayFileRender_t::writeTextures()
395 {
396         // used to keep track of images already written
397         // (to avoid duplicates if also in imagetex for material TexFace texture)
398         set<Image*> dupimg;
399         
400         for (map<string, MTex*>::const_iterator blendtex=used_textures.begin();
401                                                 blendtex!=used_textures.end();++blendtex) {
402                 MTex* mtex = blendtex->second;
403                 Tex* tex = mtex->tex;
404
405                 float nsz = tex->noisesize;
406                 if (nsz!=0.f) nsz=1.f/nsz;
407
408                 // noisebasis type
409                 string ntype = noise2string(tex->noisebasis);
410                 string ts, hardnoise=(tex->noisetype==TEX_NOISESOFT) ? "off" : "on";
411
412                 switch (tex->type) {
413                         case TEX_STUCCI:
414                                 // stucci is clouds as bump, only difference is an extra parameter to handle wall in/out
415                                 // turbulence value is not used, so for large values will not match well
416                         case TEX_CLOUDS: {
417                                 ostr.str("");
418                                 ostr << "<shader type=\"clouds\" name=\"" << blendtex->first << "\" >\n";
419                                 ostr << "\t<attributes>\n";
420                                 ostr << "\t\t<size value=\"" << nsz << "\" />\n";
421                                 ostr << "\t\t<hard value=\"" << hardnoise << "\" />\n";
422                                 if (tex->type==TEX_STUCCI) {
423                                         if (tex->stype==1)
424                                                 ts = "positive";
425                                         else if (tex->stype==2)
426                                                 ts = "negative";
427                                         else ts = "none";
428                                         ostr << "\t\t<bias value=\"" << ts << "\" />\n";
429                                         ostr << "\t\t<depth value=\"0\" />\n";  // for stucci always 0
430                                 }
431                                 else ostr << "\t\t<depth value=\"" << tex->noisedepth << "\" />\n";
432                                 ostr << "\t\t<color_type value=\"" << tex->stype << "\" />\n";
433                                 ostr << "\t\t<noise_type value=\"" << ntype << "\" />\n";
434                                 ostr << "\t</attributes>\n</shader >\n\n";
435                                 xmlfile << ostr.str();
436                                 break;
437                         }
438                         case TEX_WOOD: {
439                                 ostr.str("");
440                                 ostr << "<shader type=\"wood\" name=\"" << blendtex->first << "\" >\n";
441                                 ostr << "\t\t<attributes>\n";
442                                 // blender does not use depth value for wood, always 0
443                                 ostr << "\t\t<depth value=\"0\" />\n";
444                                 float turb = (tex->stype<2) ? 0.0 : tex->turbul;
445                                 ostr << "\t\t<turbulence value=\"" << turb << "\" />\n";
446                                 ostr << "\t\t<size value=\"" << nsz << "\" />\n";
447                                 ostr << "\t\t<hard value=\"" << hardnoise << "\" />\n";
448                                 ts = (tex->stype & 1) ? "rings" : "bands";      //stype 1&3 ringtype
449                                 ostr << "\t\t<wood_type value=\"" << ts << "\" />\n";
450                                 ostr << "\t\t<noise_type value=\"" << ntype << "\" />\n";
451                                 // shape parameter, for some reason noisebasis2 is used...
452                                 ts = "sin";
453                                 if (tex->noisebasis2==1) ts="saw"; else if (tex->noisebasis2==2) ts="tri";
454                                 ostr << "\t\t<shape value=\"" << ts << "\" />\n";
455                                 ostr << "\t</attributes>\n</shader>\n\n";
456                                 xmlfile << ostr.str();
457                                 break;
458                         }
459                         case TEX_MARBLE: {
460                                 ostr.str("");
461                                 ostr << "<shader type=\"marble\" name=\"" << blendtex->first << "\" >\n";
462                                 ostr << "\t<attributes>\n";
463                                 ostr << "\t\t<depth value=\"" << tex->noisedepth << "\" />\n";
464                                 ostr << "\t\t<turbulence value=\"" << tex->turbul << "\" />\n";
465                                 ostr << "\t\t<size value=\"" << nsz << "\" />\n";
466                                 ostr << "\t\t<hard value=\"" << hardnoise << "\" />\n";
467                                 ostr << "\t\t<sharpness value=\"" << (float)(1<<tex->stype) << "\" />\n";
468                                 ostr << "\t\t<noise_type value=\"" << ntype << "\" />\n";
469                                 ts = "sin";
470                                 if (tex->noisebasis2==1) ts="saw"; else if (tex->noisebasis2==2) ts="tri";
471                                 ostr << "\t\t<shape value=\"" << ts << "\" />\n";
472                                 ostr << "\t</attributes>\n</shader>\n\n";
473                                 xmlfile << ostr.str();
474                                 break;
475                         }
476                         case TEX_VORONOI: {
477                                 ostr.str("");
478                                 ostr << "<shader type=\"voronoi\" name=\"" << blendtex->first << "\" >\n";
479                                 ostr << "\t<attributes>\n";
480                                 ts = "int";
481                                 if (tex->vn_coltype==1)
482                                         ts = "col1";
483                                 else if (tex->vn_coltype==2)
484                                         ts = "col2";
485                                 else if (tex->vn_coltype==3)
486                                         ts = "col3";
487                                 ostr << "\t\t<color_type value=\"" << ts << "\" />\n";
488                                 ostr << "\t\t<weight1 value=\"" << tex->vn_w1 << "\" />\n";
489                                 ostr << "\t\t<weight2 value=\"" << tex->vn_w2 << "\" />\n";
490                                 ostr << "\t\t<weight3 value=\"" << tex->vn_w3 << "\" />\n";
491                                 ostr << "\t\t<weight4 value=\"" << tex->vn_w4 << "\" />\n";
492                                 ostr << "\t\t<mk_exponent value=\"" << tex->vn_mexp << "\" />\n";
493                                 ostr << "\t\t<intensity value=\"" << tex->ns_outscale << "\" />\n";
494                                 ostr << "\t\t<size value=\"" << nsz << "\" />\n";
495                                 ts = "actual";
496                                 if (tex->vn_distm==TEX_DISTANCE_SQUARED)
497                                         ts = "squared";
498                                 else if (tex->vn_distm==TEX_MANHATTAN)
499                                         ts = "manhattan";
500                                 else if (tex->vn_distm==TEX_CHEBYCHEV)
501                                         ts = "chebychev";
502                                 else if (tex->vn_distm==TEX_MINKOVSKY_HALF)
503                                         ts = "minkovsky_half";
504                                 else if (tex->vn_distm==TEX_MINKOVSKY_FOUR)
505                                         ts = "minkovsky_four";
506                                 else if (tex->vn_distm==TEX_MINKOVSKY)
507                                         ts = "minkovsky";
508                                 ostr << "\t\t<distance_metric value=\"" << ts << "\" />\n";
509                                 ostr << "\t</attributes>\n</shader>\n\n";
510                                 xmlfile << ostr.str();
511                                 break;
512                         }
513                         case TEX_MUSGRAVE: {
514                                 ostr.str("");
515                                 ostr << "<shader type=\"musgrave\" name=\"" << blendtex->first << "\" >\n";
516                                 ostr << "\t<attributes>\n";
517                                 switch (tex->stype) {
518                                         case TEX_MFRACTAL:
519                                                 ts = "multifractal";
520                                                 break;
521                                         case TEX_RIDGEDMF:
522                                                 ts = "ridgedmf";
523                                                 break;
524                                         case TEX_HYBRIDMF:
525                                                 ts = "hybridmf";
526                                                 break;
527                                         case TEX_HTERRAIN:
528                                                 ts = "heteroterrain";
529                                                 break;
530                                         default:
531                                         case TEX_FBM:
532                                                 ts = "fBm";
533                                 }
534                                 ostr << "\t\t<musgrave_type value=\"" << ts << "\" />\n";
535                                 ostr << "\t\t<noise_type value=\"" << ntype << "\" />\n";
536                                 ostr << "\t\t<H value=\"" << tex->mg_H << "\" />\n";
537                                 ostr << "\t\t<lacunarity value=\"" << tex->mg_lacunarity << "\" />\n";
538                                 ostr << "\t\t<octaves value=\"" << tex->mg_octaves << "\" />\n";
539                                 if ((tex->stype==TEX_HTERRAIN) || (tex->stype==TEX_RIDGEDMF) || (tex->stype==TEX_HYBRIDMF)) {
540                                         ostr << "\t\t<offset value=\"" << tex->mg_offset << "\" />\n";
541                                         if ((tex->stype==TEX_RIDGEDMF) || (tex->stype==TEX_HYBRIDMF))
542                                                 ostr << "\t\t<gain value=\"" << tex->mg_gain << "\" />\n";
543                                 }
544                                 ostr << "\t\t<size value=\"" << nsz << "\" />\n";
545                                 ostr << "\t\t<intensity value=\"" << tex->ns_outscale << "\" />\n";
546                                 ostr << "\t</attributes>\n</shader>\n\n";
547                                 xmlfile << ostr.str();
548                                 break;
549                         }
550                         case TEX_DISTNOISE: {
551                                 ostr.str("");
552                                 ostr << "<shader type=\"distorted_noise\" name=\"" << blendtex->first << "\" >\n";
553                                 ostr << "\t<attributes>\n";
554                                 ostr << "\t\t<distort value=\"" << tex->dist_amount << "\" />\n";
555                                 ostr << "\t\t<size value=\"" << nsz << "\" />\n";
556                                 ostr << "\t\t<noise_type1 value=\"" << ntype << "\" />\n";
557                                 ostr << "\t\t<noise_type2 value=\"" << noise2string(tex->noisebasis2) << "\" />\n";
558                                 ostr << "\t</attributes>\n</shader>\n\n";
559                                 xmlfile << ostr.str();
560                                 break;
561                         }
562                         case TEX_BLEND: {
563                                 ostr.str("");
564                                 ostr << "<shader type=\"gradient\" name=\"" << blendtex->first << "\" >\n";
565                                 ostr << "\t<attributes>\n";
566                                 switch (tex->stype) {
567                                         case 1:  ts="quadratic"; break;
568                                         case 2:  ts="cubic";     break;
569                                         case 3:  ts="diagonal";  break;
570                                         case 4:  ts="sphere";    break;
571                                         case 5:  ts="halo";      break;
572                                         default:
573                                         case 0:  ts="linear";    break;
574                                 }
575                                 ostr << "\t\t<gradient_type value=\"" << ts << "\" />\n";
576                                 if (tex->flag & TEX_FLIPBLEND) ts="on"; else ts="off";
577                                 ostr << "\t\t<flip_xy value=\"" << ts << "\" />\n";
578                                 ostr << "\t</attributes>\n</shader>\n\n";
579                                 xmlfile << ostr.str();
580                                 break;
581                         }
582                         case TEX_NOISE: {
583                                 ostr.str("");
584                                 ostr << "<shader type=\"random_noise\" name=\"" << blendtex->first << "\" >\n";
585                                 ostr << "\t<attributes>\n";
586                                 ostr << "\t\t<depth value=\"" << tex->noisedepth << "\" />\n";
587                                 ostr << "\t</attributes>\n</shader>\n\n";
588                                 xmlfile << ostr.str();
589                                 break;
590                         }
591                         case TEX_IMAGE: {
592                                 Image* ima = tex->ima;
593                                 if (ima) {
594                                         // remember image to avoid duplicates later if also in imagetex
595                                         // (formerly done by removing from imagetex, but need image/material link)
596                                         dupimg.insert(ima);
597                                         ostr.str("");
598                                         // use image name instead of texname here
599                                         ostr << "<shader type=\"image\" name=\"" << ima->id.name << "\" >\n";
600                                         ostr << "\t<attributes>\n";
601                                         string texpath(ima->name);
602                                         adjustPath(texpath);
603                                         ostr << "\t\t<filename value=\"" << texpath << "\" />\n";
604                                         ostr << "\t\t<interpolate value=\"" << ((tex->imaflag & TEX_INTERPOL) ? "bilinear" : "none") << "\" />\n";
605                                         ostr << "\t</attributes>\n</shader>\n\n";
606                                         xmlfile << ostr.str();
607                                 }
608                                 break;
609                         }
610                         default:
611                                 cout << "Unsupported texture type\n";
612                 }
613
614                 // colorbands
615                 if (tex->flag & TEX_COLORBAND) {
616                         ColorBand* cb = tex->coba;
617                         if (cb) {
618                                 ostr.str("");
619                                 ostr << "<shader type=\"colorband\" name=\"" << blendtex->first + "_coba" << "\" >\n";
620                                 ostr << "\t<attributes>\n";
621                                 ostr << "\t\t<input value=\"" << blendtex->first << "\" />\n";
622                                 ostr << "\t</attributes>\n";
623                                 for (int i=0;i<cb->tot;i++) {
624                                         ostr << "\t<modulator value=\"" << cb->data[i].pos << "\" >\n";
625                                         ostr << "\t\t<color r=\"" << cb->data[i].r << "\"" <<
626                                                                                                                 " g=\"" << cb->data[i].g << "\"" <<
627                                                                                                                 " b=\"" << cb->data[i].b << "\"" <<
628                                                                                                                 " a=\"" << cb->data[i].a << "\" />\n";
629                                         ostr << "\t</modulator>\n";
630                                 }
631                                 ostr << "</shader>\n\n";
632                                 xmlfile << ostr.str();
633                         }
634                 }
635
636         }
637         
638         // If used, textures for the material 'TexFace' case
639         if (!imagetex.empty()) {
640                 for (map<Image*, set<Material*> >::const_iterator imgtex=imagetex.begin();
641                                         imgtex!=imagetex.end();++imgtex)
642                 {
643                         // skip if already written above
644                         Image* ima = imgtex->first;
645                         if (dupimg.find(ima)==dupimg.end()) {
646                                 ostr.str("");
647                                 ostr << "<shader type=\"image\" name=\"" << ima->id.name << "\" >\n";
648                                 ostr << "\t<attributes>\n";
649                                 string texpath(ima->name);
650                                 adjustPath(texpath);
651                                 ostr << "\t\t<filename value=\"" << texpath << "\" />\n";
652                                 ostr << "\t</attributes>\n</shader>\n\n";
653                                 xmlfile << ostr.str();
654                         }
655                 }
656         }
657
658 }
659
660 void yafrayFileRender_t::writeShader(const string &shader_name, Material* matr, const string &facetexname)
661 {
662         // if material has ramps, export colorbands first
663         if (matr->mode & (MA_RAMP_COL|MA_RAMP_SPEC))
664         {
665                 // both colorbands without input shader
666                 ColorBand* cb = matr->ramp_col;
667                 if ((matr->mode & MA_RAMP_COL) && (cb!=NULL))
668                 {
669                         ostr.str("");
670                         ostr << "<shader type=\"colorband\" name=\"" << shader_name+"_difframp" << "\" >\n";
671                         ostr << "\t<attributes>\n\t</attributes>\n";
672                         for (int i=0;i<cb->tot;i++) {
673                                 ostr << "\t<modulator value=\"" << cb->data[i].pos << "\" >\n";
674                                 ostr << "\t\t<color r=\"" << cb->data[i].r << "\"" <<
675                                                                                                         " g=\"" << cb->data[i].g << "\"" <<
676                                                                                                         " b=\"" << cb->data[i].b << "\"" <<
677                                                                                                         " a=\"" << cb->data[i].a << "\" />\n";
678                                 ostr << "\t</modulator>\n";
679                         }
680                         ostr << "</shader>\n\n";
681                         xmlfile << ostr.str();
682                 }
683                 cb = matr->ramp_spec;
684                 if ((matr->mode & MA_RAMP_SPEC) && (cb!=NULL))
685                 {
686                         ostr.str("");
687                         ostr << "<shader type=\"colorband\" name=\"" << shader_name+"_specramp" << "\" >\n";
688                         ostr << "\t<attributes>\n\t</attributes>\n";
689                         for (int i=0;i<cb->tot;i++) {
690                                 ostr << "\t<modulator value=\"" << cb->data[i].pos << "\" >\n";
691                                 ostr << "\t\t<color r=\"" << cb->data[i].r << "\"" <<
692                                                                                                         " g=\"" << cb->data[i].g << "\"" <<
693                                                                                                         " b=\"" << cb->data[i].b << "\"" <<
694                                                                                                         " a=\"" << cb->data[i].a << "\" />\n";
695                                 ostr << "\t</modulator>\n";
696                         }
697                         ostr << "</shader>\n\n";
698                         xmlfile << ostr.str();
699                 }
700         }
701
702         ostr.str("");
703         ostr << "<shader type=\"blendershader\" name=\"" << shader_name << "\" >\n";
704         ostr << "\t<attributes>\n";
705         ostr << "\t\t<color r=\"" << matr->r << "\" g=\"" << matr->g << "\" b=\"" << matr->b << "\" />\n";
706         float sr=matr->specr, sg=matr->specg, sb=matr->specb;
707         if (matr->spec_shader==MA_SPEC_WARDISO) {
708                 // ........
709                 sr /= M_PI;
710                 sg /= M_PI;
711                 sb /= M_PI;
712         }
713         ostr << "\t\t<specular_color r=\"" << sr << "\" g=\"" << sg << "\" b=\"" << sb << "\" />\n";
714         ostr << "\t\t<mirror_color r=\"" << matr->mirr << "\" g=\"" << matr->mirg << "\" b=\"" << matr->mirb << "\" />\n";
715         ostr << "\t\t<diffuse_reflect value=\"" << matr->ref << "\" />\n";
716         ostr << "\t\t<specular_amount value=\"" << matr->spec << "\" />\n";
717         ostr << "\t\t<alpha value=\"" << matr->alpha << "\" />\n";
718         // if no GI used, the GIpower parameter is not always initialized, so in that case ignore it
719         float bg_mult = (re->r.GImethod==0) ? 1 : re->r.GIpower;
720         ostr << "\t\t<emit value=\"" << (matr->emit * bg_mult) << "\" />\n";
721
722         // reflection/refraction
723         if ( (matr->mode & MA_RAYMIRROR) || (matr->mode & MA_RAYTRANSP) )
724                 ostr << "\t\t<IOR value=\"" << matr->ang << "\" />\n";
725
726         if (matr->mode & MA_RAYMIRROR)
727         {
728                 // Sofar yafray's min_refle parameter (which misleadingly actually controls fresnel reflection offset)
729                 // has been mapped to Blender's ray_mirror parameter.
730                 // This causes it be be misinterpreted and misused as a reflection amount control however.
731                 // Besides that, it also causes extra complications for the yafray Blendershader.
732                 // So added an actual amount of reflection parameter instead, and another
733                 // extra parameter 'frsOfs' to actually control fresnel offset (re-uses Blender fresnel_mir_i param).
734                 ostr << "\t\t<reflect value=\"on\" />\n";
735                 ostr << "\t\t<reflect_amount value=\""<< matr->ray_mirror << "\" />\n";
736                 float fo = 1.f-(matr->fresnel_mir_i-1.f)*0.25f; // blender param range [1,5], also here reversed (1 in Blender -> no fresnel)
737                 ostr << "\t\t<fresnel_offset value=\""<< fo << "\" />\n";
738
739                 // for backward compatibility, also add old 'reflected' parameter, copy of mirror_color
740                 ostr << "\t\t<reflected r=\"" << matr->mirr << "\" g=\"" << matr->mirg << "\" b=\"" << matr->mirb << "\" />\n";
741                 // same for 'min_refle' param. Instead of the ray_mirror parameter that was used before, since now
742                 // the parameter's function is taken over by the fresnel offset parameter, use that instead.
743                 ostr << "\t\t<min_refle value=\"" << fo << "\" />\n";
744
745         }
746
747         if (matr->mode & MA_RAYTRANSP) 
748         {
749                 ostr << "\t\t<refract value=\"on\" />\n";
750                 ostr << "\t\t<transmit_filter value=\"" << matr->filter << "\" />\n";
751                 // tir on by default
752                 ostr << "\t\t<tir value=\"on\" />\n";
753
754                 // transmit absorption color
755                 // to make things easier(?) for user it now specifies the actual color at 1 unit / YF_dscale of distance
756                 const float maxlog = -log(1e-38);
757                 float ar = (matr->YF_ar>0) ? -log(matr->YF_ar) : maxlog;
758                 float ag = (matr->YF_ag>0) ? -log(matr->YF_ag) : maxlog;
759                 float ab = (matr->YF_ab>0) ? -log(matr->YF_ab) : maxlog;
760                 float sc = matr->YF_dscale;
761                 if (sc!=0.f) sc=1.f/sc;
762                 ostr << "\t\t<absorption r=\"" << ar*sc << "\" g=\"" << ag*sc << "\" b=\"" << ab*sc << "\" />\n";
763                 // dispersion
764                 ostr << "\t\t<dispersion_power value=\"" << matr->YF_dpwr << "\" />\n";
765                 ostr << "\t\t<dispersion_samples value=\"" << matr->YF_dsmp << "\" />\n";
766                 ostr << "\t\t<dispersion_jitter value=\"" << (matr->YF_djit ? "on" : "off") << "\" />\n";
767
768                 // for backward compatibility, also add old 'transmitted' parameter, copy of 'color' * (1-alpha)
769                 float na = 1.f-matr->alpha;
770                 ostr << "\t\t<transmitted r=\"" << matr->r*na << "\" g=\"" << matr->g*na << "\" b=\"" << matr->b*na << "\" />\n";
771         }
772
773         string Mmode = "";
774         if (matr->mode & MA_TRACEBLE) Mmode += "traceable";
775         if (matr->mode & MA_SHADOW) Mmode += " shadow";
776         if (matr->mode & MA_SHLESS) Mmode += " shadeless";
777         if (matr->mode & MA_VERTEXCOL) Mmode += " vcol_light";
778         if (matr->mode & MA_VERTEXCOLP) Mmode += " vcol_paint";
779         if (matr->mode & MA_ZTRA) Mmode += " ztransp";
780         if (matr->mode & MA_ONLYSHADOW) Mmode += " onlyshadow";
781         if (Mmode!="") ostr << "\t\t<matmodes value=\"" << Mmode << "\" />\n";
782
783         // diffuse & specular brdf, lambert/cooktorr defaults
784         // diffuse
785         if (matr->diff_shader==MA_DIFF_ORENNAYAR) {
786                 ostr << "\t\t<diffuse_brdf value=\"oren_nayar\" />\n";
787                 ostr << "\t\t<roughness value=\"" << matr->roughness << "\" />\n";
788         }
789         else if (matr->diff_shader==MA_DIFF_TOON) {
790                 ostr << "\t\t<diffuse_brdf value=\"toon\" />\n";
791                 ostr << "\t\t<toondiffuse_size value=\"" << matr->param[0] << "\" />\n";
792                 ostr << "\t\t<toondiffuse_smooth value=\"" << matr->param[1] << "\" />\n";
793         }
794         else if (matr->diff_shader==MA_DIFF_MINNAERT) {
795                 ostr << "\t\t<diffuse_brdf value=\"minnaert\" />\n";
796                 ostr << "\t\t<darkening value=\"" << matr->darkness << "\" />\n";
797         }
798         else ostr << "\t\t<diffuse_brdf value=\"lambert\" />\n";
799         // specular
800         if (matr->spec_shader==MA_SPEC_PHONG) {
801                 ostr << "\t\t<specular_brdf value=\"phong\" />\n";
802                 ostr << "\t\t<hard value=\"" << matr->har << "\" />\n";
803         }
804         else if (matr->spec_shader==MA_SPEC_BLINN) {
805                 ostr << "\t\t<specular_brdf value=\"blinn\" />\n";
806                 ostr << "\t\t<blinn_ior value=\"" << matr->refrac << "\" />\n";
807                 ostr << "\t\t<hard value=\"" << matr->har << "\" />\n";
808         }
809         else if (matr->spec_shader==MA_SPEC_TOON) {
810                 ostr << "\t\t<specular_brdf value=\"toon\" />\n";
811                 ostr << "\t\t<toonspecular_size value=\"" << matr->param[2] << "\" />\n";
812                 ostr << "\t\t<toonspecular_smooth value=\"" << matr->param[3] << "\" />\n";
813         }
814         else if (matr->spec_shader==MA_SPEC_WARDISO) {
815                 ostr << "\t\t<specular_brdf value=\"ward\" />\n";
816                 ostr << "\t\t<u_roughness value=\"" << matr->rms << "\" />\n";
817                 ostr << "\t\t<v_roughness value=\"" << matr->rms << "\" />\n";
818         }
819         else {
820                 ostr << "\t\t<specular_brdf value=\"blender_cooktorr\" />\n";
821                 ostr << "\t\t<hard value=\"" << matr->har << "\" />\n";
822         }
823
824         // ramps, if used
825         if (matr->mode & (MA_RAMP_COL|MA_RAMP_SPEC))
826         {
827                 const string rm_blend[9] = {"mix", "add", "mul", "sub", "screen", "divide", "difference", "darken", "lighten"};
828                 const string rm_mode[4] = {"shader", "energy", "normal", "result"};
829                 // diffuse
830                 if ((matr->mode & MA_RAMP_COL) && (matr->ramp_col!=NULL))
831                 {
832                         ostr << "\t\t<diffuse_ramp value=\"" << shader_name+"_difframp" << "\" />\n";
833                         ostr << "\t\t<diffuse_ramp_mode value=\"" << rm_mode[(int)matr->rampin_col] << "\" />\n";
834                         ostr << "\t\t<diffuse_ramp_blend value=\"" << rm_blend[(int)matr->rampblend_col] << "\" />\n";
835                         ostr << "\t\t<diffuse_ramp_factor value=\"" << matr->rampfac_col << "\" />\n";
836                 }
837                 // specular
838                 if ((matr->mode & MA_RAMP_SPEC) && (matr->ramp_spec!=NULL)) {
839                         ostr << "\t\t<specular_ramp value=\"" << shader_name+"_specramp" << "\" />\n";
840                         ostr << "\t\t<specular_ramp_mode value=\"" << rm_mode[(int)matr->rampin_spec] << "\" />\n";
841                         ostr << "\t\t<specular_ramp_blend value=\"" << rm_blend[(int)matr->rampblend_spec] << "\" />\n";
842                         ostr << "\t\t<specular_ramp_factor value=\"" << matr->rampfac_spec << "\" />\n";
843                 }
844         }
845
846         ostr << "\t</attributes>\n";
847         xmlfile << ostr.str();
848         
849         // modulators
850         // first modulator is the texture of the face, if used (TexFace mode)
851         if (facetexname.length()!=0) {
852                         ostr.str("");
853                         ostr << "\t<modulator>\n";
854                         ostr << "\t\t<input value=\"" << facetexname << "\" />\n";
855                         ostr << "\t\t<color value=\"1\" />\n";
856                         ostr << "\t</modulator>\n";
857                         xmlfile << ostr.str();
858         }
859
860         for (int m2=0;m2<MAX_MTEX;m2++) {
861
862                 if (matr->septex & (1<<m2)) continue;// all active channels
863
864                 // ignore null mtex
865                 MTex* mtex = matr->mtex[m2];
866                 if (mtex==NULL) continue;
867
868                 // ignore null tex
869                 Tex* tex = mtex->tex;
870                 if (tex==NULL) continue;
871
872                 map<string, MTex*>::const_iterator mtexL = used_textures.find(string(tex->id.name));
873                 if (mtexL!=used_textures.end()) {
874
875                         ostr.str("");
876                         ostr << "\t<modulator>\n";
877                         // when no facetex used, shader_name is created from original material name
878                         if (facetexname.length()!=0)
879                                 ostr << "\t\t<input value=\"" << matr->id.name << "_map" << m2 << "\" />\n";
880                         else
881                                 ostr << "\t\t<input value=\"" << shader_name << "_map" << m2 << "\" />\n";
882
883                         // blendtype, would have been nice if the order would have been the same as for ramps...
884                         const string blendtype[MTEX_NUM_BLENDTYPES] = {"mix", "mul", "add", "sub", "divide", "darken", "difference", "lighten", "screen", "hue", "sat", "val", "color"};
885                         ostr << "\t\t<mode value=\"" << blendtype[(int)mtex->blendtype] << "\" />\n";
886
887                         // texture color (for use with MUL and/or no_rgb etc..)
888                         ostr << "\t\t<texcol r=\"" << mtex->r << "\" g=\"" << mtex->g << "\" b=\"" << mtex->b << "\" />\n";
889
890                         // texture contrast, brightness & color adjustment
891                         ostr << "\t\t<filtercolor r=\"" << tex->rfac << "\" g=\"" << tex->gfac << "\" b=\"" << tex->bfac << "\" />\n";
892                         ostr << "\t\t<contrast value=\"" << tex->contrast << "\" />\n";
893                         ostr << "\t\t<brightness value=\"" << tex->bright << "\" />\n";
894
895                         // all texture flags now are switches, having the value 1 or -1 (negative option)
896                         // the negative option only used for the intensity modulation options.
897
898                         // material (diffuse) color, amount controlled by colfac (see below)
899                         if (mtex->mapto & MAP_COL)
900                                 ostr << "\t\t<color value=\"1\" />\n";
901
902                         // bumpmapping
903                         if ((mtex->mapto & MAP_NORM) || (mtex->maptoneg & MAP_NORM)) {
904                                 // for yafray, bump factor is negated (unless tex is stucci, not affected by 'Neg')
905                                 // scaled down quite a bit
906                                 float nf = mtex->norfac;
907                                 if (tex->type!=TEX_STUCCI) nf *= -1.f;
908                                 if (mtex->maptoneg & MAP_NORM) nf *= -1.f;
909                                 ostr << "\t\t<normal value=\"" << (nf/60.f) << "\" />\n";
910
911                         }
912
913                         // all blender texture modulation as switches, either 1 or -1 (negative state of button)
914                         // Csp, specular color modulation
915                         if (mtex->mapto & MAP_COLSPEC)
916                                 ostr << "\t\t<colspec value=\"1\" />\n";
917
918                         // CMir, mirror color  modulation
919                         if (mtex->mapto & MAP_COLMIR)
920                                 ostr << "\t\t<colmir value=\"1\" />\n";
921
922                         // Ref, diffuse reflection amount  modulation
923                         if ((mtex->mapto & MAP_REF) || (mtex->maptoneg & MAP_REF)) {
924                                 int t = 1;
925                                 if (mtex->maptoneg & MAP_REF) t = -1;
926                                 ostr << "\t\t<difref value=\"" << t << "\" />\n";
927                         }
928
929                         // Spec, specular amount mod
930                         if ((mtex->mapto & MAP_SPEC) || (mtex->maptoneg & MAP_SPEC)) {
931                                 int t = 1;
932                                 if (mtex->maptoneg & MAP_SPEC) t = -1;
933                                 ostr << "\t\t<specular value=\"" << t << "\" />\n";
934                         }
935
936                         // hardness modulation
937                         if ((mtex->mapto & MAP_HAR) || (mtex->maptoneg & MAP_HAR)) {
938                                 int t = 1;
939                                 if (mtex->maptoneg & MAP_HAR) t = -1;
940                                 ostr << "\t\t<hard value=\"" << t << "\" />\n";
941                         }
942
943                         // alpha modulation
944                         if ((mtex->mapto & MAP_ALPHA) || (mtex->maptoneg & MAP_ALPHA)) {
945                                 int t = 1;
946                                 if (mtex->maptoneg & MAP_ALPHA) t = -1;
947                                 ostr << "\t\t<alpha value=\"" << t << "\" />\n";
948                         }
949
950                         // emit modulation
951                         if ((mtex->mapto & MAP_EMIT) || (mtex->maptoneg & MAP_EMIT)) {
952                                 int t = 1;
953                                 if (mtex->maptoneg & MAP_EMIT) t = -1;
954                                 ostr << "\t\t<emit value=\"" << t << "\" />\n";
955                         }
956
957                         // raymir modulation
958                         if ((mtex->mapto & MAP_RAYMIRR) || (mtex->maptoneg & MAP_RAYMIRR)) {
959                                 int t = 1;
960                                 if (mtex->maptoneg & MAP_RAYMIRR) t = -1;
961                                 ostr << "\t\t<raymir value=\"" << t << "\" />\n";
962                         }
963
964                         // texture flag, combination of strings
965                         string ts = "";
966                         if (mtex->texflag & (MTEX_RGBTOINT | MTEX_STENCIL | MTEX_NEGATIVE)) {
967                                 if (mtex->texflag & MTEX_RGBTOINT) ts += "no_rgb ";
968                                 if (mtex->texflag & MTEX_STENCIL) ts += "stencil ";
969                                 if (mtex->texflag & MTEX_NEGATIVE) ts += "negative";
970                                 ostr << "\t\t<texflag value=\"" << ts << "\" />\n";
971                         }
972
973                         // colfac, controls amount of color modulation
974                         ostr << "\t\t<colfac value=\"" << mtex->colfac << "\" />\n";
975
976                         // def_var
977                         ostr << "\t\t<def_var value=\"" << mtex->def_var << "\" />\n";
978
979                         //varfac
980                         ostr << "\t\t<varfac value=\"" << mtex->varfac << "\" />\n";
981
982                         if ((tex->imaflag & (TEX_CALCALPHA | TEX_USEALPHA)) || (tex->flag & TEX_NEGALPHA)) {
983                                 ts = "";
984                                 if (tex->imaflag & TEX_CALCALPHA) ts += "calc_alpha ";
985                                 if (tex->imaflag & TEX_USEALPHA) ts += "use_alpha ";
986                                 if (tex->flag & TEX_NEGALPHA) ts += "neg_alpha";
987                                 ostr << "\t\t<alpha_flag value=\"" << ts << "\" />\n";
988                         }
989
990                         // image as normalmap flag
991                         if (tex->imaflag & TEX_NORMALMAP) ostr << "\t\t<normalmap value=\"on\" />\n";
992
993                         ostr << "\t</modulator>\n";
994                         xmlfile << ostr.str();
995
996                 }
997         }
998         xmlfile << "</shader>\n\n";
999
1000 }
1001
1002
1003 // write all materials & modulators
1004 void yafrayFileRender_t::writeMaterialsAndModulators()
1005 {
1006         // shaders/mappers for regular texture (or non-texture) mode
1007         // In case material has texface mode, and all faces have an image texture,
1008         // this shader will not be used, but still be written
1009         for (map<string, Material*>::const_iterator blendmat=used_materials.begin();
1010                         blendmat!=used_materials.end();++blendmat)
1011         {
1012
1013                 Material* matr = blendmat->second;
1014
1015                 // mapper(s)
1016                 for (int m=0;m<MAX_MTEX;m++)
1017                 {
1018
1019                         if (matr->septex & (1<<m)) continue;// all active channels
1020
1021                         // ignore null mtex
1022                         MTex* mtex = matr->mtex[m];
1023                         if (mtex==NULL) continue;
1024                         // ignore null tex
1025                         Tex* tex = mtex->tex;
1026                         if (tex==NULL) continue;
1027
1028                         map<string, MTex*>::const_iterator mtexL = used_textures.find(string(tex->id.name));
1029                         if (mtexL!=used_textures.end()) {
1030                                 ostr.str("");
1031                                 ostr << "<shader type=\"blendermapper\" name=\"" << blendmat->first + "_map" << m <<"\"";
1032                                 if ((mtex->texco & TEXCO_OBJECT) || (mtex->texco & TEXCO_REFL) || (mtex->texco & TEXCO_NORM))
1033                                 {
1034                                         // For object, reflection & normal mapping, add the object matrix to the modulator,
1035                                         // as in LF script, use camera matrix if no object specified.
1036                                         // In this case this means the inverse of that matrix
1037                                         float texmat[4][4], itexmat[4][4];
1038                                         if ((mtex->texco & TEXCO_OBJECT) && (mtex->object))
1039                                                 MTC_Mat4CpyMat4(texmat, mtex->object->obmat);
1040                                         else    // also for refl. map
1041                                                 MTC_Mat4CpyMat4(texmat, maincam_obj->obmat);
1042                                         MTC_Mat4Invert(itexmat, texmat);
1043                                         ostr << "\n\t\tm00=\"" << itexmat[0][0] << "\" m01=\"" << itexmat[1][0]
1044                                                          << "\" m02=\"" << itexmat[2][0] << "\" m03=\"" << itexmat[3][0] << "\"\n";
1045                                         ostr << "\t\tm10=\"" << itexmat[0][1] << "\" m11=\"" << itexmat[1][1]
1046                                                          << "\" m12=\"" << itexmat[2][1] << "\" m13=\"" << itexmat[3][1] << "\"\n";
1047                                         ostr << "\t\tm20=\"" << itexmat[0][2] << "\" m21=\"" << itexmat[1][2]
1048                                                          << "\" m22=\"" << itexmat[2][2] << "\" m23=\"" << itexmat[3][2] << "\"\n";
1049                                         ostr << "\t\tm30=\"" << itexmat[0][3] << "\" m31=\"" << itexmat[1][3]
1050                                                          << "\" m32=\"" << itexmat[2][3] << "\" m33=\"" << itexmat[3][3] << "\">\n";
1051                                 }
1052                                 else ostr << ">\n";
1053                                 ostr << "\t<attributes>\n";
1054
1055                                 // use image name instead of texname when texture is image
1056                                 if ((tex->type==TEX_IMAGE) && tex->ima)
1057                                         ostr << "\t\t<input value=\"" << tex->ima->id.name << "\" />\n";
1058                                 else if ((tex->flag & TEX_COLORBAND) & (tex->coba!=NULL))
1059                                         ostr << "\t\t<input value=\"" << mtexL->first + "_coba" << "\" />\n";
1060                                 else
1061                                         ostr << "\t\t<input value=\"" << mtexL->first << "\" />\n";
1062
1063                                 // texture size
1064                                 ostr << "\t\t<sizex value=\"" << mtex->size[0] << "\" />\n";
1065                                 ostr << "\t\t<sizey value=\"" << mtex->size[1] << "\" />\n";
1066                                 ostr << "\t\t<sizez value=\"" << mtex->size[2] << "\" />\n";
1067
1068                                 // texture offset
1069                                 ostr << "\t\t<ofsx value=\"" << mtex->ofs[0] << "\" />\n";
1070                                 ostr << "\t\t<ofsy value=\"" << mtex->ofs[1] << "\" />\n";
1071                                 ostr << "\t\t<ofsz value=\"" << mtex->ofs[2] << "\" />\n";
1072
1073                                 // texture coordinates, have to disable 'sticky' in Blender
1074                                 if (mtex->texco & TEXCO_UV)
1075                                         ostr << "\t\t<texco value=\"uv\" />\n";
1076                                 else if ((mtex->texco & TEXCO_GLOB) || (mtex->texco & TEXCO_OBJECT))
1077                                         // object mode is also set as global, but the object matrix was specified above with <modulator..>
1078                                         ostr << "\t\t<texco value=\"global\" />\n";
1079                                 else if ((mtex->texco & TEXCO_ORCO) || (mtex->texco & TEXCO_STRAND))
1080                                         // orco flag now used for 'strand'-mapping as well, see mesh code
1081                                         ostr << "\t\t<texco value=\"orco\" />\n";
1082                                 else if (mtex->texco & TEXCO_WINDOW)
1083                                         ostr << "\t\t<texco value=\"window\" />\n";
1084                                 else if (mtex->texco & TEXCO_NORM)
1085                                         ostr << "\t\t<texco value=\"normal\" />\n";
1086                                 else if (mtex->texco & TEXCO_REFL)
1087                                         ostr << "\t\t<texco value=\"reflect\" />\n";
1088
1089                                 // texture projection axes, both image & procedural
1090                                 string proj = "nxyz";           // 'n' for 'none'
1091                                 ostr << "\t\t<proj_x value=\"" << proj[mtex->projx] << "\" />\n";
1092                                 ostr << "\t\t<proj_y value=\"" << proj[mtex->projy] << "\" />\n";
1093                                 ostr << "\t\t<proj_z value=\"" << proj[mtex->projz] << "\" />\n";
1094
1095                                 // texture mapping parameters only relevant to image type
1096                                 if (tex->type==TEX_IMAGE) {
1097                                         if (mtex->mapping==MTEX_FLAT)
1098                                                 ostr << "\t\t<mapping value=\"flat\" />\n";
1099                                         else if (mtex->mapping==MTEX_CUBE)
1100                                                 ostr << "\t\t<mapping value=\"cube\" />\n";
1101                                         else if (mtex->mapping==MTEX_TUBE)
1102                                                 ostr << "\t\t<mapping value=\"tube\" />\n";
1103                                         else if (mtex->mapping==MTEX_SPHERE)
1104                                                 ostr << "\t\t<mapping value=\"sphere\" />\n";
1105
1106                                         // repeat
1107                                         ostr << "\t\t<xrepeat value=\"" << tex->xrepeat << "\" />\n";
1108                                         ostr << "\t\t<yrepeat value=\"" << tex->yrepeat << "\" />\n";
1109
1110                                         // clipping
1111                                         if (tex->extend==TEX_EXTEND)
1112                                                 ostr << "\t\t<clipping value=\"extend\" />\n";
1113                                         else if (tex->extend==TEX_CLIP)
1114                                                 ostr << "\t\t<clipping value=\"clip\" />\n";
1115                                         else if (tex->extend==TEX_CLIPCUBE)
1116                                                 ostr << "\t\t<clipping value=\"clipcube\" />\n";
1117                                         else if (tex->extend==TEX_CHECKER) {
1118                                                 ostr << "\t\t<clipping value=\"checker\" />\n";
1119                                                 string ts = "";
1120                                                 if (tex->flag & TEX_CHECKER_ODD) ts += "odd";
1121                                                 if (tex->flag & TEX_CHECKER_EVEN) ts += " even";
1122                                                 ostr << "\t\t<checker_mode value=\"" << ts << "\" />\n";
1123                                                 ostr << "\t\t<checker_dist value=\"" << tex->checkerdist << "\" />\n";
1124                                         }
1125                                         else
1126                                                 ostr << "\t\t<clipping value=\"repeat\" />\n";
1127
1128                                         // crop min/max
1129                                         ostr << "\t\t<cropmin_x value=\"" << tex->cropxmin << "\" />\n";
1130                                         ostr << "\t\t<cropmin_y value=\"" << tex->cropymin << "\" />\n";
1131                                         ostr << "\t\t<cropmax_x value=\"" << tex->cropxmax << "\" />\n";
1132                                         ostr << "\t\t<cropmax_y value=\"" << tex->cropymax << "\" />\n";
1133
1134                                         // rot90 flag
1135                                         string ts = "off";
1136                                         if (tex->imaflag & TEX_IMAROT) ts = "on";
1137                                         ostr << "\t\t<rot90 value=\"" << ts << "\" />\n";
1138                                 }
1139
1140                                 ostr << "\t</attributes>\n";
1141                                 ostr << "</shader>\n\n";
1142
1143                                 xmlfile << ostr.str();
1144                         }
1145                 }
1146
1147                 // shader + modulators
1148                 writeShader(blendmat->first, matr);
1149
1150         }
1151
1152         // write the mappers & shaders for the TexFace case
1153         if (!imagetex.empty()) {
1154                 // Yafray doesn't have per-face-textures, only per-face-shaders,
1155                 // so create as many mappers/shaders as the images used by the object
1156                 int snum = 0;
1157                 for (map<Image*, set<Material*> >::const_iterator imgtex=imagetex.begin();
1158                                 imgtex!=imagetex.end();++imgtex)
1159                 {
1160
1161                         for (set<Material*>::const_iterator imgmat=imgtex->second.begin();
1162                                         imgmat!=imgtex->second.end();++imgmat)
1163                         {
1164                                 Material* matr = *imgmat;
1165                                 // mapper
1166                                 ostr.str("");
1167                                 ostr << "<shader type=\"blendermapper\" name=\"" << string(matr->id.name) + "_ftmap" << snum << "\" >\n";
1168                                 ostr << "\t<attributes>\n";
1169                                 ostr << "\t\t<input value=\"" << imgtex->first->id.name << "\" />\n";
1170                                 // all yafray default settings, except for texco, so no need to set others
1171                                 ostr << "\t\t<texco value=\"uv\" />\n";
1172                                 ostr << "\t</attributes>\n";
1173                                 ostr << "</shader>\n\n";
1174                                 xmlfile << ostr.str();
1175
1176                                 // shader, remember name, used later when writing per-face-shaders
1177                                 ostr.str("");
1178                                 ostr << matr->id.name <<  "_ftsha" << snum;
1179                                 string shader_name = ostr.str();
1180                                 imgtex_shader[string(matr->id.name) + string(imgtex->first->id.name)] = shader_name;
1181
1182                                 ostr.str("");
1183                                 ostr << matr->id.name << "_ftmap" << snum++;
1184                                 writeShader(shader_name, matr, ostr.str());
1185                         }
1186
1187                 }
1188         }
1189
1190 }
1191
1192
1193 void yafrayFileRender_t::writeObject(Object* obj, ObjectRen *obr, const vector<VlakRen*> &VLR_list, const float obmat[4][4])
1194 {
1195         ostr.str("");
1196         // transform first (not necessarily actual obj->obmat, can be duplivert see below)
1197         ostr << "<transform m00=\"" << obmat[0][0] << "\" m01=\"" << obmat[1][0]
1198                          <<         "\" m02=\"" << obmat[2][0] << "\" m03=\"" << obmat[3][0] << "\"\n";
1199         ostr << "           m10=\"" << obmat[0][1] << "\" m11=\"" << obmat[1][1]
1200                          <<         "\" m12=\"" << obmat[2][1] << "\" m13=\"" << obmat[3][1] << "\"\n";
1201         ostr << "           m20=\"" << obmat[0][2] << "\" m21=\"" << obmat[1][2]
1202                          <<         "\" m22=\"" << obmat[2][2] << "\" m23=\"" << obmat[3][2] << "\"\n";
1203         ostr << "           m30=\"" << obmat[0][3] << "\" m31=\"" << obmat[1][3]
1204                          <<         "\" m32=\"" << obmat[2][3] << "\" m33=\"" << obmat[3][3] << "\">\n";
1205         xmlfile << ostr.str();
1206
1207         ostr.str("");
1208
1209         // using the ObjectRen database, contruct a new name if object has a parent.
1210         // This is done to prevent name clashes (group/library link related)
1211         string obname(obj->id.name);
1212         // previous implementation, keep around, in case this is still useful
1213         //if (obj->id.flag & (LIB_EXTERN|LIB_INDIRECT))obname = "lib_" + obname;
1214         ObjectRen *obren;
1215         for (obren = static_cast<ObjectRen*>(re->objecttable.first);
1216              obren; obren=static_cast<ObjectRen*>(obren->next))
1217         {
1218                 Object *db_ob = obren->ob, *db_par = obren->par;
1219                 if (db_ob==obj)
1220                         if ((db_ob!=NULL) && (db_par!=NULL)) {
1221                                 obname += "_" + string(db_par->id.name);
1222                                 break;
1223                         }
1224         }
1225
1226         ostr << "<object name=\"" << obname << "\"";
1227         // Yafray still needs default shader name in object def.,
1228         // since we write a shader with every face, simply use the material of the first face.
1229         // If this is an empty string, assume default material.
1230         VlakRen* face0 = VLR_list[0];
1231         Material* face0mat = face0->mat;
1232         string matname(face0mat->id.name);
1233         // use name in imgtex_shader list if 'TexFace' enabled for this material
1234         if (face0mat->mode & MA_FACETEXTURE) {
1235                 MTFace* tface = RE_vlakren_get_tface(obr, face0, obr->actmtface, NULL, 0);
1236                 if (tface) {
1237                         Image* fimg = (Image*)tface->tpage;
1238                         if (fimg) matname = imgtex_shader[string(face0mat->id.name) + string(fimg->id.name)];
1239                 }
1240         }
1241         bool shadow = face0mat->mode & MA_TRACEBLE;
1242         ostr <<" shadow=\""<< (shadow ? "on" : "off" ) << "\" ";
1243         bool caus = (((face0mat->mode & MA_RAYTRANSP) | (face0->mat->mode & MA_RAYMIRROR))!=0);
1244         if (caus) ostr << "caus_IOR=\"" << face0mat->ang << "\"";
1245         if (matname.length()==0) matname = "blender_default";
1246         ostr << " shader_name=\"" << matname << "\" >\n";
1247         ostr << "\t<attributes>\n";
1248         if (caus)
1249         {
1250                         float tr = 1.0-face0mat->alpha;
1251                         ostr << "\t\t<caus_tcolor r=\"" << face0mat->r*tr
1252                                          << "\" g=\"" << face0mat->g*tr
1253                                          << "\" b=\"" << face0mat->b*tr << "\" />\n";
1254                         tr = face0mat->ray_mirror;
1255                         ostr << "\t\t<caus_rcolor r=\"" << face0mat->mirr*tr
1256                                          << "\" g=\"" << face0mat->mirg*tr
1257                                          << "\" b=\"" << face0mat->mirb*tr << "\" />\n";
1258         }
1259         ostr << "\t</attributes>\n";
1260         xmlfile << ostr.str();
1261
1262         // Export orco coords test.
1263         // Previously was done by checking orco pointer, however this can be non-null but still not initialized.
1264         // Test the rendermaterial texco flag instead.
1265         // update2: bug #3193 it seems it has changed again with the introduction of static 'hair' particles,
1266         // now it uses the vert pointer again as an extra test to make sure there are orco coords available
1267         int has_orco = 0;
1268         if (face0mat->texco & TEXCO_STRAND)
1269                 has_orco = 1;
1270         else
1271                 has_orco = (((face0mat->texco & TEXCO_ORCO)!=0) && (face0->v1->orco!=NULL)) ? 2 : 0;
1272
1273         string has_orco_st = has_orco ? "on" : "off";
1274
1275         // smooth shading if enabled
1276         bool no_auto = true;    //in case non-mesh, or mesh has no autosmooth
1277         if (obj->type==OB_MESH) {
1278                 Mesh* mesh = (Mesh*)obj->data;
1279                 if (mesh->flag & ME_AUTOSMOOTH) {
1280                         no_auto = false;
1281                         ostr.str("");
1282                         ostr << "\t<mesh autosmooth=\"" << mesh->smoothresh << "\" has_orco=\"" << has_orco_st << "\" >\n";
1283                         xmlfile << ostr.str();
1284                 }
1285         }
1286         // this for non-mesh as well
1287         if (no_auto) {
1288                 // If AutoSmooth not used, since yafray currently cannot specify if a face is smooth
1289                 // or flat shaded, the smooth flag of the first face is used to determine
1290                 // the shading for the whole mesh
1291                 if (face0->flag & ME_SMOOTH)
1292                         xmlfile << "\t<mesh autosmooth=\"180\" has_orco=\"" << has_orco_st << "\" >\n";
1293                 else
1294                         xmlfile << "\t<mesh autosmooth=\"0.1\" has_orco=\"" << has_orco_st << "\" >\n"; //0 shows artefacts
1295         }
1296
1297         // now all vertices
1298         map<VertRen*, int> vert_idx;    // for removing duplicate verts and creating an index list
1299         int vidx = 0;   // vertex index counter
1300
1301         // vertices, transformed back to world
1302         xmlfile << "\t\t<points>\n";
1303
1304         // for deformed objects, object->imat is no longer valid,
1305         // so have to create inverse render matrix ourselves here
1306         float mat[4][4], imat[4][4];
1307         MTC_Mat4MulMat4(mat, obj->obmat, re->viewmat);
1308         MTC_Mat4Invert(imat, mat);
1309
1310         for (vector<VlakRen*>::const_iterator fci=VLR_list.begin();
1311                                 fci!=VLR_list.end();++fci)
1312         {
1313                 VlakRen* vlr = *fci;
1314                 VertRen* ver;
1315                 float* orco;
1316                 float tvec[3];
1317                 ostr.str("");
1318                 if (vert_idx.find(vlr->v1)==vert_idx.end()) {
1319                         vert_idx[vlr->v1] = vidx++;
1320                         ver = vlr->v1;
1321                         MTC_cp3Float(ver->co, tvec);
1322                         MTC_Mat4MulVecfl(imat, tvec);
1323                         ostr << "\t\t\t<p x=\"" << tvec[0]
1324                                    << "\" y=\"" << tvec[1]
1325                                    << "\" z=\"" << tvec[2] << "\" />\n";
1326                         // has_orco now an int, if 1 -> strand mapping, if 2 -> normal orco mapping
1327                         if (has_orco==1) {
1328                                 ostr << "\t\t\t<p x=\"" << ver->accum
1329                                      << "\" y=\"" << ver->accum
1330                                      << "\" z=\"" << ver->accum << "\" />\n";
1331                         }
1332                         else if (has_orco==2) {
1333                                 orco = ver->orco;
1334                                 ostr << "\t\t\t<p x=\"" << orco[0]
1335                                      << "\" y=\"" << orco[1]
1336                                      << "\" z=\"" << orco[2] << "\" />\n";
1337                         }
1338                 }
1339                 if (vert_idx.find(vlr->v2)==vert_idx.end()) {
1340                         vert_idx[vlr->v2] = vidx++;
1341                         ver = vlr->v2;
1342                         MTC_cp3Float(ver->co, tvec);
1343                         MTC_Mat4MulVecfl(imat, tvec);
1344                         ostr << "\t\t\t<p x=\"" << tvec[0]
1345                                    << "\" y=\"" << tvec[1]
1346                                    << "\" z=\"" << tvec[2] << "\" />\n";
1347                         // has_orco now an int, if 1 -> strand mapping, if 2 -> normal orco mapping
1348                         if (has_orco==1) {
1349                                 ostr << "\t\t\t<p x=\"" << ver->accum
1350                                      << "\" y=\"" << ver->accum
1351                                      << "\" z=\"" << ver->accum << "\" />\n";
1352                         }
1353                         else if (has_orco==2) {
1354                                 orco = ver->orco;
1355                                 ostr << "\t\t\t<p x=\"" << orco[0]
1356                                      << "\" y=\"" << orco[1]
1357                                      << "\" z=\"" << orco[2] << "\" />\n";
1358                         }
1359                 }
1360                 if (vert_idx.find(vlr->v3)==vert_idx.end()) {
1361                         vert_idx[vlr->v3] = vidx++;
1362                         ver = vlr->v3;
1363                         MTC_cp3Float(ver->co, tvec);
1364                         MTC_Mat4MulVecfl(imat, tvec);
1365                         ostr << "\t\t\t<p x=\"" << tvec[0]
1366                                    << "\" y=\"" << tvec[1]
1367                                    << "\" z=\"" << tvec[2] << "\" />\n";
1368                         // has_orco now an int, if 1 -> strand mapping, if 2 -> normal orco mapping
1369                         if (has_orco==1) {
1370                                 ostr << "\t\t\t<p x=\"" << ver->accum
1371                                      << "\" y=\"" << ver->accum
1372                                      << "\" z=\"" << ver->accum << "\" />\n";
1373                         }
1374                         else if (has_orco==2) {
1375                                 orco = ver->orco;
1376                                 ostr << "\t\t\t<p x=\"" << orco[0]
1377                                      << "\" y=\"" << orco[1]
1378                                      << "\" z=\"" << orco[2] << "\" />\n";
1379                         }
1380                 }
1381                 if ((vlr->v4) && (vert_idx.find(vlr->v4)==vert_idx.end())) {
1382                         vert_idx[vlr->v4] = vidx++;
1383                         ver = vlr->v4;
1384                         MTC_cp3Float(ver->co, tvec);
1385                         MTC_Mat4MulVecfl(imat, tvec);
1386                         ostr << "\t\t\t<p x=\"" << tvec[0]
1387                                    << "\" y=\"" << tvec[1]
1388                                    << "\" z=\"" << tvec[2] << "\" />\n";
1389                         // has_orco now an int, if 1 -> strand mapping, if 2 -> normal orco mapping
1390                         if (has_orco==1) {
1391                                 ostr << "\t\t\t<p x=\"" << ver->accum
1392                                      << "\" y=\"" << ver->accum
1393                                      << "\" z=\"" << ver->accum << "\" />\n";
1394                         }
1395                         else if (has_orco==2) {
1396                                 orco = ver->orco;
1397                                 ostr << "\t\t\t<p x=\"" << orco[0]
1398                                      << "\" y=\"" << orco[1]
1399                                      << "\" z=\"" << orco[2] << "\" />\n";
1400                         }
1401                 }
1402                 xmlfile << ostr.str();
1403         }
1404         xmlfile << "\t\t</points>\n";
1405
1406         // all faces using the index list created above
1407         xmlfile << "\t\t<faces>\n";
1408         for (vector<VlakRen*>::const_iterator fci2=VLR_list.begin();
1409                                 fci2!=VLR_list.end();++fci2)
1410         {
1411                 VlakRen* vlr = *fci2;
1412                 Material* fmat = vlr->mat;
1413                 bool EXPORT_VCOL = ((fmat->mode & (MA_VERTEXCOL|MA_VERTEXCOLP))!=0);
1414                 string fmatname(fmat->id.name);
1415                 // use name in imgtex_shader list if 'TexFace' enabled for this face material
1416                 if (fmat->mode & MA_FACETEXTURE) {
1417                         MTFace* tface = RE_vlakren_get_tface(obr, vlr, obr->actmtface, NULL, 0);
1418                         if (tface) {
1419                                 Image* fimg = (Image*)tface->tpage;
1420                                 if (fimg) fmatname = imgtex_shader[fmatname + string(fimg->id.name)];
1421                         }
1422                 }
1423                 else if (fmatname.length()==0) fmatname = "blender_default";
1424         
1425                 int idx1 = vert_idx.find(vlr->v1)->second;
1426                 int idx2 = vert_idx.find(vlr->v2)->second;
1427                 int idx3 = vert_idx.find(vlr->v3)->second;
1428                 // make sure the indices point to the vertices when orco coords exported
1429                 if (has_orco) { idx1*=2;  idx2*=2;  idx3*=2; }
1430
1431                 ostr.str("");
1432                 ostr << "\t\t\t<f a=\"" << idx1 << "\" b=\"" << idx2 << "\" c=\"" << idx3 << "\"";
1433
1434                 // triangle uv and vcol indices
1435                 int ui1=0, ui2=1, ui3=2;
1436                 if (vlr->flag & R_DIVIDE_24) {
1437                         ui3++;
1438                         if (vlr->flag & R_FACE_SPLIT) { ui1++;  ui2++; }
1439                 }
1440                 else if (vlr->flag & R_FACE_SPLIT) { ui2++;  ui3++; }
1441
1442                 MTFace* uvc = RE_vlakren_get_tface(obr, vlr, obr->actmtface, NULL, 0); // possible uvcoords (v upside down)
1443                 if (uvc) {
1444                         ostr << " u_a=\"" << uvc->uv[ui1][0] << "\" v_a=\"" << 1-uvc->uv[ui1][1] << "\""
1445                              << " u_b=\"" << uvc->uv[ui2][0] << "\" v_b=\"" << 1-uvc->uv[ui2][1] << "\""
1446                              << " u_c=\"" << uvc->uv[ui3][0] << "\" v_c=\"" << 1-uvc->uv[ui3][1] << "\"";
1447                 }
1448
1449                 MCol *mcol= RE_vlakren_get_mcol(obr, vlr, obr->actmcol, NULL, 0);
1450
1451                 // since Blender seems to need vcols when uvs are used, for yafray only export when the material actually uses vcols
1452                 if ((EXPORT_VCOL) && mcol) {
1453                         // vertex colors
1454                         unsigned char* pt = reinterpret_cast<unsigned char*>(&mcol[ui1]);
1455                         ostr << " vcol_a_r=\"" << (float)pt[3]/255.f << "\" vcol_a_g=\"" << (float)pt[2]/255.f
1456                              << "\" vcol_a_b=\"" << (float)pt[1]/255.f << "\"";
1457                         pt = reinterpret_cast<unsigned char*>(&mcol[ui2]);
1458                         ostr << " vcol_b_r=\"" << (float)pt[3]/255.f << "\" vcol_b_g=\"" << (float)pt[2]/255.f
1459                              << "\" vcol_b_b=\"" << (float)pt[1]/255.f << "\"";
1460                         pt = reinterpret_cast<unsigned char*>(&mcol[ui3]);
1461                         ostr << " vcol_c_r=\"" << (float)pt[3]/255.f << "\" vcol_c_g=\"" << (float)pt[2]/255.f
1462                              << "\" vcol_c_b=\"" << (float)pt[1]/255.f << "\"";
1463                 }
1464                 ostr << " shader_name=\"" << fmatname << "\" />\n";
1465
1466                 if (vlr->v4) {
1467
1468                         idx1 = vert_idx.find(vlr->v3)->second;
1469                         idx2 = vert_idx.find(vlr->v4)->second;
1470                         idx3 = vert_idx.find(vlr->v1)->second;
1471
1472                         // make sure the indices point to the vertices when orco coords exported
1473                         if (has_orco) { idx1*=2;  idx2*=2;  idx3*=2; }
1474
1475                         ostr << "\t\t\t<f a=\"" << idx1 << "\" b=\"" << idx2 << "\" c=\"" << idx3 << "\"";
1476
1477                         // increment uv & vcol indices
1478                         ui1 = (ui1+2) & 3;
1479                         ui2 = (ui2+2) & 3;
1480                         ui3 = (ui3+2) & 3;
1481
1482                         if (uvc) {
1483                                 ostr << " u_a=\"" << uvc->uv[ui1][0] << "\" v_a=\"" << 1-uvc->uv[ui1][1] << "\""
1484                                      << " u_b=\"" << uvc->uv[ui2][0] << "\" v_b=\"" << 1-uvc->uv[ui2][1] << "\""
1485                                      << " u_c=\"" << uvc->uv[ui3][0] << "\" v_c=\"" << 1-uvc->uv[ui3][1] << "\"";
1486                         }
1487                         if ((EXPORT_VCOL) && mcol) {
1488                                 // vertex colors
1489                                 unsigned char* pt = reinterpret_cast<unsigned char*>(&mcol[ui1]);
1490                                 ostr << " vcol_a_r=\"" << (float)pt[3]/255.f << "\" vcol_a_g=\"" << (float)pt[2]/255.f
1491                                      << "\" vcol_a_b=\"" << (float)pt[1]/255.f << "\"";
1492                                 pt = reinterpret_cast<unsigned char*>(&mcol[ui2]);
1493                                 ostr << " vcol_b_r=\"" << (float)pt[3]/255.f << "\" vcol_b_g=\"" << (float)pt[2]/255.f
1494                                      << "\" vcol_b_b=\"" << (float)pt[1]/255.f << "\"";
1495                                 pt = reinterpret_cast<unsigned char*>(&mcol[ui3]);
1496                                 ostr << " vcol_c_r=\"" << (float)pt[3]/255.f << "\" vcol_c_g=\"" << (float)pt[2]/255.f
1497                                      << "\" vcol_c_b=\"" << (float)pt[1]/255.f << "\"";
1498                         }
1499                         ostr << " shader_name=\"" << fmatname << "\" />\n";
1500
1501                 }
1502                 xmlfile << ostr.str();
1503         }
1504         xmlfile << "\t\t</faces>\n\t</mesh>\n</object>\n</transform>\n\n";
1505 }
1506
1507
1508 // write all objects
1509 void yafrayFileRender_t::writeAllObjects()
1510 {
1511
1512         // first all objects except dupliverts (and main instance object for dups)
1513         for (map<Object*, yafrayObjectRen >::const_iterator obi=all_objects.begin();
1514                         obi!=all_objects.end(); ++obi)
1515         {
1516                 // skip main duplivert object if in dupliMtx_list, written later
1517                 Object* obj = obi->first;
1518                 if (dupliMtx_list.find(string(obj->id.name))!=dupliMtx_list.end()) continue;
1519                 writeObject(obj, obi->second.obr, obi->second.faces, obj->obmat);
1520         }
1521
1522         // Now all duplivert objects (if any) as instances of main object
1523         // The original object has been included in the VlakRen renderlist above (see convertBlenderScene.c)
1524         // but is written here which all other duplis are instances of.
1525         float obmat[4][4], cmat[4][4], imat[4][4], nmat[4][4];
1526         for (map<string, vector<float> >::const_iterator dupMtx=dupliMtx_list.begin();
1527                 dupMtx!=dupliMtx_list.end();++dupMtx) {
1528
1529                 // original inverse matrix, not actual matrix of object, but first duplivert.
1530                 
1531                 for (int i=0;i<4;i++)
1532                         for (int j=0;j<4;j++)
1533                                 obmat[i][j] = dupMtx->second[(i<<2)+j];
1534
1535                 MTC_Mat4Invert(imat, obmat);
1536
1537                 // first object written as normal (but with transform of first duplivert)
1538                 Object* obj = dup_srcob[dupMtx->first];
1539                 writeObject(obj, all_objects[obj].obr, all_objects[obj].faces, obmat);
1540
1541                 // all others instances of first
1542                 for (unsigned int curmtx=16;curmtx<dupMtx->second.size();curmtx+=16) {  // number of 4x4 matrices
1543
1544                         // new mtx
1545                         for (int i=0;i<4;i++)
1546                                 for (int j=0;j<4;j++)
1547                                         nmat[i][j] = dupMtx->second[curmtx+(i<<2)+j];
1548
1549                         MTC_Mat4MulMat4(cmat, imat, nmat);      // transform with respect to original = inverse_original * new
1550
1551                         ostr.str("");
1552                         // yafray matrix = transpose of Blender
1553                         ostr << "<transform m00=\"" << cmat[0][0] << "\" m01=\"" << cmat[1][0]
1554                                          <<         "\" m02=\"" << cmat[2][0] << "\" m03=\"" << cmat[3][0] << "\"\n";
1555                         ostr << "           m10=\"" << cmat[0][1] << "\" m11=\"" << cmat[1][1]
1556                                          <<         "\" m12=\"" << cmat[2][1] << "\" m13=\"" << cmat[3][1] << "\"\n";
1557                         ostr << "           m20=\"" << cmat[0][2] << "\" m21=\"" << cmat[1][2]
1558                                          <<         "\" m22=\"" << cmat[2][2] << "\" m23=\"" << cmat[3][2] << "\"\n";
1559                         ostr << "           m30=\"" << cmat[0][3] << "\" m31=\"" << cmat[1][3]
1560                                          <<         "\" m32=\"" << cmat[2][3] << "\" m33=\"" << cmat[3][3] << "\">\n";
1561                         xmlfile << ostr.str();
1562
1563                         // new name from original
1564                         ostr.str("");
1565                         ostr << "<object name=\"" << obj->id.name << "_dup" << (curmtx>>4) << "\" original=\"" << obj->id.name << "\" >\n";
1566                         xmlfile << ostr.str();
1567                         xmlfile << "\t<attributes>\n\t</attributes>\n\t<null/>\n</object>\n</transform>\n\n";
1568
1569                 }
1570
1571         }
1572
1573 }
1574
1575 void yafrayFileRender_t::writeAreaLamp(LampRen* lamp, int num, float iview[4][4])
1576 {
1577         if (lamp->area_shape!=LA_AREA_SQUARE) return;
1578         float *a=lamp->area[0], *b=lamp->area[1], *c=lamp->area[2], *d=lamp->area[3];
1579         float power=lamp->energy;
1580         
1581         ostr.str("");
1582         string md = "off";
1583         // if no GI used, the GIphotons flag can still be set, so only use when 'full' selected
1584         if ((re->r.GImethod==2) && (re->r.GIphotons)) { md="on";  power*=re->r.GIpower; }
1585         ostr << "<light type=\"arealight\" name=\"LAMP" << num+1 << "\" dummy=\""<< md << "\" power=\"" << power << "\" ";
1586         // samples not used for GI with photons, can still be exported, is ignored
1587         int psm=0, sm = lamp->ray_totsamp;
1588         if (sm>=25) psm = sm/5;
1589         ostr << "samples=\"" << sm << "\" psamples=\"" << psm << "\" ";
1590         ostr << ">\n";
1591         
1592         // transform area lamp coords back to world
1593         float lpco[4][3];
1594         MTC_cp3Float(a, lpco[0]);
1595         MTC_Mat4MulVecfl(iview, lpco[0]);
1596         MTC_cp3Float(b, lpco[1]);
1597         MTC_Mat4MulVecfl(iview, lpco[1]);
1598         MTC_cp3Float(c, lpco[2]);
1599         MTC_Mat4MulVecfl(iview, lpco[2]);
1600         MTC_cp3Float(d, lpco[3]);
1601         MTC_Mat4MulVecfl(iview, lpco[3]);
1602         ostr << "\t<a x=\""<< lpco[0][0] <<"\" y=\""<< lpco[0][1] <<"\" z=\"" << lpco[0][2] <<"\" />\n";
1603         ostr << "\t<b x=\""<< lpco[1][0] <<"\" y=\""<< lpco[1][1] <<"\" z=\"" << lpco[1][2] <<"\" />\n";
1604         ostr << "\t<c x=\""<< lpco[2][0] <<"\" y=\""<< lpco[2][1] <<"\" z=\"" << lpco[2][2] <<"\" />\n";
1605         ostr << "\t<d x=\""<< lpco[3][0] <<"\" y=\""<< lpco[3][1] <<"\" z=\"" << lpco[3][2] <<"\" />\n";
1606
1607         ostr << "\t<color r=\"" << lamp->r << "\" g=\"" << lamp->g << "\" b=\"" << lamp->b << "\" />\n";
1608         ostr << "</light>\n\n";
1609         xmlfile << ostr.str();
1610 }
1611
1612 void yafrayFileRender_t::writeLamps()
1613 {
1614         GroupObject *go;
1615         int i=0;
1616         
1617         // inverse viewmatrix needed for back2world transform
1618         float iview[4][4];
1619         // re->viewinv != inv.re->viewmat because of possible ortho mode (see convertBlenderScene.c)
1620         // have to invert it here
1621         MTC_Mat4Invert(iview, re->viewmat);
1622         
1623         // all lamps
1624         for(go=(GroupObject *)re->lights.first; go; go= go->next, i++) {
1625                 LampRen* lamp = (LampRen *)go->lampren;
1626
1627                 ostr.str("");
1628                 
1629                 if (lamp->type==LA_AREA) { writeAreaLamp(lamp, i, iview);  continue; }
1630                 
1631                 // TODO: add decay setting in yafray
1632                 ostr << "<light type=\"";
1633                 bool is_softL=false, is_sphereL=false;
1634                 if (lamp->type==LA_LOCAL) {
1635                         if (lamp->mode & LA_YF_SOFT) {
1636                                 // shadowmapped omnidirectional light
1637                                 ostr << "softlight\"";
1638                                 is_softL = true;
1639                         }
1640                         else if ((lamp->mode & LA_SHAD_RAY) && (lamp->YF_ltradius>0.0)) {
1641                                 // area sphere, only when ray shadows enabled and radius>0.0
1642                                 ostr << "spherelight\"";
1643                                 is_sphereL = true;
1644                         }
1645                         else ostr << "pointlight\"";
1646                         ostr << " glow_intensity=\"" << lamp->YF_glowint << "\" glow_offset=\"" << lamp->YF_glowofs
1647                                          << "\" glow_type=\"" << lamp->YF_glowtype << "\"";
1648                 }
1649                 else if (lamp->type==LA_SPOT)
1650                         ostr << "spotlight\"";
1651                 else if ((lamp->type==LA_SUN) || (lamp->type==LA_HEMI)) // hemi exported as sun
1652                         ostr << "sunlight\"";
1653                 else if (lamp->type==LA_YF_PHOTON)
1654                         ostr << "photonlight\"";
1655                 else {
1656                         // possibly unknown type, ignore
1657                         cout << "Unknown Blender lamp type: " << lamp->type << endl;
1658                         continue;
1659                 }
1660                 
1661                 //no name available here, create one
1662                 ostr << " name=\"LAMP" << i+1;
1663                 // color already premultiplied by energy, so only need distance here
1664                 float pwr = 1;  // default for sun/hemi, distance irrelevant
1665                 if ((lamp->type!=LA_SUN) && (lamp->type!=LA_HEMI)) {
1666                         if (lamp->mode & LA_SPHERE) {
1667                                 // best approx. as used in LFexport script (LF d.f.m. 4pi?)
1668                                 pwr = lamp->dist*(lamp->dist+1)*(0.25/M_PI);
1669                                 //decay = 2;
1670                         }
1671                         else {
1672                                 pwr = lamp->dist;
1673                                 //decay = 1;
1674                         }
1675                 }
1676
1677                 if (is_sphereL) {
1678                         // 'dummy' mode for spherelight when used with gpm
1679                         string md = "off";
1680                         // if no GI used, the GIphotons flag can still be set, so only use when 'full' selected
1681                         if ((re->r.GImethod==2) && (re->r.GIphotons)) { md="on";  pwr*=re->r.GIpower; }
1682                         ostr << "\" power=\"" <<  pwr << "\" dummy=\"" << md << "\"";
1683                 }
1684                 else ostr << "\" power=\"" << pwr << "\"";
1685                 
1686                 // cast_shadows flag not used with softlight, spherelight or photonlight
1687                 if ((!is_softL) && (!is_sphereL) && (lamp->type!=LA_YF_PHOTON)) {
1688                         string lpmode="off";
1689                         // Blender hemilights exported as sunlights which might have shadow flag set
1690                         // should have cast_shadows set to off (reported by varuag)
1691                         if (lamp->type!=LA_HEMI) {
1692                                 if (re->r.mode & R_SHADOW) {
1693                                         // old bug was here since the yafray lamp settings panel was added,
1694                                         // blender spotlight shadbuf flag should be ignored, since it is not in the panel anymore
1695                                         if (lamp->mode & LA_SHAD_RAY) lpmode="on";
1696                                 }
1697                         }
1698                         ostr << " cast_shadows=\"" << lpmode << "\"";
1699                 }
1700
1701                 
1702                 // spot specific stuff
1703                 bool has_halo = ((lamp->type==LA_SPOT) && (lamp->mode & LA_HALO) && (lamp->haint>0.0));
1704                 if (lamp->type==LA_SPOT) {
1705                         // conversion already changed spotsize to cosine of half angle
1706                         float ld = 1-lamp->spotsi;      //convert back to blender slider setting
1707                         if (ld!=0) ld = 1.f/ld;
1708                         ostr    << " size=\"" << acos(lamp->spotsi)*180.0/M_PI << "\""
1709                                                 << " blend=\"" << lamp->spotbl*ld << "\""
1710                                                 << " beam_falloff=\"2\"";       // no Blender equivalent (yet)
1711                         // halo params
1712                         if (has_halo) {
1713                                 ostr << "\n\thalo=\"on\" " << "res=\"" << lamp->YF_bufsize << "\"\n";
1714                                 int hsmp = ((12-lamp->shadhalostep)*16)/12;
1715                                 hsmp = (hsmp+1)*16;     // makes range (16, 272) for halostep(12, 0), good enough?
1716                                 // halo 'samples' now 'stepsize'
1717                                 // convert from old integer samples value to some reasonable stepsize
1718                                 ostr << "\tstepsize=\"" << (1.0/sqrt((float)hsmp)) <<  "\" shadow_samples=\"" << (lamp->samp*lamp->samp) << "\"\n";
1719                                 ostr << "\thalo_blur=\"0\" shadow_blur=\"" << (lamp->soft*0.01f) << "\"\n";
1720                                 ostr << "\tfog_density=\"" << (lamp->haint*0.2f) << "\"";
1721                         }
1722                 }
1723                 else if (is_softL) {
1724                         // softlight
1725                         ostr    << " res=\"" << lamp->YF_bufsize << "\""
1726                                                 << " radius=\"" << lamp->soft << "\""
1727                                                 << " bias=\"" << lamp->bias << "\"";
1728                 }
1729                 else if (is_sphereL) {
1730                         // spherelight
1731                         int psm=0, sm = lamp->ray_samp*lamp->ray_samp;
1732                         if (sm>=25) psm = sm/5;
1733                         ostr    << " radius=\"" << lamp->YF_ltradius << "\""
1734                                                 << " samples=\"" << sm << "\""
1735                                                 << " psamples=\"" << psm << "\""
1736                                                 << " qmc_method=\"1\"";
1737                 }
1738                 else if (lamp->type==LA_YF_PHOTON) {
1739                         string qmc="off";
1740                         if (lamp->YF_useqmc) qmc="on";
1741                         ostr    << "\n\tphotons=\"" << lamp->YF_numphotons << "\""
1742                                                 << " search=\"" << lamp->YF_numsearch << "\""
1743                                                 << " depth=\"" << lamp->YF_phdepth << "\""
1744                                                 << " use_QMC=\"" << qmc << "\""
1745                                                 << " angle=\"" << acos(lamp->spotsi)*180.0/M_PI << "\"";
1746                         float cl = lamp->YF_causticblur/sqrt((float)lamp->YF_numsearch);
1747                         ostr    << "\n\tfixedradius=\"" << lamp->YF_causticblur << "\" cluster=\"" << cl << "\"";
1748                 }
1749                 ostr << " >\n";
1750
1751                 // transform lamp co & vec back to world
1752                 float lpco[3], lpvec[3];
1753                 MTC_cp3Float(lamp->co, lpco);
1754                 MTC_Mat4MulVecfl(iview, lpco);
1755                 MTC_cp3Float(lamp->vec, lpvec);
1756                 MTC_Mat4Mul3Vecfl(iview, lpvec);
1757
1758                 // position, (==-blendir for sun/hemi)
1759                 if ((lamp->type==LA_SUN) || (lamp->type==LA_HEMI))
1760                         ostr << "\t<from x=\"" << -lpvec[0] << "\" y=\"" << -lpvec[1] << "\" z=\"" << -lpvec[2] << "\" />\n";
1761                 else
1762                         ostr << "\t<from x=\"" << lpco[0] << "\" y=\"" << lpco[1] << "\" z=\"" << lpco[2] << "\" />\n";         
1763                 // 'to' for spot/photonlight, already calculated by Blender
1764                 if ((lamp->type==LA_SPOT) || (lamp->type==LA_YF_PHOTON)) {
1765                         ostr << "\t<to x=\"" << lpco[0] + lpvec[0]
1766                                                         << "\" y=\"" << lpco[1] + lpvec[1]
1767                                                         << "\" z=\"" << lpco[2] + lpvec[2] << "\" />\n";
1768                         if (has_halo) ostr << "\t<fog r=\"1\" g=\"1\" b=\"1\" />\n";
1769                 }
1770
1771                 // color
1772                 // rgb in LampRen is premultiplied by energy, power is compensated for that above
1773                 ostr << "\t<color r=\"" << lamp->r << "\" g=\"" << lamp->g << "\" b=\"" << lamp->b << "\" />\n";
1774                 ostr << "</light>\n\n";
1775                 xmlfile << ostr.str();
1776         }
1777 }
1778
1779 // write main camera
1780 void yafrayFileRender_t::writeCamera()
1781 {
1782         // here Global used again
1783         ostr.str("");
1784         ostr << "<camera name=\"MAINCAM\" ";
1785         if (re->r.mode & R_ORTHO)
1786                 ostr << "type=\"ortho\"";
1787         else    
1788                 ostr << "type=\"perspective\"";
1789
1790         // render resolution including the percentage buttons
1791         ostr << " resx=\"" << re->winx << "\" resy=\"" << re->winy << "\"";
1792
1793         float f_aspect = 1;
1794         if ((re->winx * re->r.xasp) <= (re->winy * re->r.yasp))
1795                 f_aspect = float(re->winx * re->r.xasp) / float(re->winy * re->r.yasp);
1796         ostr << "\n\tfocal=\"" << mainCamLens/(f_aspect*32.f);
1797         // bug #4532, when field rendering is enabled, ycor is doubled
1798         if (re->r.mode & R_FIELDS)
1799                 ostr << "\" aspect_ratio=\"" << (re->ycor * 0.5f) << "\"";
1800         else
1801                 ostr << "\" aspect_ratio=\"" << re->ycor << "\"";
1802
1803
1804         // dof params, only valid for real camera
1805         float fdist = 1;        // only changes for ortho
1806         if (maincam_obj->type==OB_CAMERA) {
1807                 Camera* cam = (Camera*)maincam_obj->data;
1808                 if (re->r.mode & R_ORTHO) fdist = cam->ortho_scale*(mainCamLens/32.f);
1809                 ostr << "\n\tdof_distance=\"" << cam->YF_dofdist << "\"";
1810                 ostr << " aperture=\"" << cam->YF_aperture << "\"";
1811                 string st = "on";
1812                 if (cam->flag & CAM_YF_NO_QMC) st = "off";
1813                 ostr << " use_qmc=\"" << st << "\"";
1814                 // bokeh params
1815                 st = "disk1";
1816                 if (cam->YF_bkhtype==1)
1817                         st = "disk2";
1818                 else if (cam->YF_bkhtype==2)
1819                         st = "triangle";
1820                 else if (cam->YF_bkhtype==3)
1821                         st = "square";
1822                 else if (cam->YF_bkhtype==4)
1823                         st = "pentagon";
1824                 else if (cam->YF_bkhtype==5)
1825                         st = "hexagon";
1826                 else if (cam->YF_bkhtype==6)
1827                         st = "ring";
1828                 ostr << "\n\tbokeh_type=\"" << st << "\"";
1829                 st = "uniform";
1830                 if (cam->YF_bkhbias==1)
1831                         st = "center";
1832                 else if (cam->YF_bkhbias==2)
1833                         st = "edge";
1834                 ostr << " bokeh_bias=\"" << st << "\"";
1835                 ostr << " bokeh_rotation=\"" << cam->YF_bkhrot << "\"";
1836         }
1837
1838         ostr << " >\n";
1839         xmlfile << ostr.str();
1840
1841         ostr.str("");
1842         ostr << "\t<from x=\"" << maincam_obj->obmat[3][0] << "\""
1843                                                         << " y=\"" << maincam_obj->obmat[3][1] << "\""
1844                                                         << " z=\"" << maincam_obj->obmat[3][2] << "\" />\n";
1845         ostr << "\t<to x=\"" << maincam_obj->obmat[3][0] - fdist * re->viewmat[0][2]
1846                                         << "\" y=\"" << maincam_obj->obmat[3][1] - fdist * re->viewmat[1][2]
1847                                         << "\" z=\"" << maincam_obj->obmat[3][2] - fdist * re->viewmat[2][2] << "\" />\n";
1848         ostr << "\t<up x=\"" << maincam_obj->obmat[3][0] + re->viewmat[0][1]
1849                                         << "\" y=\"" << maincam_obj->obmat[3][1] + re->viewmat[1][1]
1850                                         << "\" z=\"" << maincam_obj->obmat[3][2] + re->viewmat[2][1] << "\" />\n";
1851         xmlfile << ostr.str();
1852
1853         xmlfile << "</camera>\n\n";
1854 }
1855
1856 void yafrayFileRender_t::writeHemilight()
1857 {
1858         World *world = G.scene->world;
1859         bool fromAO = false;
1860         if (re->r.GIquality==6){
1861                 // use Blender AO params is possible
1862                 if (world==NULL) return;
1863                 if ((world->mode & WO_AMB_OCC)==0) {
1864                         // no AO, use default GIquality
1865                         cout << "No ambient occlusion enabled\nUsing defaults of 25 samples & infinite distance instead" << endl;
1866                 }
1867                 else fromAO = true;
1868         }
1869         ostr.str("");
1870         if (re->r.GIcache) {
1871                 ostr << "<light type=\"pathlight\" name=\"path_LT\" power=\"" << re->r.GIpower << "\" mode=\"occlusion\"";
1872                 ostr << "\n\tcache=\"on\" use_QMC=\"on\" threshold=\"" << re->r.GIrefinement << "\" "
1873                                  << "cache_size=\"" << ((2.0/float(re->winx))*re->r.GIpixelspersample) << "\"";
1874                 ostr << "\n\tshadow_threshold=\"" << (1.0-re->r.GIshadowquality) << "\" grid=\"82\" search=\"35\"";
1875                 ostr << "\n\tignore_bumpnormals=\"" << (re->r.YF_nobump ? "on" : "off") << "\"";
1876                 if (fromAO) {
1877                         // for AO, with cache, using range of 32*1 to 32*16 seems good enough
1878                         ostr << "\n\tsamples=\"" << 32*world->aosamp << "\" maxdistance=\"" << world->aodist << "\" >\n";
1879                 }
1880                 else {
1881                         switch (re->r.GIquality)
1882                         {
1883                                 case 1 : ostr << " samples=\"128\" >\n";  break;
1884                                 case 2 : ostr << " samples=\"256\" >\n";  break;
1885                                 case 3 : ostr << " samples=\"512\" >\n";  break;
1886                                 case 4 : ostr << " samples=\"1024\" >\n"; break;
1887                                 case 5 : ostr << " samples=\"2048\" >\n"; break;
1888                                 default: ostr << " samples=\"256\" >\n";
1889                         }
1890                 }
1891         }
1892         else {
1893                 ostr << "<light type=\"hemilight\" name=\"hemi_LT\" power=\"" << re->r.GIpower << "\"";
1894                 if (fromAO) {
1895                         // use minimum of 4 samples for lowest sample setting, single sample way too noisy
1896                         ostr << "\n\tsamples=\"" << 3 + world->aosamp*world->aosamp
1897                                          << "\" maxdistance=\"" << world->aodist
1898                                          << "\" use_QMC=\"" << ((world->aomode & WO_AORNDSMP) ? "off" : "on") << "\" >\n";
1899                 }
1900                 else {
1901                         switch (re->r.GIquality)
1902                         {
1903                                 case 1 :
1904                                 case 2 : ostr << " samples=\"16\" >\n";  break;
1905                                 case 3 : ostr << " samples=\"36\" >\n";  break;
1906                                 case 4 : ostr << " samples=\"64\" >\n";  break;
1907                                 case 5 : ostr << " samples=\"128\" >\n";  break;
1908                                 default: ostr << " samples=\"25\" >\n";
1909                         }
1910                 }
1911         }
1912         ostr << "</light>\n\n";
1913         xmlfile << ostr.str();
1914 }
1915
1916 void yafrayFileRender_t::writePathlight()
1917 {
1918         ostr.str("");
1919         if (re->r.GIphotons)
1920         {
1921                 ostr << "<light type=\"globalphotonlight\" name=\"gpm\" photons=\"" << re->r.GIphotoncount << "\"" << endl;
1922                 ostr << "\tradius=\"" << re->r.GIphotonradius << "\" depth=\"" << ((re->r.GIdepth>2) ? (re->r.GIdepth-1) : 1)
1923                                  << "\" caus_depth=\"" << re->r.GIcausdepth << "\" search=\"" << re->r.GImixphotons << "\" >"<<endl;
1924                 ostr << "</light>"<<endl;
1925         }
1926         ostr << "<light type=\"pathlight\" name=\"path_LT\" power=\"" << re->r.GIindirpower << "\"";
1927         ostr << " depth=\"" << ((re->r.GIphotons) ? 1 : re->r.GIdepth) << "\" caus_depth=\"" << re->r.GIcausdepth <<"\"\n";
1928         if (re->r.GIdirect && re->r.GIphotons) ostr << "direct=\"on\"" << endl;
1929         if (re->r.GIcache && !(re->r.GIdirect && re->r.GIphotons))
1930         {
1931                 switch (re->r.GIquality)
1932                 {
1933                         case 1 : ostr << " samples=\"128\" \n";   break;
1934                         case 2 : ostr << " samples=\"256\" \n";   break;
1935                         case 3 : ostr << " samples=\"512\" \n";   break;
1936                         case 4 : ostr << " samples=\"1024\" \n";  break;
1937                         case 5 : ostr << " samples=\"2048\" \n";  break;
1938                         default: ostr << " samples=\"512\" \n";
1939                 }
1940                 ostr << " cache=\"on\" use_QMC=\"on\" threshold=\"" << re->r.GIrefinement << "\"" << endl;
1941                 ostr << "\tignore_bumpnormals=\"" << (re->r.YF_nobump ? "on" : "off") << "\"\n";
1942                 float sbase = 2.0/float(re->winx);
1943                 ostr << "\tcache_size=\"" << sbase*re->r.GIpixelspersample << "\" shadow_threshold=\"" <<
1944                         1.0-re->r.GIshadowquality << "\" grid=\"82\" search=\"35\" >\n";
1945         }
1946         else
1947         {
1948                 switch (re->r.GIquality)
1949                 {
1950                         case 1 : ostr << " samples=\"16\" >\n";   break;
1951                         case 2 : ostr << " samples=\"36\" >\n";   break;
1952                         case 3 : ostr << " samples=\"64\" >\n";   break;
1953                         case 4 : ostr << " samples=\"128\" >\n";  break;
1954                         case 5 : ostr << " samples=\"256\" >\n";  break;
1955                         default: ostr << " samples=\"25\" >\n";
1956                 }
1957         }
1958         ostr << "</light>\n\n";
1959         xmlfile << ostr.str();
1960 }
1961
1962 bool yafrayFileRender_t::writeWorld()
1963 {
1964         World *world = G.scene->world;
1965         if (re->r.GIquality!=0) {
1966                 if (re->r.GImethod==1) {
1967                         if (world==NULL) cout << "WARNING: need world background for skydome!\n";
1968                         writeHemilight();
1969                 }
1970                 else if (re->r.GImethod==2) writePathlight();
1971         }
1972
1973         if (world==NULL) return false;
1974
1975         for (int i=0;i<MAX_MTEX;i++) {
1976                 MTex* wtex = world->mtex[i];
1977                 if (!wtex) continue;
1978                 Image* wimg = wtex->tex->ima;
1979                 // now always exports if image used as world texture (and 'Hori' mapping enabled)
1980                 if ((wtex->tex->type==TEX_IMAGE) && (wimg!=NULL) && (wtex->mapto & WOMAP_HORIZ)) {
1981                         string wt_path = wimg->name;
1982                         adjustPath(wt_path);
1983                         ostr.str("");
1984                         ostr << "<background type=\"image\" name=\"world_background\" ";
1985                         // exposure_adjust not restricted to integer range anymore
1986                         ostr << "exposure_adjust=\"" << wtex->tex->bright-1.f << "\"";
1987                         if (wtex->texco & TEXCO_ANGMAP)
1988                                 ostr << " mapping=\"probe\" >\n";
1989                         else if (wtex->texco & TEXCO_H_SPHEREMAP)       // in yafray full sphere
1990                                 ostr << " mapping=\"sphere\" >\n";
1991                         else    // assume 'tube' for anything else
1992                                 ostr << " mapping=\"tube\" >\n";
1993                         ostr << "\t<filename value=\"" << wt_path << "\" />\n";
1994                         ostr << "\t<interpolate value=\"" << ((wtex->tex->imaflag & TEX_INTERPOL) ? "bilinear" : "none") << "\" />\n";
1995                         if (wtex->tex->filtersize>1.f) ostr << "\t<prefilter value=\"on\" />\n";
1996                         ostr << "</background>\n\n";
1997                         xmlfile << ostr.str();
1998                         return true;
1999                 }
2000         }
2001
2002         ostr.str("");
2003         ostr << "<background type=\"constant\" name=\"world_background\" >\n";
2004         // if no GI used, the GIpower parameter is not always initialized, so in that case ignore it
2005         // (have to change method to init yafray vars in Blender)
2006         float bg_mult = (re->r.GImethod==0) ? 1 : re->r.GIpower;
2007         ostr << "\t<color r=\"" << (world->horr * bg_mult) << 
2008                                                                 "\" g=\"" << (world->horg * bg_mult) << 
2009                                                                 "\" b=\"" << (world->horb * bg_mult) << "\" />\n";
2010         ostr << "</background>\n\n";
2011         xmlfile << ostr.str();
2012
2013         return true;
2014 }
2015
2016 bool yafrayFileRender_t::executeYafray(const string &xmlpath)
2017 {
2018         ostr.str("");
2019         if (re->r.mode & R_BORDER) {
2020                 ostr << command_path << "yafray -c " << re->r.threads
2021                      << " -r " << (2.f*re->r.border.xmin - 1.f)
2022                      << ":"    << (2.f*re->r.border.xmax - 1.f)
2023                      << ":"    << (2.f*re->r.border.ymin - 1.f)
2024                      << ":"    << (2.f*re->r.border.ymax - 1.f)
2025                      << " \"" << xmlpath << "\"";
2026         }
2027         else
2028                 ostr << command_path << "yafray -c " << re->r.threads << " \"" << xmlpath << "\"";
2029         
2030         string command = ostr.str();
2031         cout << "COMMAND: " << command << endl;
2032 #ifndef WIN32
2033         sigset_t yaf,old;
2034         sigemptyset(&yaf);
2035         sigaddset(&yaf, SIGVTALRM);
2036         sigprocmask(SIG_BLOCK, &yaf, &old);
2037         int ret=system(command.c_str());
2038         sigprocmask(SIG_SETMASK, &old, NULL);
2039         if (WIFEXITED(ret))
2040         {
2041                 if (WEXITSTATUS(ret)) cout<<"Executed -"<<command<<"-"<<endl;
2042                 switch (WEXITSTATUS(ret))
2043                 {
2044                         case 0: cout << "Yafray completed successfully\n";  return true;
2045                         case 127: cout << "Yafray not found\n";  return false;
2046                         case 126: cout << "Yafray: permission denied\n";  return false;
2047                         default: cout << "Yafray exited with errors\n";  return false;
2048                 }
2049         }
2050         else if (WIFSIGNALED(ret))
2051                 cout << "Yafray crashed\n";
2052         else
2053                 cout << "Unknown error\n";
2054         return false;
2055 #else
2056         int ret=system(command.c_str());
2057         return ret==0;
2058 #endif
2059         
2060 }