Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/yafray/YafRay_Api.h2
-rwxr-xr-xsource/blender/yafray/intern/api.cpp15
-rwxr-xr-xsource/blender/yafray/intern/export_File.cpp1156
-rwxr-xr-xsource/blender/yafray/intern/export_File.h33
-rw-r--r--source/blender/yafray/intern/yafray_Render.cpp1165
-rw-r--r--source/blender/yafray/intern/yafray_Render.h90
6 files changed, 1258 insertions, 1203 deletions
diff --git a/source/blender/yafray/YafRay_Api.h b/source/blender/yafray/YafRay_Api.h
index f36a0b3df0d..b6c0ad03651 100644
--- a/source/blender/yafray/YafRay_Api.h
+++ b/source/blender/yafray/YafRay_Api.h
@@ -6,7 +6,7 @@
extern "C" {
#endif
int YAF_exportScene();
-void YAF_displayImage();
+//void YAF_displayImage();
void YAF_addDupliMtx(Object* obj);
int YAF_objectKnownData(Object* obj);
#ifdef __cplusplus
diff --git a/source/blender/yafray/intern/api.cpp b/source/blender/yafray/intern/api.cpp
new file mode 100755
index 00000000000..c484a881641
--- /dev/null
+++ b/source/blender/yafray/intern/api.cpp
@@ -0,0 +1,15 @@
+#include "export_File.h"
+
+static yafrayFileRender_t byfile;
+
+yafrayRender_t *YAFBLEND=&byfile;
+
+extern "C"
+{
+
+int YAF_exportScene() { return (int)YAFBLEND->exportScene(); }
+//void YAF_displayImage() { YAFBLEND->displayImage(); }
+void YAF_addDupliMtx(Object* obj) { YAFBLEND->addDupliMtx(obj); }
+int YAF_objectKnownData(Object* obj) { return (int)YAFBLEND->objectKnownData(obj); }
+
+}
diff --git a/source/blender/yafray/intern/export_File.cpp b/source/blender/yafray/intern/export_File.cpp
new file mode 100755
index 00000000000..ed43216f0f3
--- /dev/null
+++ b/source/blender/yafray/intern/export_File.cpp
@@ -0,0 +1,1156 @@
+#include"export_File.h"
+
+#include <math.h>
+
+using namespace std;
+
+#ifdef WIN32
+
+#include<windows.h>
+
+#ifndef FILE_MAXDIR
+#define FILE_MAXDIR 160
+#endif
+
+#ifndef FILE_MAXFILE
+#define FILE_MAXFILE 80
+#endif
+
+static string command_path = "";
+
+static string find_path()
+{
+ HKEY hkey;
+ DWORD dwType, dwSize;
+
+ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,"Software\\YafRay Team\\YafRay",0,KEY_READ,&hkey)==ERROR_SUCCESS)
+ {
+ dwType = REG_EXPAND_SZ;
+ dwSize = MAX_PATH;
+ DWORD dwStat;
+
+ char *pInstallDir=new char[MAX_PATH];
+
+ dwStat=RegQueryValueEx(hkey, TEXT("InstallDir"),
+ NULL, NULL,(LPBYTE)pInstallDir, &dwSize);
+
+ if (dwStat == NO_ERROR)
+ {
+ string res=pInstallDir;
+ delete [] pInstallDir;
+ return res;
+ }
+ else
+ cout << "Couldn't READ \'InstallDir\' value. Is yafray correctly installed?\n";
+ delete [] pInstallDir;
+
+ RegCloseKey(hkey);
+ }
+ else
+ cout << "Couldn't FIND registry key for yafray, is it installed?\n";
+
+ return string("");
+
+}
+
+static int createDir(char* name)
+{
+ if (BLI_exists(name))
+ return 2; //exists
+ if (CreateDirectory((LPCTSTR)(name), NULL)) {
+ cout << "Directory: " << name << " created\n";
+ return 1; // created
+ }
+ else {
+ cout << "Could not create directory: " << name << endl;
+ return 0; // fail
+ }
+}
+
+#endif
+
+bool yafrayFileRender_t::initExport()
+{
+ xmlpath = "";
+ bool dir_failed = false;
+ // try the user setting setting first, export dir must be set and exist
+ if (strlen(U.yfexportdir)==0)
+ {
+ cout << "No export directory set in user defaults!\n";
+ dir_failed = true;
+ }
+ else
+ {
+ // check if it exists
+ if (!BLI_exists(U.yfexportdir)) {
+ cout << "YafRay temporary xml export directory:\n" << U.yfexportdir << "\ndoes not exist!\n";
+#ifdef WIN32
+ // try to create it
+ cout << "Trying to create...\n";
+ if (createDir(U.yfexportdir)==0) dir_failed=true; else dir_failed=false;
+#else
+ dir_failed = true;
+#endif
+ }
+ xmlpath = U.yfexportdir;
+ }
+
+#ifdef WIN32
+ // for windows try to get the path to the yafray binary from the registry, only done once
+ if (command_path=="")
+ {
+ char path[FILE_MAXDIR+FILE_MAXFILE];
+ string yafray_path = find_path();
+ if (yafray_path=="")
+ {
+ // error already printed in find_path()
+ clearAll();
+ return false;
+ }
+ GetShortPathName((LPCTSTR)(yafray_path.c_str()), path, FILE_MAXDIR+FILE_MAXFILE);
+ command_path = string(path);
+ cout << "yafray path found: " << command_path << endl;
+ }
+ // if no export dir set, or could not create, try to create one in the yafray dir, unless it already exists
+ if (dir_failed)
+ {
+ string ybdir = command_path + "\\YBtest";
+ if (createDir(const_cast<char*>(ybdir.c_str()))==0) dir_failed=true; else dir_failed=false;
+ xmlpath = ybdir;
+ }
+#endif
+
+ // for all
+ if (dir_failed) return false;
+
+#ifdef WIN32
+ string DLM = "\\";
+#else
+ string DLM = "/";
+#endif
+ if (xmlpath.find_last_of(DLM)!=(xmlpath.length()-1)) xmlpath += DLM;
+
+ imgout = xmlpath + "YBtest.tga";
+ xmlpath += "YBtest.xml";
+ xmlfile.open(xmlpath.c_str());
+ if (xmlfile.fail())
+ {
+ cout << "Could not open file\n";
+ return false;
+ }
+ ostr << setiosflags(ios::showpoint | ios::fixed);
+ xmlfile << "<scene>\n\n";
+ return true;
+}
+
+bool yafrayFileRender_t::writeRender()
+{
+ // finally export render block
+ ostr.str("");
+ ostr << "<render camera_name=\"MAINCAM\"\n";
+ ostr << "\traydepth=\"" << maxraydepth << "\" gamma=\"" << R.r.YF_gamma << "\" exposure=\"" << R.r.YF_exposure << "\"\n";
+
+ //if( (G.scene->world!=NULL) && (G.scene->world->GIquality>1) && ! G.scene->world->cache )
+ if ((R.r.GImethod!=0) && (R.r.GIquality>1) && (!R.r.GIcache))
+ ostr << "\tAA_passes=\"5\" AA_minsamples=\"5\" " << endl;
+ else if ((R.r.mode & R_OSA) && (R.r.osa)) {
+ int passes=(R.r.osa%4)==0 ? R.r.osa/4 : 1;
+ int minsamples=(R.r.osa%4)==0 ? 4 : R.r.osa;
+ ostr << "\tAA_passes=\"" << passes << "\" AA_minsamples=\"" << minsamples << "\"";
+ }
+ else ostr << "\tAA_passes=\"0\" AA_minsamples=\"1\"";
+
+ ostr << "\n";
+
+ if (hasworld) ostr << "\tbackground_name=\"world_background\"\n";
+
+ ostr << "\tAA_pixelwidth=\"2\" AA_threshold=\"0.06\" bias=\"0.0001\" >\n";
+
+ ostr << "\t<outfile value=\"" << imgout << "\" />\n";
+
+ ostr << "</render>\n\n";
+ xmlfile << ostr.str();
+ return true;
+}
+
+bool yafrayFileRender_t::finishExport()
+{
+ xmlfile << "</scene>\n";
+ xmlfile.close();
+
+ // file exported, now render
+ if (executeYafray(xmlpath))
+ displayImage();
+ else
+ {
+ cout << "Could not execute yafray. Is it in path?" << endl;
+ return false;
+ }
+ return true;
+}
+
+// displays the image rendered with xml export
+// Now loads rendered image into blender renderbuf.
+void yafrayFileRender_t::displayImage()
+{
+ // although it is possible to load the image using blender,
+ // maybe it is best to just do a read here, for now the yafray output is always a raw tga anyway
+
+ // rectot already freed in initrender
+ R.rectot = (unsigned int *)MEM_callocN(sizeof(int)*R.rectx*R.recty, "rectot");
+
+ FILE* fp = fopen(imgout.c_str(), "rb");
+ if (fp==NULL) {
+ cout << "YAF_displayImage(): Could not open image file\n";
+ return;
+ }
+
+ unsigned char header[18];
+ fread(&header, 1, 18, fp);
+ unsigned short width = (unsigned short)(header[12] + (header[13]<<8));
+ unsigned short height = (unsigned short)(header[14] + (header[15]<<8));
+ unsigned char byte_per_pix = (unsigned char)(header[16]>>3);
+ // read past any id (none in this case though)
+ unsigned int idlen = (unsigned int)header[0];
+ if (idlen) fseek(fp, idlen, SEEK_CUR);
+
+ // read data directly into buffer, picture is upside down
+ for (unsigned short y=0;y<height;y++) {
+ unsigned char* bpt = (unsigned char*)R.rectot + ((((height-1)-y)*width)<<2);
+ for (unsigned short x=0;x<width;x++) {
+ bpt[2] = (unsigned char)fgetc(fp);
+ bpt[1] = (unsigned char)fgetc(fp);
+ bpt[0] = (unsigned char)fgetc(fp);
+ if (byte_per_pix==4)
+ bpt[3] = (unsigned char)fgetc(fp);
+ else
+ bpt[3] = 255;
+ bpt += 4;
+ }
+ }
+
+ fclose(fp);
+ fp = NULL;
+}
+
+void yafrayFileRender_t::writeTextures()
+{
+ for (map<string, pair<Material*, MTex*> >::const_iterator blendtex=used_textures.begin();
+ blendtex!=used_textures.end();++blendtex) {
+ Material* matr = blendtex->second.first;
+ MTex* mtex = blendtex->second.second;
+ Tex* tex = mtex->tex;
+ switch (tex->type) {
+ case TEX_STUCCI:
+ // stucci is clouds as bump, but could be added to yafray to handle both wall in/out as well.
+ // noisedepth must be at least 1 in yafray
+ case TEX_CLOUDS: {
+ ostr.str("");
+ ostr << "<shader type=\"clouds\" name=\"" << blendtex->first << "\" >\n";
+ ostr << "\t<attributes>\n";
+ ostr << "\t\t<depth value=\"" << tex->noisedepth+1 << "\" />\n";
+ ostr << "\t</attributes>\n";
+ ostr << "</shader >\n\n";
+ xmlfile << ostr.str();
+ break;
+ }
+ case TEX_WOOD: {
+ ostr.str("");
+ ostr << "<shader type=\"wood\" name=\"" << blendtex->first << "\" >\n";
+ ostr << "\t\t<attributes>\n";
+ ostr << "\t\t<depth value=\"" << tex->noisedepth+1 << "\" />\n";
+ ostr << "\t\t<turbulence value=\"" << tex->turbul << "\" />\n";
+ ostr << "\t\t<ringscale_x value=\"" << mtex->size[0] << "\" />\n";
+ ostr << "\t\t<ringscale_y value=\"" << mtex->size[1] << "\" />\n";
+ string ts = "on";
+ if (tex->noisetype==TEX_NOISESOFT) ts = "off";
+ ostr << "\t\t<hard value=\"" << ts << "\" />\n";
+ ostr << "\t</attributes>\n";
+ ostr << "</shader>\n\n";
+ xmlfile << ostr.str();
+ break;
+ }
+ case TEX_MARBLE: {
+ ostr.str("");
+ ostr << "<shader type=\"marble\" name=\"" << blendtex->first << "\" >\n";
+ ostr << "\t<attributes>\n";
+ ostr << "\t\t<depth value=\"" << tex->noisedepth+1 << "\" />\n";
+ ostr << "\t\t<turbulence value=\"" << tex->turbul << "\" />\n";
+ string ts = "on";
+ if (tex->noisetype==TEX_NOISESOFT) ts = "off";
+ ostr << "\t\t<hard value=\"" << ts << "\" />\n";
+ ts = "1";
+ if (tex->stype==1) ts="5"; else if (tex->stype==2) ts="10";
+ ostr << "\t\t<sharpness value=\"" << ts << "\" />\n";
+ ostr << "\t</attributes>\n";
+ ostr << "</shader>\n\n";
+ xmlfile << ostr.str();
+ break;
+ }
+ case TEX_IMAGE: {
+ Image* ima = tex->ima;
+ if (ima) {
+ ostr.str("");
+ ostr << "<shader type=\"image\" name=\"" << blendtex->first << "\" >\n";
+ ostr << "\t<attributes>\n";
+ // image->name is full path
+ ostr << "\t\t<filename value=\"" << ima->name << "\" />\n";
+ ostr << "\t</attributes>\n";
+ ostr << "</shader>\n\n";
+ xmlfile << ostr.str();
+ }
+ break;
+ }
+ default:
+ cout << "Unsupported texture type\n";
+ }
+
+ // colorbands
+ if (tex->flag & TEX_COLORBAND) {
+ ColorBand* cb = tex->coba;
+ if (cb) {
+ ostr.str("");
+ ostr << "<shader type=\"colorband\" name=\"" << blendtex->first + "_coba" << "\" >\n";
+ ostr << "\t<attributes>\n";
+ ostr << "\t\t<input value=\"" << blendtex->first << "\" />\n";
+ ostr << "\t</attributes>\n";
+ for (int i=0;i<cb->tot;i++) {
+ ostr << "\t<modulator value=\"" << cb->data[i].pos << "\" >\n";
+ ostr << "\t\t<color r=\"" << cb->data[i].r << "\"" <<
+ " g=\"" << cb->data[i].g << "\"" <<
+ " b=\"" << cb->data[i].b << "\" />\n";
+ ostr << "\t</modulator>\n";
+ }
+ ostr << "</shader>\n\n";
+ xmlfile << ostr.str();
+ }
+ }
+
+ }
+}
+
+
+// write all materials & modulators
+void yafrayFileRender_t::writeMaterialsAndModulators()
+{
+ for (map<string, Material*>::const_iterator blendmat=used_materials.begin();
+ blendmat!=used_materials.end();++blendmat) {
+
+ Material* matr = blendmat->second;
+
+ // blendermappers
+ for (int m=0;m<8;m++) {
+
+ if (matr->septex & (1<<m)) continue;// all active channels
+
+ // ignore null mtex
+ MTex* mtex = matr->mtex[m];
+ if (mtex==NULL) continue;
+ // ignore null tex
+ Tex* tex = mtex->tex;
+ if (tex==NULL) continue;
+
+ map<string, pair<Material*, MTex*> >::const_iterator mtexL = used_textures.find(string(tex->id.name+2));
+ if (mtexL!=used_textures.end()) {
+ ostr.str("");
+ ostr << "<shader type=\"blendermapper\" name=\"" << blendmat->first + "_map" << m <<"\"";
+ if ((mtex->texco & TEXCO_OBJECT) || (mtex->texco & TEXCO_REFL))
+ {
+ // For object & reflection mapping, add the object matrix to the modulator,
+ // as in LF script, use camera matrix if no object specified.
+ // In this case this means the inverse of that matrix
+ float texmat[4][4], itexmat[4][4];
+ if ((mtex->texco & TEXCO_OBJECT) && (mtex->object))
+ MTC_Mat4CpyMat4(texmat, mtex->object->obmat);
+ else // also for refl. map
+ MTC_Mat4CpyMat4(texmat, maincam_obj->obmat);
+ MTC_Mat4Invert(itexmat, texmat);
+ ostr << "\n m00=\"" << itexmat[0][0] << "\" m01=\"" << itexmat[1][0]
+ << "\" m02=\"" << itexmat[2][0] << "\" m03=\"" << itexmat[3][0] << "\"\n\t";
+ ostr << " m10=\"" << itexmat[0][1] << "\" m11=\"" << itexmat[1][1]
+ << "\" m12=\"" << itexmat[2][1] << "\" m13=\"" << itexmat[3][1] << "\"\n\t";
+ ostr << " m20=\"" << itexmat[0][2] << "\" m21=\"" << itexmat[1][2]
+ << "\" m22=\"" << itexmat[2][2] << "\" m23=\"" << itexmat[3][2] << "\"\n\t";
+ ostr << " m30=\"" << itexmat[0][3] << "\" m31=\"" << itexmat[1][3]
+ << "\" m32=\"" << itexmat[2][3] << "\" m33=\"" << itexmat[3][3] << "\">\n";
+ }
+ else ostr << ">\n";
+ ostr << "\t<attributes>\n";
+
+ if ((tex->flag & TEX_COLORBAND) & (tex->coba!=NULL))
+ ostr << "\t\t<input value=\"" << mtexL->first + "_coba" << "\" />\n";
+ else
+ ostr << "\t\t<input value=\"" << mtexL->first << "\" />\n";
+
+ // size, if the texturetype is clouds/marble/wood, also take noisesize into account
+ float sc = 1;
+ if ((tex->type==TEX_CLOUDS) || (tex->type==TEX_MARBLE) || (tex->type==TEX_WOOD)) {
+ sc = tex->noisesize;
+ if (sc!=0) sc = 1.f/sc;
+
+ }
+ // texture size
+ ostr << "\t\t<sizex value=\"" << mtex->size[0]*sc << "\" />\n";
+ ostr << "\t\t<sizey value=\"" << mtex->size[1]*sc << "\" />\n";
+ ostr << "\t\t<sizez value=\"" << mtex->size[2]*sc << "\" />\n";
+
+ // texture offset
+ ostr << "\t\t<ofsx value=\"" << mtex->ofs[0] << "\" />\n";
+ ostr << "\t\t<ofsy value=\"" << mtex->ofs[1] << "\" />\n";
+ ostr << "\t\t<ofsz value=\"" << mtex->ofs[2] << "\" />\n";
+
+ // texture coordinates, have to disable 'sticky' in Blender
+ if ((mtex->texco & TEXCO_UV) || (matr->mode & MA_FACETEXTURE))
+ ostr << "\t\t<texco value=\"uv\" />\n";
+ else if ((mtex->texco & TEXCO_GLOB) || (mtex->texco & TEXCO_OBJECT))
+ // object mode is also set as global, but the object matrix was specified above with <modulator..>
+ ostr << "\t\t<texco value=\"global\" />\n";
+ else if (mtex->texco & TEXCO_ORCO)
+ ostr << "\t\t<texco value=\"orco\" />\n";
+ else if (mtex->texco & TEXCO_WINDOW)
+ ostr << "\t\t<texco value=\"window\" />\n";
+ else if (mtex->texco & TEXCO_NORM)
+ ostr << "\t\t<texco value=\"normal\" />\n";
+ else if (mtex->texco & TEXCO_REFL)
+ ostr << "\t\t<texco value=\"reflect\" />\n";
+
+ // texture mapping parameters only relevant to image type
+ if (tex->type==TEX_IMAGE) {
+ if (mtex->mapping==MTEX_FLAT)
+ ostr << "\t\t<mapping value=\"flat\" />\n";
+ else if (mtex->mapping==MTEX_CUBE)
+ ostr << "\t\t<mapping value=\"cube\" />\n";
+ else if (mtex->mapping==MTEX_TUBE)
+ ostr << "\t\t<mapping value=\"tube\" />\n";
+ else if (mtex->mapping==MTEX_SPHERE)
+ ostr << "\t\t<mapping value=\"sphere\" />\n";
+
+ // texture projection axes
+ string proj = "nxyz"; // 'n' for 'none'
+ ostr << "\t\t<proj_x value=\"" << proj[mtex->projx] << "\" />\n";
+ ostr << "\t\t<proj_y value=\"" << proj[mtex->projy] << "\" />\n";
+ ostr << "\t\t<proj_z value=\"" << proj[mtex->projz] << "\" />\n";
+
+ // repeat
+ ostr << "\t\t<xrepeat value=\"" << tex->xrepeat << "\" />\n";
+ ostr << "\t\t<yrepeat value=\"" << tex->yrepeat << "\" />\n";
+
+ // clipping
+ if (tex->extend==TEX_EXTEND)
+ ostr << "\t\t<clipping value=\"extend\" />\n";
+ else if (tex->extend==TEX_CLIP)
+ ostr << "\t\t<clipping value=\"clip\" />\n";
+ else if (tex->extend==TEX_CLIPCUBE)
+ ostr << "\t\t<clipping value=\"clipcube\" />\n";
+ else
+ ostr << "\t\t<clipping value=\"repeat\" />\n";
+
+ // crop min/max
+ ostr << "\t\t<cropmin_x value=\"" << tex->cropxmin << "\" />\n";
+ ostr << "\t\t<cropmin_y value=\"" << tex->cropymin << "\" />\n";
+ ostr << "\t\t<cropmax_x value=\"" << tex->cropxmax << "\" />\n";
+ ostr << "\t\t<cropmax_y value=\"" << tex->cropymax << "\" />\n";
+
+ // rot90 flag
+ string ts = "off";
+ if (tex->imaflag & TEX_IMAROT) ts = "on";
+ ostr << "\t\t<rot90 value=\"" << ts << "\" />\n";
+ }
+
+ ostr << "\t</attributes>\n";
+ ostr << "</shader>\n\n";
+
+ xmlfile << ostr.str();
+ }
+ }
+
+ // blendershaders + modulators
+ ostr.str("");
+ ostr << "<shader type=\"blendershader\" name=\"" << blendmat->first << "\" >\n";
+ ostr << "\t<attributes>\n";
+ float diff=matr->alpha;
+ ostr << "\t\t<color r=\"" << matr->r*diff << "\" g=\"" << matr->g*diff << "\" b=\"" << matr->b*diff << "\" />\n";
+ ostr << "\t\t<specular_color r=\"" << matr->specr << "\" g=\"" << matr->specg << "\" b=\"" << matr->specb<< "\" />\n";
+ ostr << "\t\t<mirror_color r=\"" << matr->mirr << "\" g=\"" << matr->mirg << "\" b=\"" << matr->mirb << "\" />\n";
+ ostr << "\t\t<diffuse_reflect value=\"" << matr->ref << "\" />\n";
+ ostr << "\t\t<specular_amount value=\"" << matr->spec << "\" />\n";
+ ostr << "\t\t<hard value=\"" << matr->har << "\" />\n";
+ ostr << "\t\t<alpha value=\"" << matr->alpha << "\" />\n";
+ ostr << "\t\t<emit value=\"" << matr->emit << "\" />\n";
+
+ // reflection/refraction
+ if ( (matr->mode & MA_RAYMIRROR) || (matr->mode & MA_RAYTRANSP) )
+ ostr << "\t\t<IOR value=\"" << matr->ang << "\" />\n";
+ if (matr->mode & MA_RAYMIRROR) {
+ float rf = matr->ray_mirror;
+ // blender uses mir color for reflection as well
+ ostr << "\t\t<reflected r=\"" << matr->mirr << "\" g=\"" << matr->mirg << "\" b=\"" << matr->mirb << "\" />\n";
+ ostr << "\t\t<min_refle value=\""<< rf << "\" />\n";
+ if (matr->ray_depth>maxraydepth) maxraydepth = matr->ray_depth;
+ }
+ if (matr->mode & MA_RAYTRANSP)
+ {
+ float tr=1.0-matr->alpha;
+ ostr << "\t\t<transmitted r=\"" << matr->r * tr << "\" g=\"" << matr->g * tr << "\" b=\"" << matr->b * tr << "\" />\n";
+ // tir on by default
+ ostr << "\t\t<tir value=\"on\" />\n";
+ if (matr->ray_depth_tra>maxraydepth) maxraydepth = matr->ray_depth_tra;
+ }
+
+ string Mmode = "";
+ if (matr->mode & MA_TRACEBLE) Mmode += "traceable";
+ if (matr->mode & MA_SHADOW) Mmode += " shadow";
+ if (matr->mode & MA_SHLESS) Mmode += " shadeless";
+ if (matr->mode & MA_VERTEXCOL) Mmode += " vcol_light";
+ if (matr->mode & MA_VERTEXCOLP) Mmode += " vcol_paint";
+ if (matr->mode & MA_ZTRA) Mmode += " ztransp";
+ if (matr->mode & MA_ONLYSHADOW) Mmode += " onlyshadow";
+ if (Mmode!="") ostr << "\t\t<matmodes value=\"" << Mmode << "\" />\n";
+ ostr << "\t</attributes>\n";
+ xmlfile << ostr.str();
+
+ // modulators
+ for (int m2=0;m2<8;m2++) {
+
+ if (matr->septex & (1<<m2)) continue;// all active channels
+
+ // ignore null mtex
+ MTex* mtex = matr->mtex[m2];
+ if (mtex==NULL) continue;
+
+ // ignore null tex
+ Tex* tex = mtex->tex;
+ if (tex==NULL) continue;
+
+ map<string, pair<Material*, MTex*> >::const_iterator mtexL = used_textures.find(string(tex->id.name+2));
+ if (mtexL!=used_textures.end()) {
+
+ ostr.str("");
+ ostr << "\t<modulator>\n";
+ ostr << "\t\t<input value=\"" << blendmat->first + "_map" << m2 << "\" />\n";
+
+ // blendtype
+ string ts = "mix";
+ if (mtex->blendtype==MTEX_MUL) ts="mul";
+ else if (mtex->blendtype==MTEX_ADD) ts="add";
+ else if (mtex->blendtype==MTEX_SUB) ts="sub";
+ ostr << "\t\t<mode value=\"" << ts << "\" />\n";
+
+ // texture color (for use with MUL and/or no_rgb etc..)
+ ostr << "\t\t<texcol r=\"" << mtex->r << "\" g=\"" << mtex->g << "\" b=\"" << mtex->b << "\" />\n";
+
+ // texture contrast, brightness & color adjustment
+ ostr << "\t\t<filtercolor r=\"" << tex->rfac << "\" g=\"" << tex->gfac << "\" b=\"" << tex->bfac << "\" />\n";
+ ostr << "\t\t<contrast value=\"" << tex->contrast << "\" />\n";
+ ostr << "\t\t<brightness value=\"" << tex->bright << "\" />\n";
+
+ // all texture flags now are switches, having the value 1 or -1 (negative option)
+ // the negative option only used for the intensity modulation options.
+
+ // material (diffuse) color, amount controlled by colfac (see below)
+ if (mtex->mapto & MAP_COL)
+ ostr << "\t\t<color value=\"1\" />\n";
+
+ // bumpmapping
+ if ((mtex->mapto & MAP_NORM) || (mtex->maptoneg & MAP_NORM)) {
+ // for yafray, bump factor is negated (unless negative option of 'Nor', is not affected by 'Neg')
+ // scaled down quite a bit for yafray when image type, otherwise used directly
+ float nf = -mtex->norfac;
+ if (mtex->maptoneg & MAP_NORM) nf *= -1.f;
+ if (tex->type==TEX_IMAGE) nf *= 2e-3f;
+ ostr << "\t\t<normal value=\"" << nf << "\" />\n";
+
+ }
+
+ // all blender texture modulation as switches, either 1 or -1 (negative state of button)
+ // Csp, specular color modulation
+ if (mtex->mapto & MAP_COLSPEC)
+ ostr << "\t\t<colspec value=\"1\" />\n";
+
+ // CMir, mirror color modulation
+ if (mtex->mapto & MAP_COLMIR)
+ ostr << "\t\t<colmir value=\"1\" />\n";
+
+ // Ref, diffuse reflection amount modulation
+ if ((mtex->mapto & MAP_REF) || (mtex->maptoneg & MAP_REF)) {
+ int t = 1;
+ if (mtex->maptoneg & MAP_REF) t = -1;
+ ostr << "\t\t<difref value=\"" << t << "\" />\n";
+ }
+
+ // Spec, specular amount mod
+ if ((mtex->mapto & MAP_SPEC) || (mtex->maptoneg & MAP_SPEC)) {
+ int t = 1;
+ if (mtex->maptoneg & MAP_SPEC) t = -1;
+ ostr << "\t\t<specular value=\"" << t << "\" />\n";
+ }
+
+ // hardness modulation
+ if ((mtex->mapto & MAP_HAR) || (mtex->maptoneg & MAP_HAR)) {
+ int t = 1;
+ if (mtex->maptoneg & MAP_HAR) t = -1;
+ ostr << "\t\t<hard value=\"" << t << "\" />\n";
+ }
+
+ // alpha modulation
+ if ((mtex->mapto & MAP_ALPHA) || (mtex->maptoneg & MAP_ALPHA)) {
+ int t = 1;
+ if (mtex->maptoneg & MAP_ALPHA) t = -1;
+ ostr << "\t\t<alpha value=\"" << t << "\" />\n";
+
+ }
+
+ // emit modulation
+ if ((mtex->mapto & MAP_EMIT) || (mtex->maptoneg & MAP_EMIT)) {
+ int t = 1;
+ if (mtex->maptoneg & MAP_EMIT) t = -1;
+ ostr << "\t\t<emit value=\"" << t << "\" />\n";
+ }
+
+ // texture flag, combination of strings
+ if (mtex->texflag & (MTEX_RGBTOINT | MTEX_STENCIL | MTEX_NEGATIVE)) {
+ ts = "";
+ if (mtex->texflag & MTEX_RGBTOINT) ts += "no_rgb ";
+ if (mtex->texflag & MTEX_STENCIL) ts += "stencil ";
+ if (mtex->texflag & MTEX_NEGATIVE) ts += "negative";
+ ostr << "\t\t<texflag value=\"" << ts << "\" />\n";
+ }
+
+ // colfac, controls amount of color modulation
+ ostr << "\t\t<colfac value=\"" << mtex->colfac << "\" />\n";
+
+ // def_var
+ ostr << "\t\t<def_var value=\"" << mtex->def_var << "\" />\n";
+
+ //varfac
+ ostr << "\t\t<varfac value=\"" << mtex->varfac << "\" />\n";
+
+ if ((tex->imaflag & (TEX_CALCALPHA | TEX_USEALPHA)) || (tex->flag & TEX_NEGALPHA)) {
+ ts = "";
+ if (tex->imaflag & TEX_CALCALPHA) ts += "calc_alpha ";
+ if (tex->imaflag & TEX_USEALPHA) ts += "use_alpha ";
+ if (tex->flag & TEX_NEGALPHA) ts += "neg_alpha";
+ ostr << "\t\t<alpha_flag value=\"" << ts << "\" />\n";
+ }
+
+ ostr << "\t</modulator>\n";
+ xmlfile << ostr.str();
+
+ }
+ }
+ xmlfile << "</shader>\n\n";
+ }
+}
+
+
+void yafrayFileRender_t::writeObject(Object* obj, const vector<VlakRen*> &VLR_list, const float obmat[4][4])
+{
+ ostr.str("");
+ // transform first (not necessarily actual obj->obmat, can be duplivert see below)
+ ostr << "<transform m00=\"" << obmat[0][0] << "\" m01=\"" << obmat[1][0]
+ << "\" m02=\"" << obmat[2][0] << "\" m03=\"" << obmat[3][0] << "\"\n";
+ ostr << " m10=\"" << obmat[0][1] << "\" m11=\"" << obmat[1][1]
+ << "\" m12=\"" << obmat[2][1] << "\" m13=\"" << obmat[3][1] << "\"\n";
+ ostr << " m20=\"" << obmat[0][2] << "\" m21=\"" << obmat[1][2]
+ << "\" m22=\"" << obmat[2][2] << "\" m23=\"" << obmat[3][2] << "\"\n";
+ ostr << " m30=\"" << obmat[0][3] << "\" m31=\"" << obmat[1][3]
+ << "\" m32=\"" << obmat[2][3] << "\" m33=\"" << obmat[3][3] << "\">\n";
+ xmlfile << ostr.str();
+
+ ostr.str("");
+ ostr << "<object name=\"" << obj->id.name+2 << "\"";
+ // yafray still needs default shader name in object def.,
+ // since we write a shader with every face, simply use the material of the first face
+ // if this is an empty string, assume default mat
+ char* matname = VLR_list[0]->mat->id.name;
+ bool shadow=VLR_list[0]->mat->mode & MA_TRACEBLE;
+ ostr <<" shadow=\""<< (shadow ? "on" : "off" )<<"\" ";
+ if (VLR_list[0]->mat->mode & MA_RAYTRANSP)
+ ostr << "caus_IOR=\"" << VLR_list[0]->mat->ang << "\" ";
+ if (strlen(matname)==0) matname = "blender_default"; else matname+=2; //skip MA id
+ ostr << " shader_name=\"" << matname << "\" >\n";
+ ostr << "\t<attributes>\n";
+ if (VLR_list[0]->mat->mode & MA_RAYTRANSP)
+ {
+ float tr=1.0-VLR_list[0]->mat->alpha;
+ ostr << "\t\t<caus_tcolor r=\"" << VLR_list[0]->mat->r * tr
+ << "\" g=\"" << VLR_list[0]->mat->g * tr
+ << "\" b=\"" << VLR_list[0]->mat->b * tr << "\" />\n";
+ }
+ ostr << "\t</attributes>\n";
+ xmlfile << ostr.str();
+
+ // if any face in the Blender mesh uses an orco texture, every face has orco coords,
+ // so only need to check the first facevtx.orco in the list if they need to be exported
+ bool EXPORT_ORCO = (VLR_list[0]->v1->orco!=NULL);
+
+ string has_orco = "off";
+ if (EXPORT_ORCO) has_orco = "on";
+
+ // smooth shading if enabled
+ bool no_auto = true; //in case non-mesh, or mesh has no autosmooth
+ if (obj->type==OB_MESH) {
+ Mesh* mesh = (Mesh*)obj->data;
+
+ if (mesh->flag & ME_AUTOSMOOTH) {
+ no_auto = false;
+ ostr.str("");
+ ostr << "\t<mesh autosmooth=\"" << mesh->smoothresh << "\" has_orco=\"" << has_orco << "\" >\n";
+ xmlfile << ostr.str();
+ }
+ }
+ // this for non-mesh as well
+ if (no_auto) {
+ // If AutoSmooth not used, since yafray currently cannot specify if a face is smooth
+ // or flat shaded, the smooth flag of the first face is used to determine
+ // the shading for the whole mesh
+ if (VLR_list[0]->flag & ME_SMOOTH)
+ xmlfile << "\t<mesh autosmooth=\"90\" has_orco=\"" << has_orco << "\" >\n";
+ else
+ xmlfile << "\t<mesh autosmooth=\"0.1\" has_orco=\"" << has_orco << "\" >\n"; //0 shows artefacts
+ }
+
+ // now all vertices
+ map<VertRen*, int> vert_idx; // for removing duplicate verts and creating an index list
+ int vidx = 0; // vertex index counter
+
+ xmlfile << "\t\t<points>\n";
+ for (vector<VlakRen*>::const_iterator fci=VLR_list.begin();
+ fci!=VLR_list.end();++fci)
+ {
+ VlakRen* vlr = *fci;
+ VertRen* ver;
+ float* orco;
+ ostr.str("");
+ if (vert_idx.find(vlr->v1)==vert_idx.end()) {
+ vert_idx[vlr->v1] = vidx++;
+ ver = vlr->v1;
+ ostr << "\t\t\t<p x=\"" << ver->co[0]
+ << "\" y=\"" << ver->co[1]
+ << "\" z=\"" << ver->co[2] << "\" />\n";
+ if (EXPORT_ORCO) {
+ orco = ver->orco;
+ ostr << "\t\t\t<p x=\"" << orco[0]
+ << "\" y=\"" << orco[1]
+ << "\" z=\"" << orco[2] << "\" />\n";
+ }
+ }
+ if (vert_idx.find(vlr->v2)==vert_idx.end()) {
+ vert_idx[vlr->v2] = vidx++;
+ ver = vlr->v2;
+ ostr << "\t\t\t<p x=\"" << ver->co[0]
+ << "\" y=\"" << ver->co[1]
+ << "\" z=\"" << ver->co[2] << "\" />\n";
+ if (EXPORT_ORCO) {
+ orco = ver->orco;
+ ostr << "\t\t\t<p x=\"" << orco[0]
+ << "\" y=\"" << orco[1]
+ << "\" z=\"" << orco[2] << "\" />\n";
+ }
+ }
+ if (vert_idx.find(vlr->v3)==vert_idx.end()) {
+ vert_idx[vlr->v3] = vidx++;
+ ver = vlr->v3;
+ ostr << "\t\t\t<p x=\"" << ver->co[0]
+ << "\" y=\"" << ver->co[1]
+ << "\" z=\"" << ver->co[2] << "\" />\n";
+ if (EXPORT_ORCO) {
+ orco = ver->orco;
+ ostr << "\t\t\t<p x=\"" << orco[0]
+ << "\" y=\"" << orco[1]
+ << "\" z=\"" << orco[2] << "\" />\n";
+ }
+ }
+ if ((vlr->v4) && (vert_idx.find(vlr->v4)==vert_idx.end())) {
+ vert_idx[vlr->v4] = vidx++;
+ ver = vlr->v4;
+ ostr << "\t\t\t<p x=\"" << ver->co[0]
+ << "\" y=\"" << ver->co[1]
+ << "\" z=\"" << ver->co[2] << "\" />\n";
+ if (EXPORT_ORCO) {
+ orco = ver->orco;
+ ostr << "\t\t\t<p x=\"" << orco[0]
+ << "\" y=\"" << orco[1]
+ << "\" z=\"" << orco[2] << "\" />\n";
+ }
+ }
+ xmlfile << ostr.str();
+ }
+ xmlfile << "\t\t</points>\n";
+
+ // all faces using the index list created above
+ xmlfile << "\t\t<faces>\n";
+ for (vector<VlakRen*>::const_iterator fci2=VLR_list.begin();
+ fci2!=VLR_list.end();++fci2)
+ {
+ VlakRen* vlr = *fci2;
+ Material* fmat = vlr->mat;
+ bool EXPORT_VCOL = ((fmat->mode & (MA_VERTEXCOL|MA_VERTEXCOLP))!=0);
+ char* fmatname = fmat->id.name;
+ if (strlen(fmatname)==0) fmatname = "blender_default"; else fmatname+=2; //skip MA id
+ TFace* uvc = vlr->tface; // possible uvcoords (v upside down)
+ int idx1, idx2, idx3;
+
+ idx1 = vert_idx.find(vlr->v1)->second;
+ idx2 = vert_idx.find(vlr->v2)->second;
+ idx3 = vert_idx.find(vlr->v3)->second;
+
+ // make sure the indices point to the vertices when orco coords exported
+ if (EXPORT_ORCO) { idx1*=2; idx2*=2; idx3*=2; }
+
+ ostr.str("");
+ ostr << "\t\t\t<f a=\"" << idx1 << "\" b=\"" << idx2 << "\" c=\"" << idx3 << "\"";
+
+ if (uvc) {
+ // use correct uv coords for this triangle
+ if (vlr->flag & R_FACE_SPLIT) {
+ ostr << " u_a=\"" << uvc->uv[0][0] << "\" v_a=\"" << 1-uvc->uv[0][1] << "\""
+ << " u_b=\"" << uvc->uv[2][0] << "\" v_b=\"" << 1-uvc->uv[2][1] << "\""
+ << " u_c=\"" << uvc->uv[3][0] << "\" v_c=\"" << 1-uvc->uv[3][1] << "\"";
+ }
+ else {
+ ostr << " u_a=\"" << uvc->uv[0][0] << "\" v_a=\"" << 1-uvc->uv[0][1] << "\""
+ << " u_b=\"" << uvc->uv[1][0] << "\" v_b=\"" << 1-uvc->uv[1][1] << "\""
+ << " u_c=\"" << uvc->uv[2][0] << "\" v_c=\"" << 1-uvc->uv[2][1] << "\"";
+ }
+ }
+
+ // since Blender seems to need vcols when uvs are used, for yafray only export when the material actually uses vcols
+ if ((EXPORT_VCOL) && (vlr->vcol)) {
+ // vertex colors
+ float vr, vg, vb;
+ vr = ((vlr->vcol[0] >> 24) & 255)/255.0;
+ vg = ((vlr->vcol[0] >> 16) & 255)/255.0;
+ vb = ((vlr->vcol[0] >> 8) & 255)/255.0;
+ ostr << " vcol_a_r=\"" << vr << "\" vcol_a_g=\"" << vg << "\" vcol_a_b=\"" << vb << "\"";
+ vr = ((vlr->vcol[1] >> 24) & 255)/255.0;
+ vg = ((vlr->vcol[1] >> 16) & 255)/255.0;
+ vb = ((vlr->vcol[1] >> 8) & 255)/255.0;
+ ostr << " vcol_b_r=\"" << vr << "\" vcol_b_g=\"" << vg << "\" vcol_b_b=\"" << vb << "\"";
+ vr = ((vlr->vcol[2] >> 24) & 255)/255.0;
+ vg = ((vlr->vcol[2] >> 16) & 255)/255.0;
+ vb = ((vlr->vcol[2] >> 8) & 255)/255.0;
+ ostr << " vcol_c_r=\"" << vr << "\" vcol_c_g=\"" << vg << "\" vcol_c_b=\"" << vb << "\"";
+ }
+ ostr << " shader_name=\"" << fmatname << "\" />\n";
+
+ if (vlr->v4) {
+
+ idx1 = vert_idx.find(vlr->v3)->second;
+ idx2 = vert_idx.find(vlr->v4)->second;
+ idx3 = vert_idx.find(vlr->v1)->second;
+
+ // make sure the indices point to the vertices when orco coords exported
+ if (EXPORT_ORCO) { idx1*=2; idx2*=2; idx3*=2; }
+
+ ostr << "\t\t\t<f a=\"" << idx1 << "\" b=\"" << idx2 << "\" c=\"" << idx3 << "\"";
+
+ if (uvc) {
+ ostr << " u_a=\"" << uvc->uv[2][0] << "\" v_a=\"" << 1-uvc->uv[2][1] << "\""
+ << " u_b=\"" << uvc->uv[3][0] << "\" v_b=\"" << 1-uvc->uv[3][1] << "\""
+ << " u_c=\"" << uvc->uv[0][0] << "\" v_c=\"" << 1-uvc->uv[0][1] << "\"";
+ }
+ if ((EXPORT_VCOL) && (vlr->vcol)) {
+ // vertex colors
+ float vr, vg, vb;
+ vr = ((vlr->vcol[2] >> 24) & 255)/255.0;
+ vg = ((vlr->vcol[2] >> 16) & 255)/255.0;
+ vb = ((vlr->vcol[2] >> 8) & 255)/255.0;
+ ostr << " vcol_a_r=\"" << vr << "\" vcol_a_g=\"" << vg << "\" vcol_a_b=\"" << vb << "\"";
+ vr = ((vlr->vcol[3] >> 24) & 255)/255.0;
+ vg = ((vlr->vcol[3] >> 16) & 255)/255.0;
+ vb = ((vlr->vcol[3] >> 8) & 255)/255.0;
+ ostr << " vcol_b_r=\"" << vr << "\" vcol_b_g=\"" << vg << "\" vcol_b_b=\"" << vb << "\"";
+ vr = ((vlr->vcol[0] >> 24) & 255)/255.0;
+ vg = ((vlr->vcol[0] >> 16) & 255)/255.0;
+ vb = ((vlr->vcol[0] >> 8) & 255)/255.0;
+ ostr << " vcol_c_r=\"" << vr << "\" vcol_c_g=\"" << vg << "\" vcol_c_b=\"" << vb << "\"";
+ }
+ ostr << " shader_name=\"" << fmatname << "\" />\n";
+
+ }
+ xmlfile << ostr.str();
+ }
+ xmlfile << "\t\t</faces>\n\t</mesh>\n</object>\n</transform>\n\n";
+}
+
+
+// write all objects
+void yafrayFileRender_t::writeAllObjects()
+{
+
+ // first all objects except dupliverts (and main instance object for dups)
+ for (map<Object*, vector<VlakRen*> >::const_iterator obi=all_objects.begin();
+ obi!=all_objects.end(); ++obi)
+ {
+ // skip main duplivert, written later
+ if (obi->first->flag & OB_YAF_DUPLISOURCE) continue;
+ writeObject(obi->first, obi->second, obi->first->obmat);
+ }
+
+ // Now all duplivert objects (if any) as instances of main object
+ // The original object has been included in the VlakRen renderlist above (see convertBlenderScene.c)
+ // but is written here which all other duplis are instances of.
+ float obmat[4][4], cmat[4][4], imat[4][4], nmat[4][4];
+ for (map<string, vector<float> >::const_iterator dupMtx=dupliMtx_list.begin();
+ dupMtx!=dupliMtx_list.end();++dupMtx) {
+
+ // original inverse matrix, not actual matrix of object, but first duplivert.
+ for (int i=0;i<4;i++)
+ for (int j=0;j<4;j++)
+ obmat[i][j] = dupMtx->second[(i<<2)+j];
+ MTC_Mat4Invert(imat, obmat);
+
+ // first object written as normal (but with transform of first duplivert)
+ Object* obj = dup_srcob[dupMtx->first];
+ writeObject(obj, all_objects[obj], obmat);
+
+ // all others instances of first
+ for (int curmtx=16;curmtx<dupMtx->second.size();curmtx+=16) { // number of 4x4 matrices
+
+ // new mtx
+ for (int i=0;i<4;i++)
+ for (int j=0;j<4;j++)
+ nmat[i][j] = dupMtx->second[curmtx+(i<<2)+j];
+
+ MTC_Mat4MulMat4(cmat, imat, nmat); // transform with respect to original = inverse_original * new
+
+ ostr.str("");
+ // yafray matrix = transpose of Blender
+ ostr << "<transform m00=\"" << cmat[0][0] << "\" m01=\"" << cmat[1][0]
+ << "\" m02=\"" << cmat[2][0] << "\" m03=\"" << cmat[3][0] << "\"\n";
+ ostr << " m10=\"" << cmat[0][1] << "\" m11=\"" << cmat[1][1]
+ << "\" m12=\"" << cmat[2][1] << "\" m13=\"" << cmat[3][1] << "\"\n";
+ ostr << " m20=\"" << cmat[0][2] << "\" m21=\"" << cmat[1][2]
+ << "\" m22=\"" << cmat[2][2] << "\" m23=\"" << cmat[3][2] << "\"\n";
+ ostr << " m30=\"" << cmat[0][3] << "\" m31=\"" << cmat[1][3]
+ << "\" m32=\"" << cmat[2][3] << "\" m33=\"" << cmat[3][3] << "\">\n";
+ xmlfile << ostr.str();
+
+ // new name from original
+ ostr.str("");
+ ostr << "<object name=\"" << obj->id.name+2 << "_dup" << (curmtx>>4) << "\" original=\"" << obj->id.name+2 << "\" >\n";
+ xmlfile << ostr.str();
+ xmlfile << "\t<attributes>\n\t</attributes>\n\t<null/>\n</object>\n</transform>\n\n";
+
+ }
+
+ }
+
+}
+
+
+void yafrayFileRender_t::writeLamps()
+{
+ // all lamps
+ for (int i=0;i<R.totlamp;i++)
+ {
+ ostr.str("");
+ LampRen* lamp = R.la[i];
+ // TODO: add decay setting in yafray
+ ostr << "<light type=\"";
+ if (lamp->type==LA_LOCAL)
+ ostr << "pointlight";
+ else if (lamp->type==LA_SPOT)
+ ostr << "spotlight";
+ else if (lamp->type==LA_SUN) // for now, hemi == sun
+ ostr << "sunlight";
+ /* TODO
+ else if (lamp->type==LA_AREA) {
+ // new blender area light
+ ostr << "arealight";
+ }
+ */
+ else {
+ // possibly unknown type, ignore
+ cout << "Unknown Blender lamp type: " << lamp->type << endl;
+ continue;
+ }
+ ostr << "\" name=\"LAMP" << i+1; //no name available here, create one
+ // color already premultiplied by energy, so only need distance here
+ float pwr;
+ if (lamp->mode & LA_SPHERE) {
+ // best approx. as used in LFexport script, however, in yafray it seems incorrect, so LF must use another model
+ pwr = lamp->dist*(lamp->dist+1)*0.125;
+ //decay = 2;
+ }
+ else {
+ if ((lamp->type==LA_LOCAL) || (lamp->type==LA_SPOT)) {
+ pwr = lamp->dist;
+ //decay = 1;
+ }
+ else pwr = 1; // sun/hemi distance irrelevent.
+ }
+ ostr << "\" power=\"" << pwr;
+ string lpmode="off";
+ if ((lamp->mode & LA_SHAD) || (lamp->mode & LA_SHAD_RAY)) lpmode="on";;
+ ostr << "\" cast_shadows=\"" << lpmode << "\"";
+ // spot specific stuff
+ if (lamp->type==LA_SPOT) {
+ // conversion already changed spotsize to cosine of half angle
+ float ld = 1-lamp->spotsi; //convert back to blender slider setting
+ if (ld!=0) ld = 1.f/ld;
+ ostr << " size=\"" << acos(lamp->spotsi)*180.0/M_PI << "\""
+ << " blend=\"" << lamp->spotbl*ld << "\""
+ << " beam_falloff=\"2\""; // no Blender equivalent (yet)
+ }
+ ostr << " >\n";
+ // position
+ ostr << "\t<from x=\"" << lamp->co[0] << "\" y=\"" << lamp->co[1] << "\" z=\"" << lamp->co[2] << "\" />\n";
+ // 'to' for spot, already calculated by Blender
+ if (lamp->type==LA_SPOT)
+ ostr << "\t<to x=\"" << lamp->co[0]+1e6*lamp->vec[0]
+ << "\" y=\"" << lamp->co[1]+1e6*lamp->vec[1]
+ << "\" z=\"" << lamp->co[2]+1e6*lamp->vec[2] << "\" />\n";
+ // color
+ // rgb in LampRen is premultiplied by energy, power is compensated for that above
+ ostr << "\t<color r=\"" << lamp->r << "\" g=\"" << lamp->g << "\" b=\"" << lamp->b << "\" />\n";
+ ostr << "</light>\n\n";
+ xmlfile << ostr.str();
+ }
+}
+
+
+// write main camera
+void yafrayFileRender_t::writeCamera()
+{
+ // here Global used again
+ ostr.str("");
+ ostr << "<camera name=\"MAINCAM\"";
+
+ // render resolution including the percentage buttons (aleady calculated in initrender for R renderdata)
+ int xres = R.r.xsch;
+ int yres = R.r.ysch;
+ ostr << " resx=\"" << xres << "\" resy=\"" << yres;
+
+ // aspectratio can be set in Blender as well using aspX & aspY, need an extra param. for yafray cam.
+ float aspect = 1;
+ if (R.r.xsch < R.r.ysch) aspect = float(R.r.xsch)/float(R.r.ysch);
+
+ ostr << "\" focal=\"" << mainCamLens/(aspect*32.0) << "\" >\n";
+ xmlfile << ostr.str();
+
+ // from, to, up vectors
+ // comment in MTC_matrixops.h not correct, copy is arg2->arg1
+ float camtx[4][4];
+ MTC_Mat4CpyMat4(camtx, maincam_obj->obmat);
+ MTC_normalise3DF(camtx[1]); //up
+ MTC_normalise3DF(camtx[2]); //dir
+ ostr.str("");
+ ostr << "\t<from x=\"" << camtx[3][0] << "\""
+ << " y=\"" << camtx[3][1] << "\""
+ << " z=\"" << camtx[3][2] << "\" />\n";
+ Object* dofob = findObject("OBFOCUS");
+ if (dofob) {
+ // dof empty found, modify lookat point accordingly
+ // location from matrix, in case animated
+ float fdx = dofob->obmat[3][0] - camtx[3][0];
+ float fdy = dofob->obmat[3][1] - camtx[3][1];
+ float fdz = dofob->obmat[3][2] - camtx[3][2];
+ float fdist = sqrt(fdx*fdx + fdy*fdy + fdz*fdz);
+ cout << "FOCUS object found, distance is: " << fdist << endl;
+ ostr << "\t<to x=\"" << camtx[3][0] - fdist*camtx[2][0]
+ << "\" y=\"" << camtx[3][1] - fdist*camtx[2][1]
+ << "\" z=\"" << camtx[3][2] - fdist*camtx[2][2] << "\" />\n";
+ }
+ else {
+ ostr << "\t<to x=\"" << camtx[3][0] - camtx[2][0]
+ << "\" y=\"" << camtx[3][1] - camtx[2][1]
+ << "\" z=\"" << camtx[3][2] - camtx[2][2] << "\" />\n";
+ }
+ ostr << "\t<up x=\"" << camtx[3][0] + camtx[1][0]
+ << "\" y=\"" << camtx[3][1] + camtx[1][1]
+ << "\" z=\"" << camtx[3][2] + camtx[1][2] << "\" />\n";
+ xmlfile << ostr.str();
+ xmlfile << "</camera>\n\n";
+}
+
+void yafrayFileRender_t::writeHemilight()
+{
+ ostr.str("");
+ ostr << "<light type=\"hemilight\" name=\"hemi_LT\" power=\"" << R.r.GIpower << "\" ";
+ switch (R.r.GIquality)
+ {
+ case 1 :
+ case 2 : ostr << " samples=\"16\" >\n"; break;
+ case 3 : ostr << " samples=\"36\" >\n"; break;
+ case 4 : ostr << " samples=\"64\" >\n"; break;
+ default: ostr << " samples=\"25\" >\n";
+ }
+ ostr << "</light>\n\n";
+ xmlfile << ostr.str();
+}
+
+void yafrayFileRender_t::writePathlight()
+{
+ ostr.str("");
+ ostr << "<light type=\"pathlight\" name=\"path_LT\" power=\"" << R.r.GIpower << "\" ";
+ ostr << " depth=\"" << R.r.GIdepth << "\" caus_depth=\"" << R.r.GIcausdepth <<"\"\n";
+ if (R.r.GIcache)
+ {
+ switch (R.r.GIquality)
+ {
+ case 1 : ostr << " samples=\"128\" \n"; break;
+ case 2 : ostr << " samples=\"256\" \n"; break;
+ case 3 : ostr << " samples=\"512\" \n"; break;
+ case 4 : ostr << " samples=\"1024\" \n"; break;
+ default: ostr << " samples=\"512\" \n";
+ }
+ float aspect = 1;
+ if (R.r.xsch < R.r.ysch) aspect = float(R.r.xsch)/float(R.r.ysch);
+ float sbase = 2.0*atan(0.5/(mainCamLens/(aspect*32.0)))/float(R.r.xsch);
+ ostr << " cache=\"on\" use_QMC=\"on\" \n";
+ ostr << " cache_size=\"" << sbase*R.r.GIpixelspersample << "\" shadow_threshold=\"" <<
+ 1.0 - R.r.GIshadowquality << "\" search=\"85\" gradient=\"" <<
+ ((R.r.GIgradient)? "on" : "off") << "\" >\n";
+ }
+ else
+ {
+ switch (R.r.GIquality)
+ {
+ case 1 : ostr << " samples=\"16\" >\n"; break;
+ case 2 : ostr << " samples=\"36\" >\n"; break;
+ case 3 : ostr << " samples=\"64\" >\n"; break;
+ case 4 : ostr << " samples=\"128\" >\n"; break;
+ default: ostr << " samples=\"25\" >\n";
+ }
+ }
+ ostr << "</light>\n\n";
+ xmlfile << ostr.str();
+}
+
+bool yafrayFileRender_t::writeWorld()
+{
+ World *world = G.scene->world;
+
+ if (R.r.GIquality!=0) {
+ if (R.r.GImethod==1) {
+ if (world==NULL) cout << "WARNING: need world background for skydome!\n";
+ writeHemilight();
+ }
+ else if (R.r.GImethod==2) writePathlight();
+ }
+
+ if (world==NULL) return false;
+
+ ostr.str("");
+ ostr << "<background type=\"constant\" name=\"world_background\" >\n";
+ ostr << "\t<color r=\"" << world->horr << "\" g=\"" << world->horg << "\" b=\"" << world->horb << "\" />\n";
+ ostr << "</background>\n\n";
+ xmlfile << ostr.str();
+
+ return true;
+}
+
+bool yafrayFileRender_t::executeYafray(const string &xmlpath)
+{
+ char yfr[8];
+ sprintf(yfr, "%d ", R.r.YF_numprocs);
+#ifdef WIN32
+ string command = command_path + "\\yafray -c " + yfr + "\"" + xmlpath + "\"";
+#else
+ string command = string("yafray -c ") + yfr + "\"" + xmlpath + "\"";
+#endif
+ return system(command.c_str())==0;
+}
+
diff --git a/source/blender/yafray/intern/export_File.h b/source/blender/yafray/intern/export_File.h
new file mode 100755
index 00000000000..69f47420d8c
--- /dev/null
+++ b/source/blender/yafray/intern/export_File.h
@@ -0,0 +1,33 @@
+#ifndef __EXPORT_FILE_H
+#define __EXPORT_FILE_H
+
+#include"yafray_Render.h"
+
+class yafrayFileRender_t : public yafrayRender_t
+{
+ public:
+ virtual ~yafrayFileRender_t() {}
+ protected:
+ std::string imgout;
+ std::ofstream xmlfile;
+ std::string xmlpath;
+ std::ostringstream ostr;
+
+ void displayImage();
+ bool executeYafray(const std::string &xmlpath);
+ virtual void writeTextures();
+ virtual void writeMaterialsAndModulators();
+ virtual void writeObject(Object* obj,
+ const std::vector<VlakRen*> &VLR_list, const float obmat[4][4]);
+ virtual void writeAllObjects();
+ virtual void writeLamps();
+ virtual void writeCamera();
+ virtual void writeHemilight();
+ virtual void writePathlight();
+ virtual bool writeWorld();
+ virtual bool writeRender();
+ virtual bool initExport();
+ virtual bool finishExport();
+};
+
+#endif
diff --git a/source/blender/yafray/intern/yafray_Render.cpp b/source/blender/yafray/intern/yafray_Render.cpp
index e0dde0efc2f..8096676f0db 100644
--- a/source/blender/yafray/intern/yafray_Render.cpp
+++ b/source/blender/yafray/intern/yafray_Render.cpp
@@ -10,71 +10,6 @@
using namespace std;
-#ifdef WIN32
-
-#include<windows.h>
-
-#ifndef FILE_MAXDIR
-#define FILE_MAXDIR 160
-#endif
-
-#ifndef FILE_MAXFILE
-#define FILE_MAXFILE 80
-#endif
-
-static string command_path = "";
-
-static string find_path()
-{
- HKEY hkey;
- DWORD dwType, dwSize;
-
- if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,"Software\\YafRay Team\\YafRay",0,KEY_READ,&hkey)==ERROR_SUCCESS)
- {
- dwType = REG_EXPAND_SZ;
- dwSize = MAX_PATH;
- DWORD dwStat;
-
- char *pInstallDir=new char[MAX_PATH];
-
- dwStat=RegQueryValueEx(hkey, TEXT("InstallDir"),
- NULL, NULL,(LPBYTE)pInstallDir, &dwSize);
-
- if (dwStat == NO_ERROR)
- {
- string res=pInstallDir;
- delete [] pInstallDir;
- return res;
- }
- else
- cout << "Couldn't READ \'InstallDir\' value. Is yafray correctly installed?\n";
- delete [] pInstallDir;
-
- RegCloseKey(hkey);
- }
- else
- cout << "Couldn't FIND registry key for yafray, is it installed?\n";
-
- return string("");
-
-}
-
-static int createDir(char* name)
-{
- if (BLI_exists(name))
- return 2; //exists
- if (CreateDirectory((LPCTSTR)(name), NULL)) {
- cout << "Directory: " << name << " created\n";
- return 1; // created
- }
- else {
- cout << "Could not create directory: " << name << endl;
- return 0; // fail
- }
-}
-
-#endif
-
void yafrayRender_t::clearAll()
{
all_objects.clear();
@@ -95,187 +30,37 @@ bool yafrayRender_t::exportScene()
mainCamLens = 35.0;
if (maincam_obj->type==OB_CAMERA) mainCamLens=((Camera*)maincam_obj->data)->lens;
- string xmlpath = "";
- bool dir_failed = false;
- // try the user setting setting first, export dir must be set and exist
- if (strlen(U.yfexportdir)==0) {
- cout << "No export directory set in user defaults!\n";
- dir_failed = true;
- }
- else {
- // check if it exists
- if (!BLI_exists(U.yfexportdir)) {
- cout << "YafRay temporary xml export directory:\n" << U.yfexportdir << "\ndoes not exist!\n";
-#ifdef WIN32
- // try to create it
- cout << "Trying to create...\n";
- if (createDir(U.yfexportdir)==0) dir_failed=true; else dir_failed=false;
-#else
- dir_failed = true;
-#endif
- }
- xmlpath = U.yfexportdir;
- }
-
-#ifdef WIN32
- // for windows try to get the path to the yafray binary from the registry, only done once
- if (command_path=="") {
- char path[FILE_MAXDIR+FILE_MAXFILE];
- string yafray_path = find_path();
- if (yafray_path=="") {
- // error already printed in find_path()
- clearAll();
- return false;
- }
- GetShortPathName((LPCTSTR)(yafray_path.c_str()), path, FILE_MAXDIR+FILE_MAXFILE);
- command_path = string(path);
- cout << "yafray path found: " << command_path << endl;
- }
- // if no export dir set, or could not create, try to create one in the yafray dir, unless it already exists
- if (dir_failed) {
- string ybdir = command_path + "\\YBtest";
- if (createDir(const_cast<char*>(ybdir.c_str()))==0) dir_failed=true; else dir_failed=false;
- xmlpath = ybdir;
- }
-#endif
-
- // for all
- if (dir_failed) {
- clearAll();
- return false;
- }
-
-#ifdef WIN32
- string DLM = "\\";
-#else
- string DLM = "/";
-#endif
- if (xmlpath.find_last_of(DLM)!=(xmlpath.length()-1)) xmlpath += DLM;
-
- imgout = xmlpath + "YBtest.tga";
- xmlpath += "YBtest.xml";
-
maxraydepth = 5; // will be set to maximum depth used in blender materials
// recreate the scene as object data, as well as sorting the material & textures, ignoring duplicates
- if (!getAllMatTexObs()) {
+ if (!getAllMatTexObs())
+ {
// error found, clear for next call
clearAll();
return false;
}
- // start the xml export
- xmlfile.open(xmlpath.c_str());
- if (xmlfile.fail()) {
- cout << "Could not open file\n";
+ if(!initExport())
+ {
clearAll();
return false;
}
- // file opened, start writing
-
- // make sure scientific notation is disabled for writing fp.nums, yafray doesn't like that
- ostr << setiosflags(ios::showpoint | ios::fixed);
-
- xmlfile << "<scene>\n\n";
-
// start actual data export
writeTextures();
writeMaterialsAndModulators();
writeAllObjects();
writeLamps();
- bool hasworld = writeWorld();
+ hasworld = writeWorld();
writeCamera();
-
- // finally export render block
- ostr.str("");
- ostr << "<render camera_name=\"MAINCAM\"\n";
- ostr << "\traydepth=\"" << maxraydepth << "\" gamma=\"" << R.r.YF_gamma << "\" exposure=\"" << R.r.YF_exposure << "\"\n";
-
- //if( (G.scene->world!=NULL) && (G.scene->world->GIquality>1) && ! G.scene->world->cache )
- if ((R.r.GImethod!=0) && (R.r.GIquality>1) && (!R.r.GIcache))
- ostr << "\tAA_passes=\"5\" AA_minsamples=\"5\" " << endl;
- else if ((R.r.mode & R_OSA) && (R.r.osa)) {
- int passes=(R.r.osa%4)==0 ? R.r.osa/4 : 1;
- int minsamples=(R.r.osa%4)==0 ? 4 : R.r.osa;
- ostr << "\tAA_passes=\"" << passes << "\" AA_minsamples=\"" << minsamples << "\"";
- }
- else ostr << "\tAA_passes=\"0\" AA_minsamples=\"1\"";
-
- ostr << "\n";
-
- if (hasworld) ostr << "\tbackground_name=\"world_background\"\n";
-
- ostr << "\tAA_pixelwidth=\"2\" AA_threshold=\"0.06\" bias=\"0.0001\" >\n";
-
- ostr << "\t<outfile value=\"" << imgout << "\" />\n";
-
- ostr << "</render>\n\n";
- xmlfile << ostr.str();
-
- xmlfile << "</scene>\n";
- xmlfile.close();
-
+ writeRender();
+
// clear for next call, before render to free some memory
clearAll();
- // file exported, now render
- if (executeYafray(xmlpath))
- displayImage();
- else
- {
+ if(!finishExport())
G.afbreek = 1; //stop render and anim if doing so
- cout << "Could not execute yafray. Is it in path?" << endl;
- return false;
- }
-
- return true;
-
-}
-
-
-// displays the image rendered with xml export
-// Now loads rendered image into blender renderbuf.
-void yafrayRender_t::displayImage()
-{
- // although it is possible to load the image using blender,
- // maybe it is best to just do a read here, for now the yafray output is always a raw tga anyway
-
- // rectot already freed in initrender
- R.rectot = (unsigned int *)MEM_callocN(sizeof(int)*R.rectx*R.recty, "rectot");
-
- FILE* fp = fopen(imgout.c_str(), "rb");
- if (fp==NULL) {
- cout << "YAF_displayImage(): Could not open image file\n";
- return;
- }
-
- unsigned char header[18];
- fread(&header, 1, 18, fp);
- unsigned short width = (unsigned short)(header[12] + (header[13]<<8));
- unsigned short height = (unsigned short)(header[14] + (header[15]<<8));
- unsigned char byte_per_pix = (unsigned char)(header[16]>>3);
- // read past any id (none in this case though)
- unsigned int idlen = (unsigned int)header[0];
- if (idlen) fseek(fp, idlen, SEEK_CUR);
-
- // read data directly into buffer, picture is upside down
- for (unsigned short y=0;y<height;y++) {
- unsigned char* bpt = (unsigned char*)R.rectot + ((((height-1)-y)*width)<<2);
- for (unsigned short x=0;x<width;x++) {
- bpt[2] = (unsigned char)fgetc(fp);
- bpt[1] = (unsigned char)fgetc(fp);
- bpt[0] = (unsigned char)fgetc(fp);
- if (byte_per_pix==4)
- bpt[3] = (unsigned char)fgetc(fp);
- else
- bpt[3] = 255;
- bpt += 4;
- }
- }
-
- fclose(fp);
- fp = NULL;
+ else return true;
}
@@ -379,838 +164,6 @@ bool yafrayRender_t::getAllMatTexObs()
}
-void yafrayRender_t::writeTextures()
-{
- for (map<string, pair<Material*, MTex*> >::const_iterator blendtex=used_textures.begin();
- blendtex!=used_textures.end();++blendtex) {
- Material* matr = blendtex->second.first;
- MTex* mtex = blendtex->second.second;
- Tex* tex = mtex->tex;
- switch (tex->type) {
- case TEX_STUCCI:
- // stucci is clouds as bump, but could be added to yafray to handle both wall in/out as well.
- // noisedepth must be at least 1 in yafray
- case TEX_CLOUDS: {
- ostr.str("");
- ostr << "<shader type=\"clouds\" name=\"" << blendtex->first << "\" >\n";
- ostr << "\t<attributes>\n";
- ostr << "\t\t<depth value=\"" << tex->noisedepth+1 << "\" />\n";
- ostr << "\t</attributes>\n";
- ostr << "</shader >\n\n";
- xmlfile << ostr.str();
- break;
- }
- case TEX_WOOD: {
- ostr.str("");
- ostr << "<shader type=\"wood\" name=\"" << blendtex->first << "\" >\n";
- ostr << "\t\t<attributes>\n";
- ostr << "\t\t<depth value=\"" << tex->noisedepth+1 << "\" />\n";
- ostr << "\t\t<turbulence value=\"" << tex->turbul << "\" />\n";
- ostr << "\t\t<ringscale_x value=\"" << mtex->size[0] << "\" />\n";
- ostr << "\t\t<ringscale_y value=\"" << mtex->size[1] << "\" />\n";
- string ts = "on";
- if (tex->noisetype==TEX_NOISESOFT) ts = "off";
- ostr << "\t\t<hard value=\"" << ts << "\" />\n";
- ostr << "\t</attributes>\n";
- ostr << "</shader>\n\n";
- xmlfile << ostr.str();
- break;
- }
- case TEX_MARBLE: {
- ostr.str("");
- ostr << "<shader type=\"marble\" name=\"" << blendtex->first << "\" >\n";
- ostr << "\t<attributes>\n";
- ostr << "\t\t<depth value=\"" << tex->noisedepth+1 << "\" />\n";
- ostr << "\t\t<turbulence value=\"" << tex->turbul << "\" />\n";
- string ts = "on";
- if (tex->noisetype==TEX_NOISESOFT) ts = "off";
- ostr << "\t\t<hard value=\"" << ts << "\" />\n";
- ts = "1";
- if (tex->stype==1) ts="5"; else if (tex->stype==2) ts="10";
- ostr << "\t\t<sharpness value=\"" << ts << "\" />\n";
- ostr << "\t</attributes>\n";
- ostr << "</shader>\n\n";
- xmlfile << ostr.str();
- break;
- }
- case TEX_IMAGE: {
- Image* ima = tex->ima;
- if (ima) {
- ostr.str("");
- ostr << "<shader type=\"image\" name=\"" << blendtex->first << "\" >\n";
- ostr << "\t<attributes>\n";
- // image->name is full path
- ostr << "\t\t<filename value=\"" << ima->name << "\" />\n";
- ostr << "\t</attributes>\n";
- ostr << "</shader>\n\n";
- xmlfile << ostr.str();
- }
- break;
- }
- default:
- cout << "Unsupported texture type\n";
- }
-
- // colorbands
- if (tex->flag & TEX_COLORBAND) {
- ColorBand* cb = tex->coba;
- if (cb) {
- ostr.str("");
- ostr << "<shader type=\"colorband\" name=\"" << blendtex->first + "_coba" << "\" >\n";
- ostr << "\t<attributes>\n";
- ostr << "\t\t<input value=\"" << blendtex->first << "\" />\n";
- ostr << "\t</attributes>\n";
- for (int i=0;i<cb->tot;i++) {
- ostr << "\t<modulator value=\"" << cb->data[i].pos << "\" >\n";
- ostr << "\t\t<color r=\"" << cb->data[i].r << "\"" <<
- " g=\"" << cb->data[i].g << "\"" <<
- " b=\"" << cb->data[i].b << "\" />\n";
- ostr << "\t</modulator>\n";
- }
- ostr << "</shader>\n\n";
- xmlfile << ostr.str();
- }
- }
-
- }
-}
-
-
-// write all materials & modulators
-void yafrayRender_t::writeMaterialsAndModulators()
-{
- for (map<string, Material*>::const_iterator blendmat=used_materials.begin();
- blendmat!=used_materials.end();++blendmat) {
-
- Material* matr = blendmat->second;
-
- // blendermappers
- for (int m=0;m<8;m++) {
-
- if (matr->septex & (1<<m)) continue;// all active channels
-
- // ignore null mtex
- MTex* mtex = matr->mtex[m];
- if (mtex==NULL) continue;
- // ignore null tex
- Tex* tex = mtex->tex;
- if (tex==NULL) continue;
-
- map<string, pair<Material*, MTex*> >::const_iterator mtexL = used_textures.find(string(tex->id.name+2));
- if (mtexL!=used_textures.end()) {
- ostr.str("");
- ostr << "<shader type=\"blendermapper\" name=\"" << blendmat->first + "_map" << m <<"\"";
- if ((mtex->texco & TEXCO_OBJECT) || (mtex->texco & TEXCO_REFL))
- {
- // For object & reflection mapping, add the object matrix to the modulator,
- // as in LF script, use camera matrix if no object specified.
- // In this case this means the inverse of that matrix
- float texmat[4][4], itexmat[4][4];
- if ((mtex->texco & TEXCO_OBJECT) && (mtex->object))
- MTC_Mat4CpyMat4(texmat, mtex->object->obmat);
- else // also for refl. map
- MTC_Mat4CpyMat4(texmat, maincam_obj->obmat);
- MTC_Mat4Invert(itexmat, texmat);
- ostr << "\n m00=\"" << itexmat[0][0] << "\" m01=\"" << itexmat[1][0]
- << "\" m02=\"" << itexmat[2][0] << "\" m03=\"" << itexmat[3][0] << "\"\n\t";
- ostr << " m10=\"" << itexmat[0][1] << "\" m11=\"" << itexmat[1][1]
- << "\" m12=\"" << itexmat[2][1] << "\" m13=\"" << itexmat[3][1] << "\"\n\t";
- ostr << " m20=\"" << itexmat[0][2] << "\" m21=\"" << itexmat[1][2]
- << "\" m22=\"" << itexmat[2][2] << "\" m23=\"" << itexmat[3][2] << "\"\n\t";
- ostr << " m30=\"" << itexmat[0][3] << "\" m31=\"" << itexmat[1][3]
- << "\" m32=\"" << itexmat[2][3] << "\" m33=\"" << itexmat[3][3] << "\">\n";
- }
- else ostr << ">\n";
- ostr << "\t<attributes>\n";
-
- if ((tex->flag & TEX_COLORBAND) & (tex->coba!=NULL))
- ostr << "\t\t<input value=\"" << mtexL->first + "_coba" << "\" />\n";
- else
- ostr << "\t\t<input value=\"" << mtexL->first << "\" />\n";
-
- // size, if the texturetype is clouds/marble/wood, also take noisesize into account
- float sc = 1;
- if ((tex->type==TEX_CLOUDS) || (tex->type==TEX_MARBLE) || (tex->type==TEX_WOOD)) {
- sc = tex->noisesize;
- if (sc!=0) sc = 1.f/sc;
-
- }
- // texture size
- ostr << "\t\t<sizex value=\"" << mtex->size[0]*sc << "\" />\n";
- ostr << "\t\t<sizey value=\"" << mtex->size[1]*sc << "\" />\n";
- ostr << "\t\t<sizez value=\"" << mtex->size[2]*sc << "\" />\n";
-
- // texture offset
- ostr << "\t\t<ofsx value=\"" << mtex->ofs[0] << "\" />\n";
- ostr << "\t\t<ofsy value=\"" << mtex->ofs[1] << "\" />\n";
- ostr << "\t\t<ofsz value=\"" << mtex->ofs[2] << "\" />\n";
-
- // texture coordinates, have to disable 'sticky' in Blender
- if ((mtex->texco & TEXCO_UV) || (matr->mode & MA_FACETEXTURE))
- ostr << "\t\t<texco value=\"uv\" />\n";
- else if ((mtex->texco & TEXCO_GLOB) || (mtex->texco & TEXCO_OBJECT))
- // object mode is also set as global, but the object matrix was specified above with <modulator..>
- ostr << "\t\t<texco value=\"global\" />\n";
- else if (mtex->texco & TEXCO_ORCO)
- ostr << "\t\t<texco value=\"orco\" />\n";
- else if (mtex->texco & TEXCO_WINDOW)
- ostr << "\t\t<texco value=\"window\" />\n";
- else if (mtex->texco & TEXCO_NORM)
- ostr << "\t\t<texco value=\"normal\" />\n";
- else if (mtex->texco & TEXCO_REFL)
- ostr << "\t\t<texco value=\"reflect\" />\n";
-
- // texture mapping parameters only relevant to image type
- if (tex->type==TEX_IMAGE) {
- if (mtex->mapping==MTEX_FLAT)
- ostr << "\t\t<mapping value=\"flat\" />\n";
- else if (mtex->mapping==MTEX_CUBE)
- ostr << "\t\t<mapping value=\"cube\" />\n";
- else if (mtex->mapping==MTEX_TUBE)
- ostr << "\t\t<mapping value=\"tube\" />\n";
- else if (mtex->mapping==MTEX_SPHERE)
- ostr << "\t\t<mapping value=\"sphere\" />\n";
-
- // texture projection axes
- string proj = "nxyz"; // 'n' for 'none'
- ostr << "\t\t<proj_x value=\"" << proj[mtex->projx] << "\" />\n";
- ostr << "\t\t<proj_y value=\"" << proj[mtex->projy] << "\" />\n";
- ostr << "\t\t<proj_z value=\"" << proj[mtex->projz] << "\" />\n";
-
- // repeat
- ostr << "\t\t<xrepeat value=\"" << tex->xrepeat << "\" />\n";
- ostr << "\t\t<yrepeat value=\"" << tex->yrepeat << "\" />\n";
-
- // clipping
- if (tex->extend==TEX_EXTEND)
- ostr << "\t\t<clipping value=\"extend\" />\n";
- else if (tex->extend==TEX_CLIP)
- ostr << "\t\t<clipping value=\"clip\" />\n";
- else if (tex->extend==TEX_CLIPCUBE)
- ostr << "\t\t<clipping value=\"clipcube\" />\n";
- else
- ostr << "\t\t<clipping value=\"repeat\" />\n";
-
- // crop min/max
- ostr << "\t\t<cropmin_x value=\"" << tex->cropxmin << "\" />\n";
- ostr << "\t\t<cropmin_y value=\"" << tex->cropymin << "\" />\n";
- ostr << "\t\t<cropmax_x value=\"" << tex->cropxmax << "\" />\n";
- ostr << "\t\t<cropmax_y value=\"" << tex->cropymax << "\" />\n";
-
- // rot90 flag
- string ts = "off";
- if (tex->imaflag & TEX_IMAROT) ts = "on";
- ostr << "\t\t<rot90 value=\"" << ts << "\" />\n";
- }
-
- ostr << "\t</attributes>\n";
- ostr << "</shader>\n\n";
-
- xmlfile << ostr.str();
- }
- }
-
- // blendershaders + modulators
- ostr.str("");
- ostr << "<shader type=\"blendershader\" name=\"" << blendmat->first << "\" >\n";
- ostr << "\t<attributes>\n";
- float diff=matr->alpha;
- ostr << "\t\t<color r=\"" << matr->r*diff << "\" g=\"" << matr->g*diff << "\" b=\"" << matr->b*diff << "\" />\n";
- ostr << "\t\t<specular_color r=\"" << matr->specr << "\" g=\"" << matr->specg << "\" b=\"" << matr->specb<< "\" />\n";
- ostr << "\t\t<mirror_color r=\"" << matr->mirr << "\" g=\"" << matr->mirg << "\" b=\"" << matr->mirb << "\" />\n";
- ostr << "\t\t<diffuse_reflect value=\"" << matr->ref << "\" />\n";
- ostr << "\t\t<specular_amount value=\"" << matr->spec << "\" />\n";
- ostr << "\t\t<hard value=\"" << matr->har << "\" />\n";
- ostr << "\t\t<alpha value=\"" << matr->alpha << "\" />\n";
- ostr << "\t\t<emit value=\"" << matr->emit << "\" />\n";
-
- // reflection/refraction
- if ( (matr->mode & MA_RAYMIRROR) || (matr->mode & MA_RAYTRANSP) )
- ostr << "\t\t<IOR value=\"" << matr->ang << "\" />\n";
- if (matr->mode & MA_RAYMIRROR) {
- float rf = matr->ray_mirror;
- // blender uses mir color for reflection as well
- ostr << "\t\t<reflected r=\"" << matr->mirr << "\" g=\"" << matr->mirg << "\" b=\"" << matr->mirb << "\" />\n";
- ostr << "\t\t<min_refle value=\""<< rf << "\" />\n";
- if (matr->ray_depth>maxraydepth) maxraydepth = matr->ray_depth;
- }
- if (matr->mode & MA_RAYTRANSP)
- {
- float tr=1.0-matr->alpha;
- ostr << "\t\t<transmitted r=\"" << matr->r * tr << "\" g=\"" << matr->g * tr << "\" b=\"" << matr->b * tr << "\" />\n";
- // tir on by default
- ostr << "\t\t<tir value=\"on\" />\n";
- if (matr->ray_depth_tra>maxraydepth) maxraydepth = matr->ray_depth_tra;
- }
-
- string Mmode = "";
- if (matr->mode & MA_TRACEBLE) Mmode += "traceable";
- if (matr->mode & MA_SHADOW) Mmode += " shadow";
- if (matr->mode & MA_SHLESS) Mmode += " shadeless";
- if (matr->mode & MA_VERTEXCOL) Mmode += " vcol_light";
- if (matr->mode & MA_VERTEXCOLP) Mmode += " vcol_paint";
- if (matr->mode & MA_ZTRA) Mmode += " ztransp";
- if (matr->mode & MA_ONLYSHADOW) Mmode += " onlyshadow";
- if (Mmode!="") ostr << "\t\t<matmodes value=\"" << Mmode << "\" />\n";
- ostr << "\t</attributes>\n";
- xmlfile << ostr.str();
-
- // modulators
- for (int m2=0;m2<8;m2++) {
-
- if (matr->septex & (1<<m2)) continue;// all active channels
-
- // ignore null mtex
- MTex* mtex = matr->mtex[m2];
- if (mtex==NULL) continue;
-
- // ignore null tex
- Tex* tex = mtex->tex;
- if (tex==NULL) continue;
-
- map<string, pair<Material*, MTex*> >::const_iterator mtexL = used_textures.find(string(tex->id.name+2));
- if (mtexL!=used_textures.end()) {
-
- ostr.str("");
- ostr << "\t<modulator>\n";
- ostr << "\t\t<input value=\"" << blendmat->first + "_map" << m2 << "\" />\n";
-
- // blendtype
- string ts = "mix";
- if (mtex->blendtype==MTEX_MUL) ts="mul";
- else if (mtex->blendtype==MTEX_ADD) ts="add";
- else if (mtex->blendtype==MTEX_SUB) ts="sub";
- ostr << "\t\t<mode value=\"" << ts << "\" />\n";
-
- // texture color (for use with MUL and/or no_rgb etc..)
- ostr << "\t\t<texcol r=\"" << mtex->r << "\" g=\"" << mtex->g << "\" b=\"" << mtex->b << "\" />\n";
-
- // texture contrast, brightness & color adjustment
- ostr << "\t\t<filtercolor r=\"" << tex->rfac << "\" g=\"" << tex->gfac << "\" b=\"" << tex->bfac << "\" />\n";
- ostr << "\t\t<contrast value=\"" << tex->contrast << "\" />\n";
- ostr << "\t\t<brightness value=\"" << tex->bright << "\" />\n";
-
- // all texture flags now are switches, having the value 1 or -1 (negative option)
- // the negative option only used for the intensity modulation options.
-
- // material (diffuse) color, amount controlled by colfac (see below)
- if (mtex->mapto & MAP_COL)
- ostr << "\t\t<color value=\"1\" />\n";
-
- // bumpmapping
- if ((mtex->mapto & MAP_NORM) || (mtex->maptoneg & MAP_NORM)) {
- // for yafray, bump factor is negated (unless negative option of 'Nor', is not affected by 'Neg')
- // scaled down quite a bit for yafray when image type, otherwise used directly
- float nf = -mtex->norfac;
- if (mtex->maptoneg & MAP_NORM) nf *= -1.f;
- if (tex->type==TEX_IMAGE) nf *= 2e-3f;
- ostr << "\t\t<normal value=\"" << nf << "\" />\n";
-
- }
-
- // all blender texture modulation as switches, either 1 or -1 (negative state of button)
- // Csp, specular color modulation
- if (mtex->mapto & MAP_COLSPEC)
- ostr << "\t\t<colspec value=\"1\" />\n";
-
- // CMir, mirror color modulation
- if (mtex->mapto & MAP_COLMIR)
- ostr << "\t\t<colmir value=\"1\" />\n";
-
- // Ref, diffuse reflection amount modulation
- if ((mtex->mapto & MAP_REF) || (mtex->maptoneg & MAP_REF)) {
- int t = 1;
- if (mtex->maptoneg & MAP_REF) t = -1;
- ostr << "\t\t<difref value=\"" << t << "\" />\n";
- }
-
- // Spec, specular amount mod
- if ((mtex->mapto & MAP_SPEC) || (mtex->maptoneg & MAP_SPEC)) {
- int t = 1;
- if (mtex->maptoneg & MAP_SPEC) t = -1;
- ostr << "\t\t<specular value=\"" << t << "\" />\n";
- }
-
- // hardness modulation
- if ((mtex->mapto & MAP_HAR) || (mtex->maptoneg & MAP_HAR)) {
- int t = 1;
- if (mtex->maptoneg & MAP_HAR) t = -1;
- ostr << "\t\t<hard value=\"" << t << "\" />\n";
- }
-
- // alpha modulation
- if ((mtex->mapto & MAP_ALPHA) || (mtex->maptoneg & MAP_ALPHA)) {
- int t = 1;
- if (mtex->maptoneg & MAP_ALPHA) t = -1;
- ostr << "\t\t<alpha value=\"" << t << "\" />\n";
-
- }
-
- // emit modulation
- if ((mtex->mapto & MAP_EMIT) || (mtex->maptoneg & MAP_EMIT)) {
- int t = 1;
- if (mtex->maptoneg & MAP_EMIT) t = -1;
- ostr << "\t\t<emit value=\"" << t << "\" />\n";
- }
-
- // texture flag, combination of strings
- if (mtex->texflag & (MTEX_RGBTOINT | MTEX_STENCIL | MTEX_NEGATIVE)) {
- ts = "";
- if (mtex->texflag & MTEX_RGBTOINT) ts += "no_rgb ";
- if (mtex->texflag & MTEX_STENCIL) ts += "stencil ";
- if (mtex->texflag & MTEX_NEGATIVE) ts += "negative";
- ostr << "\t\t<texflag value=\"" << ts << "\" />\n";
- }
-
- // colfac, controls amount of color modulation
- ostr << "\t\t<colfac value=\"" << mtex->colfac << "\" />\n";
-
- // def_var
- ostr << "\t\t<def_var value=\"" << mtex->def_var << "\" />\n";
-
- //varfac
- ostr << "\t\t<varfac value=\"" << mtex->varfac << "\" />\n";
-
- if ((tex->imaflag & (TEX_CALCALPHA | TEX_USEALPHA)) || (tex->flag & TEX_NEGALPHA)) {
- ts = "";
- if (tex->imaflag & TEX_CALCALPHA) ts += "calc_alpha ";
- if (tex->imaflag & TEX_USEALPHA) ts += "use_alpha ";
- if (tex->flag & TEX_NEGALPHA) ts += "neg_alpha";
- ostr << "\t\t<alpha_flag value=\"" << ts << "\" />\n";
- }
-
- ostr << "\t</modulator>\n";
- xmlfile << ostr.str();
-
- }
- }
- xmlfile << "</shader>\n\n";
- }
-}
-
-
-void yafrayRender_t::writeObject(Object* obj, const vector<VlakRen*> &VLR_list, const float obmat[4][4])
-{
- ostr.str("");
- // transform first (not necessarily actual obj->obmat, can be duplivert see below)
- ostr << "<transform m00=\"" << obmat[0][0] << "\" m01=\"" << obmat[1][0]
- << "\" m02=\"" << obmat[2][0] << "\" m03=\"" << obmat[3][0] << "\"\n";
- ostr << " m10=\"" << obmat[0][1] << "\" m11=\"" << obmat[1][1]
- << "\" m12=\"" << obmat[2][1] << "\" m13=\"" << obmat[3][1] << "\"\n";
- ostr << " m20=\"" << obmat[0][2] << "\" m21=\"" << obmat[1][2]
- << "\" m22=\"" << obmat[2][2] << "\" m23=\"" << obmat[3][2] << "\"\n";
- ostr << " m30=\"" << obmat[0][3] << "\" m31=\"" << obmat[1][3]
- << "\" m32=\"" << obmat[2][3] << "\" m33=\"" << obmat[3][3] << "\">\n";
- xmlfile << ostr.str();
-
- ostr.str("");
- ostr << "<object name=\"" << obj->id.name+2 << "\"";
- // yafray still needs default shader name in object def.,
- // since we write a shader with every face, simply use the material of the first face
- // if this is an empty string, assume default mat
- char* matname = VLR_list[0]->mat->id.name;
- bool shadow=VLR_list[0]->mat->mode & MA_TRACEBLE;
- ostr <<" shadow=\""<< (shadow ? "on" : "off" )<<"\" ";
- if (VLR_list[0]->mat->mode & MA_RAYTRANSP)
- ostr << "caus_IOR=\"" << VLR_list[0]->mat->ang << "\" ";
- if (strlen(matname)==0) matname = "blender_default"; else matname+=2; //skip MA id
- ostr << " shader_name=\"" << matname << "\" >\n";
- ostr << "\t<attributes>\n";
- if (VLR_list[0]->mat->mode & MA_RAYTRANSP)
- {
- float tr=1.0-VLR_list[0]->mat->alpha;
- ostr << "\t\t<caus_tcolor r=\"" << VLR_list[0]->mat->r * tr
- << "\" g=\"" << VLR_list[0]->mat->g * tr
- << "\" b=\"" << VLR_list[0]->mat->b * tr << "\" />\n";
- }
- ostr << "\t</attributes>\n";
- xmlfile << ostr.str();
-
- // if any face in the Blender mesh uses an orco texture, every face has orco coords,
- // so only need to check the first facevtx.orco in the list if they need to be exported
- bool EXPORT_ORCO = (VLR_list[0]->v1->orco!=NULL);
-
- string has_orco = "off";
- if (EXPORT_ORCO) has_orco = "on";
-
- // smooth shading if enabled
- bool no_auto = true; //in case non-mesh, or mesh has no autosmooth
- if (obj->type==OB_MESH) {
- Mesh* mesh = (Mesh*)obj->data;
-
- if (mesh->flag & ME_AUTOSMOOTH) {
- no_auto = false;
- ostr.str("");
- ostr << "\t<mesh autosmooth=\"" << mesh->smoothresh << "\" has_orco=\"" << has_orco << "\" >\n";
- xmlfile << ostr.str();
- }
- }
- // this for non-mesh as well
- if (no_auto) {
- // If AutoSmooth not used, since yafray currently cannot specify if a face is smooth
- // or flat shaded, the smooth flag of the first face is used to determine
- // the shading for the whole mesh
- if (VLR_list[0]->flag & ME_SMOOTH)
- xmlfile << "\t<mesh autosmooth=\"90\" has_orco=\"" << has_orco << "\" >\n";
- else
- xmlfile << "\t<mesh autosmooth=\"0.1\" has_orco=\"" << has_orco << "\" >\n"; //0 shows artefacts
- }
-
- // now all vertices
- map<VertRen*, int> vert_idx; // for removing duplicate verts and creating an index list
- int vidx = 0; // vertex index counter
-
- xmlfile << "\t\t<points>\n";
- for (vector<VlakRen*>::const_iterator fci=VLR_list.begin();
- fci!=VLR_list.end();++fci)
- {
- VlakRen* vlr = *fci;
- VertRen* ver;
- float* orco;
- ostr.str("");
- if (vert_idx.find(vlr->v1)==vert_idx.end()) {
- vert_idx[vlr->v1] = vidx++;
- ver = vlr->v1;
- ostr << "\t\t\t<p x=\"" << ver->co[0]
- << "\" y=\"" << ver->co[1]
- << "\" z=\"" << ver->co[2] << "\" />\n";
- if (EXPORT_ORCO) {
- orco = ver->orco;
- ostr << "\t\t\t<p x=\"" << orco[0]
- << "\" y=\"" << orco[1]
- << "\" z=\"" << orco[2] << "\" />\n";
- }
- }
- if (vert_idx.find(vlr->v2)==vert_idx.end()) {
- vert_idx[vlr->v2] = vidx++;
- ver = vlr->v2;
- ostr << "\t\t\t<p x=\"" << ver->co[0]
- << "\" y=\"" << ver->co[1]
- << "\" z=\"" << ver->co[2] << "\" />\n";
- if (EXPORT_ORCO) {
- orco = ver->orco;
- ostr << "\t\t\t<p x=\"" << orco[0]
- << "\" y=\"" << orco[1]
- << "\" z=\"" << orco[2] << "\" />\n";
- }
- }
- if (vert_idx.find(vlr->v3)==vert_idx.end()) {
- vert_idx[vlr->v3] = vidx++;
- ver = vlr->v3;
- ostr << "\t\t\t<p x=\"" << ver->co[0]
- << "\" y=\"" << ver->co[1]
- << "\" z=\"" << ver->co[2] << "\" />\n";
- if (EXPORT_ORCO) {
- orco = ver->orco;
- ostr << "\t\t\t<p x=\"" << orco[0]
- << "\" y=\"" << orco[1]
- << "\" z=\"" << orco[2] << "\" />\n";
- }
- }
- if ((vlr->v4) && (vert_idx.find(vlr->v4)==vert_idx.end())) {
- vert_idx[vlr->v4] = vidx++;
- ver = vlr->v4;
- ostr << "\t\t\t<p x=\"" << ver->co[0]
- << "\" y=\"" << ver->co[1]
- << "\" z=\"" << ver->co[2] << "\" />\n";
- if (EXPORT_ORCO) {
- orco = ver->orco;
- ostr << "\t\t\t<p x=\"" << orco[0]
- << "\" y=\"" << orco[1]
- << "\" z=\"" << orco[2] << "\" />\n";
- }
- }
- xmlfile << ostr.str();
- }
- xmlfile << "\t\t</points>\n";
-
- // all faces using the index list created above
- xmlfile << "\t\t<faces>\n";
- for (vector<VlakRen*>::const_iterator fci2=VLR_list.begin();
- fci2!=VLR_list.end();++fci2)
- {
- VlakRen* vlr = *fci2;
- Material* fmat = vlr->mat;
- bool EXPORT_VCOL = ((fmat->mode & (MA_VERTEXCOL|MA_VERTEXCOLP))!=0);
- char* fmatname = fmat->id.name;
- if (strlen(fmatname)==0) fmatname = "blender_default"; else fmatname+=2; //skip MA id
- TFace* uvc = vlr->tface; // possible uvcoords (v upside down)
- int idx1, idx2, idx3;
-
- idx1 = vert_idx.find(vlr->v1)->second;
- idx2 = vert_idx.find(vlr->v2)->second;
- idx3 = vert_idx.find(vlr->v3)->second;
-
- // make sure the indices point to the vertices when orco coords exported
- if (EXPORT_ORCO) { idx1*=2; idx2*=2; idx3*=2; }
-
- ostr.str("");
- ostr << "\t\t\t<f a=\"" << idx1 << "\" b=\"" << idx2 << "\" c=\"" << idx3 << "\"";
-
- if (uvc) {
- // use correct uv coords for this triangle
- if (vlr->flag & R_FACE_SPLIT) {
- ostr << " u_a=\"" << uvc->uv[0][0] << "\" v_a=\"" << 1-uvc->uv[0][1] << "\""
- << " u_b=\"" << uvc->uv[2][0] << "\" v_b=\"" << 1-uvc->uv[2][1] << "\""
- << " u_c=\"" << uvc->uv[3][0] << "\" v_c=\"" << 1-uvc->uv[3][1] << "\"";
- }
- else {
- ostr << " u_a=\"" << uvc->uv[0][0] << "\" v_a=\"" << 1-uvc->uv[0][1] << "\""
- << " u_b=\"" << uvc->uv[1][0] << "\" v_b=\"" << 1-uvc->uv[1][1] << "\""
- << " u_c=\"" << uvc->uv[2][0] << "\" v_c=\"" << 1-uvc->uv[2][1] << "\"";
- }
- }
-
- // since Blender seems to need vcols when uvs are used, for yafray only export when the material actually uses vcols
- if ((EXPORT_VCOL) && (vlr->vcol)) {
- // vertex colors
- float vr, vg, vb;
- vr = ((vlr->vcol[0] >> 24) & 255)/255.0;
- vg = ((vlr->vcol[0] >> 16) & 255)/255.0;
- vb = ((vlr->vcol[0] >> 8) & 255)/255.0;
- ostr << " vcol_a_r=\"" << vr << "\" vcol_a_g=\"" << vg << "\" vcol_a_b=\"" << vb << "\"";
- vr = ((vlr->vcol[1] >> 24) & 255)/255.0;
- vg = ((vlr->vcol[1] >> 16) & 255)/255.0;
- vb = ((vlr->vcol[1] >> 8) & 255)/255.0;
- ostr << " vcol_b_r=\"" << vr << "\" vcol_b_g=\"" << vg << "\" vcol_b_b=\"" << vb << "\"";
- vr = ((vlr->vcol[2] >> 24) & 255)/255.0;
- vg = ((vlr->vcol[2] >> 16) & 255)/255.0;
- vb = ((vlr->vcol[2] >> 8) & 255)/255.0;
- ostr << " vcol_c_r=\"" << vr << "\" vcol_c_g=\"" << vg << "\" vcol_c_b=\"" << vb << "\"";
- }
- ostr << " shader_name=\"" << fmatname << "\" />\n";
-
- if (vlr->v4) {
-
- idx1 = vert_idx.find(vlr->v3)->second;
- idx2 = vert_idx.find(vlr->v4)->second;
- idx3 = vert_idx.find(vlr->v1)->second;
-
- // make sure the indices point to the vertices when orco coords exported
- if (EXPORT_ORCO) { idx1*=2; idx2*=2; idx3*=2; }
-
- ostr << "\t\t\t<f a=\"" << idx1 << "\" b=\"" << idx2 << "\" c=\"" << idx3 << "\"";
-
- if (uvc) {
- ostr << " u_a=\"" << uvc->uv[2][0] << "\" v_a=\"" << 1-uvc->uv[2][1] << "\""
- << " u_b=\"" << uvc->uv[3][0] << "\" v_b=\"" << 1-uvc->uv[3][1] << "\""
- << " u_c=\"" << uvc->uv[0][0] << "\" v_c=\"" << 1-uvc->uv[0][1] << "\"";
- }
- if ((EXPORT_VCOL) && (vlr->vcol)) {
- // vertex colors
- float vr, vg, vb;
- vr = ((vlr->vcol[2] >> 24) & 255)/255.0;
- vg = ((vlr->vcol[2] >> 16) & 255)/255.0;
- vb = ((vlr->vcol[2] >> 8) & 255)/255.0;
- ostr << " vcol_a_r=\"" << vr << "\" vcol_a_g=\"" << vg << "\" vcol_a_b=\"" << vb << "\"";
- vr = ((vlr->vcol[3] >> 24) & 255)/255.0;
- vg = ((vlr->vcol[3] >> 16) & 255)/255.0;
- vb = ((vlr->vcol[3] >> 8) & 255)/255.0;
- ostr << " vcol_b_r=\"" << vr << "\" vcol_b_g=\"" << vg << "\" vcol_b_b=\"" << vb << "\"";
- vr = ((vlr->vcol[0] >> 24) & 255)/255.0;
- vg = ((vlr->vcol[0] >> 16) & 255)/255.0;
- vb = ((vlr->vcol[0] >> 8) & 255)/255.0;
- ostr << " vcol_c_r=\"" << vr << "\" vcol_c_g=\"" << vg << "\" vcol_c_b=\"" << vb << "\"";
- }
- ostr << " shader_name=\"" << fmatname << "\" />\n";
-
- }
- xmlfile << ostr.str();
- }
- xmlfile << "\t\t</faces>\n\t</mesh>\n</object>\n</transform>\n\n";
-}
-
-
-// write all objects
-void yafrayRender_t::writeAllObjects()
-{
-
- // first all objects except dupliverts (and main instance object for dups)
- for (map<Object*, vector<VlakRen*> >::const_iterator obi=all_objects.begin();
- obi!=all_objects.end(); ++obi)
- {
- // skip main duplivert, written later
- if (obi->first->flag & OB_YAF_DUPLISOURCE) continue;
- writeObject(obi->first, obi->second, obi->first->obmat);
- }
-
- // Now all duplivert objects (if any) as instances of main object
- // The original object has been included in the VlakRen renderlist above (see convertBlenderScene.c)
- // but is written here which all other duplis are instances of.
- float obmat[4][4], cmat[4][4], imat[4][4], nmat[4][4];
- for (map<string, vector<float> >::const_iterator dupMtx=dupliMtx_list.begin();
- dupMtx!=dupliMtx_list.end();++dupMtx) {
-
- // original inverse matrix, not actual matrix of object, but first duplivert.
- for (int i=0;i<4;i++)
- for (int j=0;j<4;j++)
- obmat[i][j] = dupMtx->second[(i<<2)+j];
- MTC_Mat4Invert(imat, obmat);
-
- // first object written as normal (but with transform of first duplivert)
- Object* obj = dup_srcob[dupMtx->first];
- writeObject(obj, all_objects[obj], obmat);
-
- // all others instances of first
- for (int curmtx=16;curmtx<dupMtx->second.size();curmtx+=16) { // number of 4x4 matrices
-
- // new mtx
- for (int i=0;i<4;i++)
- for (int j=0;j<4;j++)
- nmat[i][j] = dupMtx->second[curmtx+(i<<2)+j];
-
- MTC_Mat4MulMat4(cmat, imat, nmat); // transform with respect to original = inverse_original * new
-
- ostr.str("");
- // yafray matrix = transpose of Blender
- ostr << "<transform m00=\"" << cmat[0][0] << "\" m01=\"" << cmat[1][0]
- << "\" m02=\"" << cmat[2][0] << "\" m03=\"" << cmat[3][0] << "\"\n";
- ostr << " m10=\"" << cmat[0][1] << "\" m11=\"" << cmat[1][1]
- << "\" m12=\"" << cmat[2][1] << "\" m13=\"" << cmat[3][1] << "\"\n";
- ostr << " m20=\"" << cmat[0][2] << "\" m21=\"" << cmat[1][2]
- << "\" m22=\"" << cmat[2][2] << "\" m23=\"" << cmat[3][2] << "\"\n";
- ostr << " m30=\"" << cmat[0][3] << "\" m31=\"" << cmat[1][3]
- << "\" m32=\"" << cmat[2][3] << "\" m33=\"" << cmat[3][3] << "\">\n";
- xmlfile << ostr.str();
-
- // new name from original
- ostr.str("");
- ostr << "<object name=\"" << obj->id.name+2 << "_dup" << (curmtx>>4) << "\" original=\"" << obj->id.name+2 << "\" >\n";
- xmlfile << ostr.str();
- xmlfile << "\t<attributes>\n\t</attributes>\n\t<null/>\n</object>\n</transform>\n\n";
-
- }
-
- }
-
-}
-
-
-void yafrayRender_t::writeLamps()
-{
- // all lamps
- for (int i=0;i<R.totlamp;i++)
- {
- ostr.str("");
- LampRen* lamp = R.la[i];
- // TODO: add decay setting in yafray
- ostr << "<light type=\"";
- if (lamp->type==LA_LOCAL)
- ostr << "pointlight";
- else if (lamp->type==LA_SPOT)
- ostr << "spotlight";
- else if (lamp->type==LA_SUN) // for now, hemi == sun
- ostr << "sunlight";
- /* TODO
- else if (lamp->type==LA_AREA) {
- // new blender area light
- ostr << "arealight";
- }
- */
- else {
- // possibly unknown type, ignore
- cout << "Unknown Blender lamp type: " << lamp->type << endl;
- continue;
- }
- ostr << "\" name=\"LAMP" << i+1; //no name available here, create one
- // color already premultiplied by energy, so only need distance here
- float pwr;
- if (lamp->mode & LA_SPHERE) {
- // best approx. as used in LFexport script, however, in yafray it seems incorrect, so LF must use another model
- pwr = lamp->dist*(lamp->dist+1)*0.125;
- //decay = 2;
- }
- else {
- if ((lamp->type==LA_LOCAL) || (lamp->type==LA_SPOT)) {
- pwr = lamp->dist;
- //decay = 1;
- }
- else pwr = 1; // sun/hemi distance irrelevent.
- }
- ostr << "\" power=\"" << pwr;
- string lpmode="off";
- if ((lamp->mode & LA_SHAD) || (lamp->mode & LA_SHAD_RAY)) lpmode="on";;
- ostr << "\" cast_shadows=\"" << lpmode << "\"";
- // spot specific stuff
- if (lamp->type==LA_SPOT) {
- // conversion already changed spotsize to cosine of half angle
- float ld = 1-lamp->spotsi; //convert back to blender slider setting
- if (ld!=0) ld = 1.f/ld;
- ostr << " size=\"" << acos(lamp->spotsi)*180.0/M_PI << "\""
- << " blend=\"" << lamp->spotbl*ld << "\""
- << " beam_falloff=\"2\""; // no Blender equivalent (yet)
- }
- ostr << " >\n";
- // position
- ostr << "\t<from x=\"" << lamp->co[0] << "\" y=\"" << lamp->co[1] << "\" z=\"" << lamp->co[2] << "\" />\n";
- // 'to' for spot, already calculated by Blender
- if (lamp->type==LA_SPOT)
- ostr << "\t<to x=\"" << lamp->co[0]+1e6*lamp->vec[0]
- << "\" y=\"" << lamp->co[1]+1e6*lamp->vec[1]
- << "\" z=\"" << lamp->co[2]+1e6*lamp->vec[2] << "\" />\n";
- // color
- // rgb in LampRen is premultiplied by energy, power is compensated for that above
- ostr << "\t<color r=\"" << lamp->r << "\" g=\"" << lamp->g << "\" b=\"" << lamp->b << "\" />\n";
- ostr << "</light>\n\n";
- xmlfile << ostr.str();
- }
-}
-
-
-// write main camera
-void yafrayRender_t::writeCamera()
-{
- // here Global used again
- ostr.str("");
- ostr << "<camera name=\"MAINCAM\"";
-
- // render resolution including the percentage buttons (aleady calculated in initrender for R renderdata)
- int xres = R.r.xsch;
- int yres = R.r.ysch;
- ostr << " resx=\"" << xres << "\" resy=\"" << yres;
-
- // aspectratio can be set in Blender as well using aspX & aspY, need an extra param. for yafray cam.
- float aspect = 1;
- if (R.r.xsch < R.r.ysch) aspect = float(R.r.xsch)/float(R.r.ysch);
-
- ostr << "\" focal=\"" << mainCamLens/(aspect*32.0) << "\" >\n";
- xmlfile << ostr.str();
-
- // from, to, up vectors
- // comment in MTC_matrixops.h not correct, copy is arg2->arg1
- float camtx[4][4];
- MTC_Mat4CpyMat4(camtx, maincam_obj->obmat);
- MTC_normalise3DF(camtx[1]); //up
- MTC_normalise3DF(camtx[2]); //dir
- ostr.str("");
- ostr << "\t<from x=\"" << camtx[3][0] << "\""
- << " y=\"" << camtx[3][1] << "\""
- << " z=\"" << camtx[3][2] << "\" />\n";
- Object* dofob = findObject("OBFOCUS");
- if (dofob) {
- // dof empty found, modify lookat point accordingly
- // location from matrix, in case animated
- float fdx = dofob->obmat[3][0] - camtx[3][0];
- float fdy = dofob->obmat[3][1] - camtx[3][1];
- float fdz = dofob->obmat[3][2] - camtx[3][2];
- float fdist = sqrt(fdx*fdx + fdy*fdy + fdz*fdz);
- cout << "FOCUS object found, distance is: " << fdist << endl;
- ostr << "\t<to x=\"" << camtx[3][0] - fdist*camtx[2][0]
- << "\" y=\"" << camtx[3][1] - fdist*camtx[2][1]
- << "\" z=\"" << camtx[3][2] - fdist*camtx[2][2] << "\" />\n";
- }
- else {
- ostr << "\t<to x=\"" << camtx[3][0] - camtx[2][0]
- << "\" y=\"" << camtx[3][1] - camtx[2][1]
- << "\" z=\"" << camtx[3][2] - camtx[2][2] << "\" />\n";
- }
- ostr << "\t<up x=\"" << camtx[3][0] + camtx[1][0]
- << "\" y=\"" << camtx[3][1] + camtx[1][1]
- << "\" z=\"" << camtx[3][2] + camtx[1][2] << "\" />\n";
- xmlfile << ostr.str();
- xmlfile << "</camera>\n\n";
-}
-
void yafrayRender_t::addDupliMtx(Object* obj)
{
@@ -1243,105 +196,5 @@ bool yafrayRender_t::objectKnownData(Object* obj)
return false;
}
-void yafrayRender_t::writeHemilight()
-{
- ostr.str("");
- ostr << "<light type=\"hemilight\" name=\"hemi_LT\" power=\"" << R.r.GIpower << "\" ";
- switch (R.r.GIquality)
- {
- case 1 :
- case 2 : ostr << " samples=\"16\" >\n"; break;
- case 3 : ostr << " samples=\"36\" >\n"; break;
- case 4 : ostr << " samples=\"64\" >\n"; break;
- default: ostr << " samples=\"25\" >\n";
- }
- ostr << "</light>\n\n";
- xmlfile << ostr.str();
-}
-void yafrayRender_t::writePathlight()
-{
- ostr.str("");
- ostr << "<light type=\"pathlight\" name=\"path_LT\" power=\"" << R.r.GIpower << "\" ";
- ostr << " depth=\"" << R.r.GIdepth << "\" caus_depth=\"" << R.r.GIcausdepth <<"\"\n";
- if (R.r.GIcache)
- {
- switch (R.r.GIquality)
- {
- case 1 : ostr << " samples=\"128\" \n"; break;
- case 2 : ostr << " samples=\"256\" \n"; break;
- case 3 : ostr << " samples=\"512\" \n"; break;
- case 4 : ostr << " samples=\"1024\" \n"; break;
- default: ostr << " samples=\"512\" \n";
- }
- float aspect = 1;
- if (R.r.xsch < R.r.ysch) aspect = float(R.r.xsch)/float(R.r.ysch);
- float sbase = 2.0*atan(0.5/(mainCamLens/(aspect*32.0)))/float(R.r.xsch);
- ostr << " cache=\"on\" use_QMC=\"on\" \n";
- ostr << " cache_size=\"" << sbase*R.r.GIpixelspersample << "\" shadow_threshold=\"" <<
- 1.0 - R.r.GIshadowquality << "\" search=\"85\" gradient=\"" <<
- ((R.r.GIgradient)? "on" : "off") << "\" >\n";
- }
- else
- {
- switch (R.r.GIquality)
- {
- case 1 : ostr << " samples=\"16\" >\n"; break;
- case 2 : ostr << " samples=\"36\" >\n"; break;
- case 3 : ostr << " samples=\"64\" >\n"; break;
- case 4 : ostr << " samples=\"128\" >\n"; break;
- default: ostr << " samples=\"25\" >\n";
- }
- }
- ostr << "</light>\n\n";
- xmlfile << ostr.str();
-}
-
-bool yafrayRender_t::writeWorld()
-{
- World *world = G.scene->world;
-
- if (R.r.GIquality!=0) {
- if (R.r.GImethod==1) {
- if (world==NULL) cout << "WARNING: need world background for skydome!\n";
- writeHemilight();
- }
- else if (R.r.GImethod==2) writePathlight();
- }
-
- if (world==NULL) return false;
-
- ostr.str("");
- ostr << "<background type=\"constant\" name=\"world_background\" >\n";
- ostr << "\t<color r=\"" << world->horr << "\" g=\"" << world->horg << "\" b=\"" << world->horb << "\" />\n";
- ostr << "</background>\n\n";
- xmlfile << ostr.str();
-
- return true;
-}
-
-bool yafrayRender_t::executeYafray(const string &xmlpath)
-{
- char yfr[8];
- sprintf(yfr, "%d ", R.r.YF_numprocs);
-#ifdef WIN32
- string command = command_path + "\\yafray -c " + yfr + "\"" + xmlpath + "\"";
-#else
- string command = string("yafray -c ") + yfr + "\"" + xmlpath + "\"";
-#endif
- return system(command.c_str())==0;
-}
-
-
-yafrayRender_t YAFBLEND;
-
-extern "C"
-{
-
-int YAF_exportScene() { return (int)YAFBLEND.exportScene(); }
-void YAF_displayImage() { YAFBLEND.displayImage(); }
-void YAF_addDupliMtx(Object* obj) { YAFBLEND.addDupliMtx(obj); }
-int YAF_objectKnownData(Object* obj) { return (int)YAFBLEND.objectKnownData(obj); }
-
-}
diff --git a/source/blender/yafray/intern/yafray_Render.h b/source/blender/yafray/intern/yafray_Render.h
index 3a46f025115..4b6a679aa9d 100644
--- a/source/blender/yafray/intern/yafray_Render.h
+++ b/source/blender/yafray/intern/yafray_Render.h
@@ -65,55 +65,53 @@ extern void error (char *fmt, ...);
class yafrayRender_t
{
-public:
- // ctor
- yafrayRender_t() {}
- // dtor
- ~yafrayRender_t() {}
-
- // mtds
- bool exportScene();
-
- void displayImage();
- void addDupliMtx(Object* obj);
-
- bool objectKnownData(Object* obj);
-
-private:
- Object* maincam_obj;
- float mainCamLens;
-
- int maxraydepth;
-
- std::string imgout;
-
- std::ofstream xmlfile;
- std::ostringstream ostr;
- std::map<Object*, std::vector<VlakRen*> > all_objects;
- std::map<std::string, Material*> used_materials;
- std::map<std::string, std::pair<Material*, MTex*> > used_textures;
- std::map<std::string, std::vector<float> > dupliMtx_list;
- std::map<std::string, Object*> dup_srcob;
- std::map<void*, Object*> objectData;
-
- Object* findObject(const char* name);
- bool getAllMatTexObs();
- void writeTextures();
- void writeMaterialsAndModulators();
- void writeObject(Object* obj, const std::vector<VlakRen*> &VLR_list, const float obmat[4][4]);
- void writeAllObjects();
- void writeLamps();
- void writeCamera();
- void writeHemilight();
- void writePathlight();
- bool writeWorld();
- void clearAll();
- bool executeYafray(const std::string &xmlpath);
+ public:
+ // ctor
+ yafrayRender_t() {}
+ // dtor
+ virtual ~yafrayRender_t() {}
+
+ // mtds
+ bool exportScene();
+
+ void addDupliMtx(Object* obj);
+
+ bool objectKnownData(Object* obj);
+
+ protected:
+ Object* maincam_obj;
+ float mainCamLens;
+
+ int maxraydepth;
+ bool hasworld;
+
+ std::map<Object*, std::vector<VlakRen*> > all_objects;
+ std::map<std::string, Material*> used_materials;
+ std::map<std::string, std::pair<Material*, MTex*> > used_textures;
+ std::map<std::string, std::vector<float> > dupliMtx_list;
+ std::map<std::string, Object*> dup_srcob;
+ std::map<void*, Object*> objectData;
+
+ Object* findObject(const char* name);
+ bool getAllMatTexObs();
+
+ virtual void writeTextures()=0;
+ virtual void writeMaterialsAndModulators()=0;
+ virtual void writeObject(Object* obj, const std::vector<VlakRen*> &VLR_list, const float obmat[4][4])=0;
+ virtual void writeAllObjects()=0;
+ virtual void writeLamps()=0;
+ virtual void writeCamera()=0;
+ virtual void writeHemilight()=0;
+ virtual void writePathlight()=0;
+ virtual bool writeWorld()=0;
+ virtual bool writeRender()=0;
+ virtual bool initExport()=0;
+ virtual bool finishExport()=0;
+
+ void clearAll();
};
-/* C access to yafray */
-extern yafrayRender_t YAFBLEND;
#endif