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