diff options
Diffstat (limited to 'source/blender/yafray/intern/export_Plugin.cpp')
-rw-r--r-- | source/blender/yafray/intern/export_Plugin.cpp | 1990 |
1 files changed, 0 insertions, 1990 deletions
diff --git a/source/blender/yafray/intern/export_Plugin.cpp b/source/blender/yafray/intern/export_Plugin.cpp deleted file mode 100644 index 9d537f18667..00000000000 --- a/source/blender/yafray/intern/export_Plugin.cpp +++ /dev/null @@ -1,1990 +0,0 @@ -#include "export_Plugin.h" - -#include <math.h> - -#include <cstring> - -using namespace std; - - -#ifdef WIN32 -#define WIN32_SKIP_HKEY_PROTECTION -#include "BLI_winstuff.h" - -#ifndef FILE_MAXDIR -#define FILE_MAXDIR 160 -#endif - -#ifndef FILE_MAXFILE -#define FILE_MAXFILE 80 -#endif - - -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 - } -} - -extern "C" { extern char bprogname[]; } - -// add drive character if not in path string, using blender executable location as reference -static void addDrive(string &path) -{ - size_t sp = path.find_first_of(":"); - if (sp==-1) { - string blpath = bprogname; - sp = blpath.find_first_of(":"); - if (sp!=-1) path = blpath.substr(0, sp+1) + path; - } -} - -#else - -#include <sys/stat.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <signal.h> -#include <stdlib.h> -#include <unistd.h> -#endif - -static string YafrayPath() -{ -#ifdef WIN32 - string path=find_path(); - return path; -#else - static const char *alternative[]= - { - "/usr/local/lib/", -#ifdef __x86_64__ - "/usr/lib64/", -#endif - "/usr/lib/", - NULL - }; - - for(int i=0;alternative[i]!=NULL;++i) - { - string fp = string(alternative[i]) + "libyafrayplugin.so"; - struct stat st; - if (stat(fp.c_str(), &st)<0) continue; - if (st.st_mode & S_IROTH) return fp; - } - return ""; -#endif -} - -static string YafrayPluginPath() -{ -#ifdef WIN32 - return find_path()+"\\plugins"; -#else - static const char *alternative[]= - { - "/usr/local/lib/yafray", -#ifdef __x86_64__ - "/usr/lib64/yafray", -#endif - "/usr/lib/yafray", - NULL - }; - - for(int i=0;alternative[i]!=NULL;++i) - { - struct stat st; - if (stat(alternative[i], &st)<0) continue; - if (S_ISDIR(st.st_mode) && (st.st_mode & S_IXOTH)) return alternative[i]; - } - return ""; -#endif -} - - - -yafrayPluginRender_t::~yafrayPluginRender_t() -{ - if (yafrayGate!=NULL) delete yafrayGate; - if (handle!=NULL) PIL_dynlib_close(handle); -#ifdef WIN32 - if (corehandle!=NULL) PIL_dynlib_close(corehandle); -#endif -} - -bool yafrayPluginRender_t::initExport() -{ - // bug #1897: when forcing render without yafray present, handle can be valid, - // but find_symbol might have failed, trying second time will crash. - // So make sure plugin loaded correctly and only get handle once. - if ((!plugin_loaded) || (handle==NULL)) - { - string location = YafrayPath(); -#ifdef WIN32 - /* Win 32 loader cannot find needed libs in yafray dir, so we have to load them - * by hand. This could be fixed using setdlldirectory function, but it is not - * available in all win32 versions - */ - corehandle = PIL_dynlib_open((char *)(location + "\\yafraycore.dll").c_str()); - if (corehandle==NULL) - { - char *err = PIL_dynlib_get_error_as_string(corehandle); - if (err) cerr << "Error loading yafray plugin: " << err << endl; - else cerr << "Error loading yafray plugin: Unknown." << endl; - return false; - } - location += "\\yafrayplugin.dll"; -#endif - - if (handle==NULL) { - handle = PIL_dynlib_open((char *)location.c_str()); - if (handle==NULL) - { - cerr << "Error loading yafray plugin: " << PIL_dynlib_get_error_as_string(handle) << endl; - return false; - } - } - yafray::yafrayConstructor *constructor; - constructor = (yafray::yafrayConstructor *)PIL_dynlib_find_symbol(handle, (char*)YAFRAY_SYMBOL); - if (constructor==NULL) - { - cerr << "Error loading yafray plugin: " << PIL_dynlib_get_error_as_string(handle) << endl; - return false; - } - yafrayGate = constructor(re->r.threads, YafrayPluginPath()); - - cout << "YafRay plugin loaded" << endl; - plugin_loaded = true; - } - - return true; -} - -bool yafrayPluginRender_t::writeRender() -{ - yafray::paramMap_t params; - params["camera_name"]=yafray::parameter_t("MAINCAM"); - params["raydepth"]=yafray::parameter_t((float)re->r.YF_raydepth); - params["gamma"]=yafray::parameter_t(re->r.YF_gamma); - params["exposure"]=yafray::parameter_t(re->r.YF_exposure); - if (re->r.YF_AA) - { - params["AA_passes"] = yafray::parameter_t((int)re->r.YF_AApasses); - params["AA_minsamples"] = yafray::parameter_t(re->r.YF_AAsamples); - params["AA_pixelwidth"] = yafray::parameter_t(re->r.YF_AApixelsize); - params["AA_threshold"] = yafray::parameter_t(re->r.YF_AAthreshold); - } - else - { - // removed the default AA settings for midquality GI, better leave it to user - if ((re->r.mode & R_OSA) && (re->r.osa)) - { - params["AA_passes"] = yafray::parameter_t((re->r.osa & 3)==0 ? (re->r.osa >> 2) : 1); - params["AA_minsamples"] = yafray::parameter_t((re->r.osa & 3)==0 ? 4 : re->r.osa); - } - else - { - params["AA_passes"] = yafray::parameter_t(0); - params["AA_minsamples"] = yafray::parameter_t(1); - } - params["AA_pixelwidth"] = yafray::parameter_t(1.5); - params["AA_threshold"] = yafray::parameter_t(0.05f); - } - if (re->r.mode & R_BORDER) - { - params["border_xmin"] = yafray::parameter_t(2.f*re->r.border.xmin - 1.f); - params["border_xmax"] = yafray::parameter_t(2.f*re->r.border.xmax - 1.f); - params["border_ymin"] = yafray::parameter_t(2.f*re->r.border.ymin - 1.f); - params["border_ymax"] = yafray::parameter_t(2.f*re->r.border.ymax - 1.f); - } - if (hasworld) { - World *world = re->scene->world; - if (world->mode & WO_MIST) { - // basic fog - float fd = world->mistdist; - if (fd>0) fd=1.f/fd; else fd=1; - params["fog_density"] = yafray::parameter_t(fd); - params["fog_color"] = yafray::parameter_t(yafray::color_t(world->horr, world->horg, world->horb)); - } - params["background_name"] = yafray::parameter_t("world_background"); - } - params["bias"] = yafray::parameter_t(re->r.YF_raybias); - params["clamp_rgb"] = yafray::parameter_t((re->r.YF_clamprgb==0) ? "on" : "off"); - // lynx request - params["threads"] = yafray::parameter_t((int)re->r.threads); - blenderYafrayOutput_t output(re); - yafrayGate->render(params, output); - cout << "render finished" << endl; - yafrayGate->clear(); - return true; -} - -bool yafrayPluginRender_t::finishExport() -{ - return true; -} - - -// displayImage() not for plugin, see putPixel() below - -#ifdef WIN32 -#define MAXPATHLEN MAX_PATH -#else -#include <sys/param.h> -#endif -static void adjustPath(string &path) -{ - // if relative, expand to full path - char cpath[MAXPATHLEN]; - strcpy(cpath, path.c_str()); - BLI_convertstringcode(cpath, G.sce); - path = cpath; -#ifdef WIN32 - // add drive char if not there - addDrive(path); -#endif -} - - -static string noise2string(short nbtype) -{ - switch (nbtype) { - case TEX_BLENDER: - return "blender"; - case TEX_STDPERLIN: - return "stdperlin"; - case TEX_VORONOI_F1: - return "voronoi_f1"; - case TEX_VORONOI_F2: - return "voronoi_f2"; - case TEX_VORONOI_F3: - return "voronoi_f3"; - case TEX_VORONOI_F4: - return "voronoi_f4"; - case TEX_VORONOI_F2F1: - return "voronoi_f2f1"; - case TEX_VORONOI_CRACKLE: - return "voronoi_crackle"; - case TEX_CELLNOISE: - return "cellnoise"; - default: - case TEX_NEWPERLIN: - return "newperlin"; - } -} - -void yafrayPluginRender_t::writeTextures() -{ - // used to keep track of images already written - // (to avoid duplicates if also in imagetex for material TexFace texture) - set<Image*> dupimg; - - yafray::paramMap_t params; - list<yafray::paramMap_t> lparams; - for (map<string, MTex*>::const_iterator blendtex=used_textures.begin(); - blendtex!=used_textures.end();++blendtex) - { - lparams.clear(); - params.clear(); - - MTex* mtex = blendtex->second; - Tex* tex = mtex->tex; - // name is image name instead of texture name when type is image (see TEX_IMAGE case below) - // (done because of possible combinations of 'TexFace' images and regular image textures, to avoid duplicates) - if (tex->type!=TEX_IMAGE) params["name"] = yafray::parameter_t(blendtex->first); - - float nsz = tex->noisesize; - if (nsz!=0.f) nsz=1.f/nsz; - - // noisebasis type - string ntype = noise2string(tex->noisebasis); - string ts, hardnoise=(tex->noisetype==TEX_NOISESOFT) ? "off" : "on"; - - switch (tex->type) { - case TEX_STUCCI: - // stucci is clouds as bump, only difference is an extra parameter to handle wall in/out - // turbulence value is not used, so for large values will not match well - case TEX_CLOUDS: { - params["type"] = yafray::parameter_t("clouds"); - params["size"] = yafray::parameter_t(nsz); - params["hard"] = yafray::parameter_t(hardnoise); - if (tex->type==TEX_STUCCI) { - if (tex->stype==1) - ts = "positive"; - else if (tex->stype==2) - ts = "negative"; - else ts = "none"; - params["bias"] = yafray::parameter_t(ts); - params["depth"] = yafray::parameter_t(0); // for stucci always 0 - } - else params["depth"] = yafray::parameter_t(tex->noisedepth); - params["color_type"] = yafray::parameter_t(tex->stype); - params["noise_type"] = yafray::parameter_t(ntype); - break; - } - case TEX_WOOD: - { - params["type"] = yafray::parameter_t("wood"); - // blender does not use depth value for wood, always 0 - params["depth"] = yafray::parameter_t(0); - float turb = (tex->stype<2) ? 0.0 : tex->turbul; - params["turbulence"] = yafray::parameter_t(turb); - params["size"] = yafray::parameter_t(nsz); - params["hard"] = yafray::parameter_t(hardnoise); - ts = (tex->stype & 1) ? "rings" : "bands"; //stype 1&3 ringtype - params["wood_type"] = yafray::parameter_t(ts); - params["noise_type"] = yafray::parameter_t(ntype); - // shape parameter, for some reason noisebasis2 is used... - ts = "sin"; - if (tex->noisebasis2==1) ts="saw"; else if (tex->noisebasis2==2) ts="tri"; - params["shape"] = yafray::parameter_t(ts); - break; - } - case TEX_MARBLE: - { - params["type"] = yafray::parameter_t("marble"); - params["depth"] = yafray::parameter_t(tex->noisedepth); - params["turbulence"] = yafray::parameter_t(tex->turbul); - params["size"] = yafray::parameter_t(nsz); - params["hard"] = yafray::parameter_t(hardnoise); - params["sharpness"] = yafray::parameter_t((float)(1<<tex->stype)); - params["noise_type"] = yafray::parameter_t(ntype); - ts = "sin"; - if (tex->noisebasis2==1) ts="saw"; else if (tex->noisebasis2==2) ts="tri"; - params["shape"] = yafray::parameter_t(ts); - break; - } - case TEX_VORONOI: - { - params["type"] = yafray::parameter_t("voronoi"); - ts = "int"; - if (tex->vn_coltype==1) - ts = "col1"; - else if (tex->vn_coltype==2) - ts = "col2"; - else if (tex->vn_coltype==3) - ts = "col3"; - params["color_type"] = yafray::parameter_t(ts); - params["weight1"] = yafray::parameter_t(tex->vn_w1); - params["weight2"] = yafray::parameter_t(tex->vn_w2); - params["weight3"] = yafray::parameter_t(tex->vn_w3); - params["weight4"] = yafray::parameter_t(tex->vn_w4); - params["mk_exponent"] = yafray::parameter_t(tex->vn_mexp); - params["intensity"] = yafray::parameter_t(tex->ns_outscale); - params["size"] = yafray::parameter_t(nsz); - ts = "actual"; - if (tex->vn_distm==TEX_DISTANCE_SQUARED) - ts = "squared"; - else if (tex->vn_distm==TEX_MANHATTAN) - ts = "manhattan"; - else if (tex->vn_distm==TEX_CHEBYCHEV) - ts = "chebychev"; - else if (tex->vn_distm==TEX_MINKOVSKY_HALF) - ts = "minkovsky_half"; - else if (tex->vn_distm==TEX_MINKOVSKY_FOUR) - ts = "minkovsky_four"; - else if (tex->vn_distm==TEX_MINKOVSKY) - ts = "minkovsky"; - params["distance_metric"] = yafray::parameter_t(ts); - break; - } - case TEX_MUSGRAVE: - { - params["type"] = yafray::parameter_t("musgrave"); - switch (tex->stype) { - case TEX_MFRACTAL: - ts = "multifractal"; - break; - case TEX_RIDGEDMF: - ts = "ridgedmf"; - break; - case TEX_HYBRIDMF: - ts = "hybridmf"; - break; - case TEX_HTERRAIN: - ts = "heteroterrain"; - break; - default: - case TEX_FBM: - ts = "fBm"; - } - params["musgrave_type"] = yafray::parameter_t(ts); - params["noise_type"] = yafray::parameter_t(ntype); - params["H"] = yafray::parameter_t(tex->mg_H); - params["lacunarity"] = yafray::parameter_t(tex->mg_lacunarity); - params["octaves"] = yafray::parameter_t(tex->mg_octaves); - if ((tex->stype==TEX_HTERRAIN) || (tex->stype==TEX_RIDGEDMF) || (tex->stype==TEX_HYBRIDMF)) { - params["offset"] = yafray::parameter_t(tex->mg_offset); - if ((tex->stype==TEX_RIDGEDMF) || (tex->stype==TEX_HYBRIDMF)) - params["gain"] = yafray::parameter_t(tex->mg_gain); - } - params["size"] = yafray::parameter_t(nsz); - params["intensity"] = yafray::parameter_t(tex->ns_outscale); - break; - } - case TEX_DISTNOISE: - { - params["type"] = yafray::parameter_t("distorted_noise"); - params["distort"] = yafray::parameter_t(tex->dist_amount); - params["size"] = yafray::parameter_t(nsz); - params["noise_type1"] = yafray::parameter_t(ntype); - params["noise_type2"] = yafray::parameter_t(noise2string(tex->noisebasis2)); - break; - } - case TEX_BLEND: - { - params["type"] = yafray::parameter_t("gradient"); - switch (tex->stype) { - case 1: ts="quadratic"; break; - case 2: ts="cubic"; break; - case 3: ts="diagonal"; break; - case 4: ts="sphere"; break; - case 5: ts="halo"; break; - default: - case 0: ts="linear"; break; - } - params["gradient_type"] = yafray::parameter_t(ts); - if (tex->flag & TEX_FLIPBLEND) ts="on"; else ts="off"; - params["flip_xy"] = yafray::parameter_t(ts); - break; - } - case TEX_NOISE: - { - params["type"] = yafray::parameter_t("random_noise"); - params["depth"] = yafray::parameter_t(tex->noisedepth); - break; - } - case TEX_IMAGE: - { - Image* ima = tex->ima; - if (ima) { - // remember image to avoid duplicates later if also in imagetex - // (formerly done by removing from imagetex, but need image/material link) - dupimg.insert(ima); - params["type"] = yafray::parameter_t("image"); - params["name"] = yafray::parameter_t(ima->id.name); - string texpath = ima->name; - adjustPath(texpath); - params["filename"] = yafray::parameter_t(texpath); - params["interpolate"] = yafray::parameter_t((tex->imaflag & TEX_INTERPOL) ? "bilinear" : "none"); - } - break; - } - default: - cout << "Unsupported texture type\n"; - } - yafrayGate->addShader(params, lparams); - - // colorbands - if (tex->flag & TEX_COLORBAND) - { - ColorBand* cb = tex->coba; - if (cb) - { - lparams.clear(); - params.clear(); - params["type"] = yafray::parameter_t("colorband"); - params["name"] = yafray::parameter_t(blendtex->first + "_coba"); - params["input"] = yafray::parameter_t(blendtex->first); - for (int i=0;i<cb->tot;i++) - { - yafray::paramMap_t mparams; - mparams["value"] = yafray::parameter_t(cb->data[i].pos); - mparams["color"] = yafray::parameter_t(yafray::colorA_t(cb->data[i].r, - cb->data[i].g, - cb->data[i].b, - cb->data[i].a)); - lparams.push_back(mparams); - } - yafrayGate->addShader(params, lparams); - } - } - - } - - // If used, textures for the material 'TexFace' case - if (!imagetex.empty()) { - for (map<Image*, set<Material*> >::const_iterator imgtex=imagetex.begin(); - imgtex!=imagetex.end();++imgtex) - { - // skip if already written above - if (dupimg.find(imgtex->first)==dupimg.end()) { - lparams.clear(); - params.clear(); - params["name"] = yafray::parameter_t(imgtex->first->id.name); - params["type"] = yafray::parameter_t("image"); - string texpath(imgtex->first->name); - adjustPath(texpath); - params["filename"] = yafray::parameter_t(texpath); - yafrayGate->addShader(params, lparams); - } - } - } - -} - - -void yafrayPluginRender_t::writeShader(const string &shader_name, Material* matr, const string &facetexname) -{ - yafray::paramMap_t params; - list<yafray::paramMap_t> lparams; - - // if material has ramps, export colorbands first - if (matr->mode & (MA_RAMP_COL|MA_RAMP_SPEC)) - { - // both colorbands without input shader - ColorBand* cb = matr->ramp_col; - if ((matr->mode & MA_RAMP_COL) && (cb!=NULL)) - { - params["type"] = yafray::parameter_t("colorband"); - params["name"] = yafray::parameter_t(shader_name+"_difframp"); - for (int i=0;i<cb->tot;i++) { - yafray::paramMap_t mparams; - mparams["value"] = yafray::parameter_t(cb->data[i].pos); - mparams["color"] = yafray::parameter_t(yafray::colorA_t(cb->data[i].r, cb->data[i].g, cb->data[i].b, cb->data[i].a)); - lparams.push_back(mparams); - } - yafrayGate->addShader(params, lparams); - } - cb = matr->ramp_spec; - if ((matr->mode & MA_RAMP_SPEC) && (cb!=NULL)) - { - lparams.clear(); - params.clear(); - params["type"] = yafray::parameter_t("colorband"); - params["name"] = yafray::parameter_t(shader_name+"_specramp"); - for (int i=0;i<cb->tot;i++) { - yafray::paramMap_t mparams; - mparams["value"] = yafray::parameter_t(cb->data[i].pos); - mparams["color"] = yafray::parameter_t(yafray::colorA_t(cb->data[i].r, cb->data[i].g, cb->data[i].b, cb->data[i].a)); - lparams.push_back(mparams); - } - yafrayGate->addShader(params, lparams); - } - lparams.clear(); - params.clear(); - } - - params["type"] = yafray::parameter_t("blendershader"); - params["name"] = yafray::parameter_t(shader_name); - params["color"] = yafray::parameter_t(yafray::color_t(matr->r, matr->g, matr->b)); - float sr=matr->specr, sg=matr->specg, sb=matr->specb; - if (matr->spec_shader==MA_SPEC_WARDISO) { - // ........ - sr /= M_PI; - sg /= M_PI; - sb /= M_PI; - } - params["specular_color"] = yafray::parameter_t(yafray::color_t(sr, sg, sb)); - params["mirror_color"] = yafray::parameter_t(yafray::color_t(matr->mirr, matr->mirg, matr->mirb)); - params["diffuse_reflect"] = yafray::parameter_t(matr->ref); - params["specular_amount"] = yafray::parameter_t(matr->spec); - params["alpha"] = yafray::parameter_t(matr->alpha); - - // if no GI used, the GIpower parameter is not always initialized, so in that case ignore it - float bg_mult = (re->r.GImethod==0) ? 1 : re->r.GIpower; - params["emit"]=yafray::parameter_t(matr->emit*bg_mult); - - // reflection/refraction - if ( (matr->mode & MA_RAYMIRROR) || (matr->mode & MA_RAYTRANSP) ) - params["IOR"] = yafray::parameter_t(matr->ang); - - if (matr->mode & MA_RAYMIRROR) - { - // Sofar yafray's min_refle parameter (which misleadingly actually controls fresnel reflection offset) - // has been mapped to Blender's ray_mirror parameter. - // This causes it be be misinterpreted and misused as a reflection amount control however. - // Besides that, it also causes extra complications for the yafray Blendershader. - // So added an actual amount of reflection parameter instead, and another - // extra parameter 'frsOfs' to actually control fresnel offset (re-uses Blender fresnel_mir_i param). - params["reflect"] = yafray::parameter_t("on"); - params["reflect_amount"] = yafray::parameter_t(matr->ray_mirror); - float fo = 1.f-(matr->fresnel_mir_i-1.f)*0.25f; // blender param range [1,5], also here reversed (1 in Blender -> no fresnel) - params["fresnel_offset"] = yafray::parameter_t(fo); - - // for backward compatibility, also add old 'reflected' parameter, copy of mirror_color - params["reflected"] = yafray::parameter_t(yafray::color_t(matr->mirr, matr->mirg, matr->mirb)); - // same for 'min_refle' param. Instead of the ray_mirror parameter that was used before, since now - // the parameter's function is taken over by the fresnel offset parameter, use that instead. - params["min_refle"] = yafray::parameter_t(fo); - - } - - if (matr->mode & MA_RAYTRANSP) - { - params["refract"] = yafray::parameter_t("on"); - params["transmit_filter"] = yafray::parameter_t(matr->filter); - // tir on by default - params["tir"] = yafray::parameter_t("on"); - - // transmit absorption color - // to make things easier(?) for user it now specifies the actual color at 1 unit / YF_dscale of distance - const float maxlog = -log(1e-38); - float ar = (matr->YF_ar>0) ? -log(matr->YF_ar) : maxlog; - float ag = (matr->YF_ag>0) ? -log(matr->YF_ag) : maxlog; - float ab = (matr->YF_ab>0) ? -log(matr->YF_ab) : maxlog; - float sc = matr->YF_dscale; - if (sc!=0.f) sc=1.f/sc; - params["absorption"] = yafray::parameter_t(yafray::color_t(ar*sc, ag*sc, ab*sc)); - // dispersion - params["dispersion_power"] = yafray::parameter_t(matr->YF_dpwr); - params["dispersion_samples"] = yafray::parameter_t(matr->YF_dsmp); - params["dispersion_jitter"] = yafray::parameter_t(matr->YF_djit ? "on" : "off"); - - // for backward compatibility, also add old 'transmitted' parameter, copy of 'color' * (1-alpha) - float na = 1.f-matr->alpha; - params["transmitted"] = yafray::parameter_t(yafray::color_t(matr->r*na, matr->g*na, matr->b*na)); - } - - 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!="") params["matmodes"] = yafray::parameter_t(Mmode); - - // diffuse & specular brdf, lambert/cooktorr defaults - // diffuse - if (matr->diff_shader==MA_DIFF_ORENNAYAR) { - params["diffuse_brdf"] = yafray::parameter_t("oren_nayar"); - params["roughness"] = yafray::parameter_t(matr->roughness); - } - else if (matr->diff_shader==MA_DIFF_TOON) { - params["diffuse_brdf"] = yafray::parameter_t("toon"); - params["toondiffuse_size"] = yafray::parameter_t(matr->param[0]); - params["toondiffuse_smooth"] = yafray::parameter_t(matr->param[1]); - } - else if (matr->diff_shader==MA_DIFF_MINNAERT) { - params["diffuse_brdf"] = yafray::parameter_t("minnaert"); - params["darkening"] = yafray::parameter_t(matr->darkness); - } - else params["diffuse_brdf"] = yafray::parameter_t("lambert"); - // specular - if (matr->spec_shader==MA_SPEC_PHONG) { - params["specular_brdf"] = yafray::parameter_t("phong"); - params["hard"] = yafray::parameter_t(matr->har); - } - else if (matr->spec_shader==MA_SPEC_BLINN) { - params["specular_brdf"] = yafray::parameter_t("blinn"); - params["blinn_ior"] = yafray::parameter_t(matr->refrac); - params["hard"] = yafray::parameter_t(matr->har); - } - else if (matr->spec_shader==MA_SPEC_TOON) { - params["specular_brdf"] = yafray::parameter_t("toon"); - params["toonspecular_size"] = yafray::parameter_t(matr->param[2]); - params["toonspecular_smooth"] = yafray::parameter_t(matr->param[3]); - } - else if (matr->spec_shader==MA_SPEC_WARDISO) { - params["specular_brdf"] = yafray::parameter_t("ward"); - params["u_roughness"] = yafray::parameter_t(matr->rms); - params["v_roughness"] = yafray::parameter_t(matr->rms); - } - else { - params["specular_brdf"] = yafray::parameter_t("blender_cooktorr"); - params["hard"] = yafray::parameter_t(matr->har); - } - - // ramps, if used - if (matr->mode & (MA_RAMP_COL|MA_RAMP_SPEC)) - { - const string rm_blend[9] = {"mix", "add", "mul", "sub", "screen", "divide", "difference", "darken", "lighten"}; - const string rm_mode[4] = {"shader", "energy", "normal", "result"}; - // diffuse - if ((matr->mode & MA_RAMP_COL) && (matr->ramp_col!=NULL)) - { - params["diffuse_ramp"] = yafray::parameter_t(shader_name+"_difframp"); - params["diffuse_ramp_mode"] = yafray::parameter_t(rm_mode[(int)matr->rampin_col]); - params["diffuse_ramp_blend"] = yafray::parameter_t(rm_blend[(int)matr->rampblend_col]); - params["diffuse_ramp_factor"] = yafray::parameter_t(matr->rampfac_col); - } - // specular - if ((matr->mode & MA_RAMP_SPEC) && (matr->ramp_spec!=NULL)) { - params["specular_ramp"] = yafray::parameter_t(shader_name+"_specramp"); - params["specular_ramp_mode"] = yafray::parameter_t(rm_mode[(int)matr->rampin_spec]); - params["specular_ramp_blend"] = yafray::parameter_t(rm_blend[(int)matr->rampblend_spec]); - params["specular_ramp_factor"] = yafray::parameter_t(matr->rampfac_spec); - } - } - - // modulators - // first modulator is the texture of the face, if used (TexFace mode) - if (facetexname.length()!=0) { - yafray::paramMap_t mparams; - mparams["input"] = yafray::parameter_t(facetexname); - mparams["color"] = yafray::parameter_t(1); - lparams.push_back(mparams); - } - - for (int m2=0;m2<MAX_MTEX;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, MTex*>::const_iterator mtexL = used_textures.find(string(tex->id.name)); - if (mtexL!=used_textures.end()) - { - yafray::paramMap_t mparams; - // when no facetex used, shader_name is created from original material name - char temp[32]; - sprintf(temp,"_map%d", m2); - if (facetexname.length()!=0) - mparams["input"] = yafray::parameter_t(string(matr->id.name) + string(temp)); - else - mparams["input"] = yafray::parameter_t(shader_name + temp); - - // blendtype, would have been nice if the order would have been the same as for ramps... - const string blendtype[MTEX_NUM_BLENDTYPES] = {"mix", "mul", "add", "sub", "divide", "darken", "difference", "lighten", "screen", "hue", "sat", "val", "color"}; - mparams["mode"] = yafray::parameter_t(blendtype[(int)mtex->blendtype]); - - // texture color (for use with MUL and/or no_rgb etc..) - mparams["texcol"]=yafray::parameter_t(yafray::color_t(mtex->r,mtex->g,mtex->b)); - // texture contrast, brightness & color adjustment - mparams["filtercolor"]=yafray::parameter_t(yafray::color_t(tex->rfac,tex->gfac,tex->bfac)); - mparams["contrast"]=yafray::parameter_t(tex->contrast); - mparams["brightness"]=yafray::parameter_t(tex->bright); - // 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) - mparams["color"]=yafray::parameter_t(1.0); - // bumpmapping - if ((mtex->mapto & MAP_NORM) || (mtex->maptoneg & MAP_NORM)) - { - // for yafray, bump factor is negated (unless tex is stucci, not affected by 'Neg') - // scaled down quite a bit - float nf = mtex->norfac; - if (tex->type!=TEX_STUCCI) nf *= -1.f; - if (mtex->maptoneg & MAP_NORM) nf *= -1.f; - mparams["normal"] = yafray::parameter_t(nf/60.f); - } - - // all blender texture modulation as switches, either 1 or -1 (negative state of button) - // Csp, specular color modulation - if (mtex->mapto & MAP_COLSPEC) - mparams["colspec"] = yafray::parameter_t(1.0); - // CMir, mirror color modulation - if (mtex->mapto & MAP_COLMIR) - mparams["colmir"] = yafray::parameter_t(1.0); - - // Ref, diffuse reflection amount modulation - if ((mtex->mapto & MAP_REF) || (mtex->maptoneg & MAP_REF)) - { - int t = 1; - if (mtex->maptoneg & MAP_REF) t = -1; - mparams["difref"] = yafray::parameter_t(t); - } - - // Spec, specular amount mod - if ((mtex->mapto & MAP_SPEC) || (mtex->maptoneg & MAP_SPEC)) - { - int t = 1; - if (mtex->maptoneg & MAP_SPEC) t = -1; - mparams["specular"] = yafray::parameter_t(t); - } - - // hardness modulation - if ((mtex->mapto & MAP_HAR) || (mtex->maptoneg & MAP_HAR)) - { - int t = 1; - if (mtex->maptoneg & MAP_HAR) t = -1; - mparams["hard"] = yafray::parameter_t(t); - } - - // alpha modulation - if ((mtex->mapto & MAP_ALPHA) || (mtex->maptoneg & MAP_ALPHA)) - { - int t = 1; - if (mtex->maptoneg & MAP_ALPHA) t = -1; - mparams["alpha"] = yafray::parameter_t(t); - } - - // emit modulation - if ((mtex->mapto & MAP_EMIT) || (mtex->maptoneg & MAP_EMIT)) { - int t = 1; - if (mtex->maptoneg & MAP_EMIT) t = -1; - mparams["emit"] = yafray::parameter_t(t); - } - - // raymir modulation - if ((mtex->mapto & MAP_RAYMIRR) || (mtex->maptoneg & MAP_RAYMIRR)) { - int t = 1; - if (mtex->maptoneg & MAP_RAYMIRR) t = -1; - mparams["raymir"] = yafray::parameter_t(t); - } - - // texture flag, combination of strings - string ts; - 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"; - mparams["texflag"]=yafray::parameter_t(ts); - } - - // colfac, controls amount of color modulation - mparams["colfac"]=yafray::parameter_t(mtex->colfac); - // def_var - mparams["def_var"]=yafray::parameter_t(mtex->def_var); - //varfac - mparams["varfac"]=yafray::parameter_t(mtex->varfac); - - 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"; - mparams["alpha_flag"] = yafray::parameter_t(ts); - } - - // image as normalmap flag - if (tex->imaflag & TEX_NORMALMAP) mparams["normalmap"] = yafray::parameter_t("on"); - - lparams.push_back(mparams); - } - } - yafrayGate->addShader(params, lparams); - -} - -// write all materials & modulators -void yafrayPluginRender_t::writeMaterialsAndModulators() -{ - // shaders/mappers for regular texture (or non-texture) mode - // In case material has texface mode, and all faces have an image texture, - // this shader will not be used, but still be written - yafray::paramMap_t params; - list<yafray::paramMap_t> lparams; - for (map<string, Material*>::const_iterator blendmat=used_materials.begin(); - blendmat!=used_materials.end();++blendmat) - { - Material* matr = blendmat->second; - // mapper(s) - for (int m=0;m<MAX_MTEX;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, MTex*>::const_iterator mtexL = used_textures.find(string(tex->id.name)); - if (mtexL!=used_textures.end()) - { - params.clear(); //!!! - lparams.clear(); - char temp[32]; - sprintf(temp, "_map%d", m); - params["type"] = yafray::parameter_t("blendermapper"); - params["name"] = yafray::parameter_t(blendmat->first + string(temp)); - if ((mtex->texco & TEXCO_OBJECT) || (mtex->texco & TEXCO_REFL) || (mtex->texco & TEXCO_NORM)) - { - // For object, reflection & normal 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); -#define flp yafray::parameter_t - params["m00"]=flp(itexmat[0][0]); params["m01"]=flp(itexmat[1][0]); - params["m02"]=flp(itexmat[2][0]); params["m03"]=flp(itexmat[3][0]); - params["m10"]=flp(itexmat[0][1]); params["m11"]=flp(itexmat[1][1]); - params["m12"]=flp(itexmat[2][1]); params["m13"]=flp(itexmat[3][1]); - params["m20"]=flp(itexmat[0][2]); params["m21"]=flp(itexmat[1][2]); - params["m22"]=flp(itexmat[2][2]); params["m23"]=flp(itexmat[3][2]); - params["m30"]=flp(itexmat[0][3]); params["m31"]=flp(itexmat[1][3]); - params["m32"]=flp(itexmat[2][3]); params["m33"]=flp(itexmat[3][3]); -#undef flp - } - // use image name instead of texname when texture is image - if ((tex->type==TEX_IMAGE) && tex->ima) - params["input"] = yafray::parameter_t(tex->ima->id.name); - else if ((tex->flag & TEX_COLORBAND) & (tex->coba!=NULL)) - params["input"] = yafray::parameter_t(mtexL->first + "_coba"); - else - params["input"] = yafray::parameter_t(mtexL->first); - - // texture size - params["sizex"] = yafray::parameter_t(mtex->size[0]); - params["sizey"] = yafray::parameter_t(mtex->size[1]); - params["sizez"] = yafray::parameter_t(mtex->size[2]); - - // texture offset - params["ofsx"] = yafray::parameter_t(mtex->ofs[0]); - params["ofsy"] = yafray::parameter_t(mtex->ofs[1]); - params["ofsz"] = yafray::parameter_t(mtex->ofs[2]); - - // texture coordinates, have to disable 'sticky' in Blender - if (mtex->texco & TEXCO_UV) - params["texco"] = yafray::parameter_t("uv"); - 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..> - params["texco"] = yafray::parameter_t("global"); - else if ((mtex->texco & TEXCO_ORCO) || (mtex->texco & TEXCO_STRAND)) - // orco flag now used for 'strand'-mapping as well, see mesh code - params["texco"] = yafray::parameter_t("orco"); - else if (mtex->texco & TEXCO_WINDOW) - params["texco"] = yafray::parameter_t("window"); - else if (mtex->texco & TEXCO_NORM) - params["texco"] = yafray::parameter_t("normal"); - else if (mtex->texco & TEXCO_REFL) - params["texco"] = yafray::parameter_t("reflect"); - - // texture projection axes, both image & procedural - string proj = "nxyz"; // 'n' for 'none' - params["proj_x"] = yafray::parameter_t(string(1,proj[mtex->projx])); - params["proj_y"] = yafray::parameter_t(string(1,proj[mtex->projy])); - params["proj_z"] = yafray::parameter_t(string(1,proj[mtex->projz])); - - // texture mapping parameters only relevant to image type - if (tex->type==TEX_IMAGE) - { - if (mtex->mapping==MTEX_FLAT) - params["mapping"] = yafray::parameter_t("flat"); - else if (mtex->mapping==MTEX_CUBE) - params["mapping"] = yafray::parameter_t("cube"); - else if (mtex->mapping==MTEX_TUBE) - params["mapping"] = yafray::parameter_t("tube"); - else if (mtex->mapping==MTEX_SPHERE) - params["mapping"] = yafray::parameter_t("sphere"); - - // repeat - params["xrepeat"] = yafray::parameter_t(tex->xrepeat); - params["yrepeat"] = yafray::parameter_t(tex->yrepeat); - - // clipping - if (tex->extend==TEX_EXTEND) - params["clipping"] = yafray::parameter_t("extend"); - else if (tex->extend==TEX_CLIP) - params["clipping"] = yafray::parameter_t("clip"); - else if (tex->extend==TEX_CLIPCUBE) - params["clipping"] = yafray::parameter_t("clipcube"); - else if (tex->extend==TEX_CHECKER) { - params["clipping"] = yafray::parameter_t("checker"); - string ts = ""; - if (tex->flag & TEX_CHECKER_ODD) ts += "odd"; - if (tex->flag & TEX_CHECKER_EVEN) ts += " even"; - params["checker_mode"] = yafray::parameter_t(ts); - params["checker_dist"] = yafray::parameter_t(tex->checkerdist); - } - else - params["clipping"] = yafray::parameter_t("repeat"); - - // crop min/max - params["cropmin_x"] = yafray::parameter_t(tex->cropxmin); - params["cropmin_y"] = yafray::parameter_t(tex->cropymin); - params["cropmax_x"] = yafray::parameter_t(tex->cropxmax); - params["cropmax_y"] = yafray::parameter_t(tex->cropymax); - - // rot90 flag - if (tex->imaflag & TEX_IMAROT) - params["rot90"] = yafray::parameter_t("on"); - else - params["rot90"] = yafray::parameter_t("off"); - } - yafrayGate->addShader(params, lparams); - } - } - - // shader + modulators - writeShader(blendmat->first, matr); - - } - - // write the mappers & shaders for the TexFace case - if (!imagetex.empty()) { - // Yafray doesn't have per-face-textures, only per-face-shaders, - // so create as many mappers/shaders as the images used by the object - params.clear(); - lparams.clear(); - int snum = 0; - for (map<Image*, set<Material*> >::const_iterator imgtex=imagetex.begin(); - imgtex!=imagetex.end();++imgtex) - { - - for (set<Material*>::const_iterator imgmat=imgtex->second.begin(); - imgmat!=imgtex->second.end();++imgmat) - { - Material* matr = *imgmat; - // mapper - params["type"] = yafray::parameter_t("blendermapper"); - char temp[32]; - sprintf(temp, "_ftmap%d", snum); - params["name"] = yafray::parameter_t(string(matr->id.name) + string(temp)); - params["input"] = yafray::parameter_t(imgtex->first->id.name); - // all yafray default settings, except for texco, so no need to set others - params["texco"] = yafray::parameter_t("uv"); - yafrayGate->addShader(params, lparams); - - // shader, remember name, used later when writing per-face-shaders - sprintf(temp, "_ftsha%d", snum); - string shader_name = string(matr->id.name) + string(temp); - imgtex_shader[string(matr->id.name) + string(imgtex->first->id.name)] = shader_name; - - sprintf(temp, "_ftmap%d", snum++); - string facetexname = string(matr->id.name) + string(temp); - writeShader(shader_name, matr, facetexname); - } - - } - } - -} - -void yafrayPluginRender_t::genUVcoords(vector<yafray::GFLOAT> &uvcoords, ObjectRen *obr, VlakRen *vlr, MTFace* uvc, bool comple) -{ - if (uvc) - { - // tri uv split indices - int ui1=0, ui2=1, ui3=2; - if (vlr->flag & R_DIVIDE_24) { - ui3++; - if (vlr->flag & R_FACE_SPLIT) { ui1++; ui2++; } - } - else if (vlr->flag & R_FACE_SPLIT) { ui2++; ui3++; } - if (comple) { - ui1 = (ui1+2) & 3; - ui2 = (ui2+2) & 3; - ui3 = (ui3+2) & 3; - } - uvcoords.push_back(uvc->uv[ui1][0]); uvcoords.push_back(1-uvc->uv[ui1][1]); - uvcoords.push_back(uvc->uv[ui2][0]); uvcoords.push_back(1-uvc->uv[ui2][1]); - uvcoords.push_back(uvc->uv[ui3][0]); uvcoords.push_back(1-uvc->uv[ui3][1]); - } - else - { - uvcoords.push_back(0); uvcoords.push_back(0); - uvcoords.push_back(0); uvcoords.push_back(0); - uvcoords.push_back(0); uvcoords.push_back(0); - } -} - -void yafrayPluginRender_t::genVcol(vector<yafray::CFLOAT> &vcol, ObjectRen *obr, VlakRen *vlr, bool comple) -{ - MCol *mcol= RE_vlakren_get_mcol(obr, vlr, obr->actmcol, NULL, 0); - - if (mcol) - { - // tri vcol split indices - int ui1=0, ui2=1, ui3=2; - if (vlr->flag & R_DIVIDE_24) { - ui3++; - if (vlr->flag & R_FACE_SPLIT) { ui1++; ui2++; } - } - else if (vlr->flag & R_FACE_SPLIT) { ui2++; ui3++; } - if (comple) { - ui1 = (ui1+2) & 3; - ui2 = (ui2+2) & 3; - ui3 = (ui3+2) & 3; - } - unsigned char* pt = reinterpret_cast<unsigned char*>(&mcol[ui1]); - vcol.push_back((float)pt[3]/255.f); vcol.push_back((float)pt[2]/255.f); vcol.push_back((float)pt[1]/255.f); - pt = reinterpret_cast<unsigned char*>(&mcol[ui2]); - vcol.push_back((float)pt[3]/255.f); vcol.push_back((float)pt[2]/255.f); vcol.push_back((float)pt[1]/255.f); - pt = reinterpret_cast<unsigned char*>(&mcol[ui3]); - vcol.push_back((float)pt[3]/255.f); vcol.push_back((float)pt[2]/255.f); vcol.push_back((float)pt[1]/255.f); - } - else - { - vcol.push_back(0); vcol.push_back(0); vcol.push_back(0); - vcol.push_back(0); vcol.push_back(0); vcol.push_back(0); - vcol.push_back(0); vcol.push_back(0); vcol.push_back(0); - } -} - -void yafrayPluginRender_t::genFace(vector<int> &faces,vector<string> &shaders,vector<int> &faceshader, - vector<yafray::GFLOAT> &uvcoords,vector<yafray::CFLOAT> &vcol, - map<VertRen*, int> &vert_idx,ObjectRen *obr,VlakRen *vlr, - int has_orco,bool has_uv) -{ - Material* fmat = vlr->mat; - bool EXPORT_VCOL = ((fmat->mode & (MA_VERTEXCOL|MA_VERTEXCOLP))!=0); - string fmatname(fmat->id.name); - // use name in imgtex_shader list if 'TexFace' enabled for this face material - if (fmat->mode & MA_FACETEXTURE) { - MTFace* tface = RE_vlakren_get_tface(obr, vlr, obr->actmtface, NULL, 0); - if (tface) { - Image* fimg = (Image*)tface->tpage; - if (fimg) fmatname = imgtex_shader[fmatname + string(fimg->id.name)]; - } - } - else if (fmatname.length()==0) fmatname = "blender_default"; - bool newmat=true; - for(unsigned int i=0;i<shaders.size();++i) - if(shaders[i]==fmatname) - { - newmat=false; - faceshader.push_back(i); - break; - } - if(newmat) - { - shaders.push_back(fmatname); - faceshader.push_back(shaders.size()-1); - } - - MTFace* uvc = RE_vlakren_get_tface(obr, vlr, obr->actmtface, NULL, 0); // 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 (has_orco) { idx1*=2; idx2*=2; idx3*=2; } - - faces.push_back(idx1); faces.push_back(idx2); faces.push_back(idx3); - - if(has_uv) genUVcoords(uvcoords, obr, vlr, uvc); - if (EXPORT_VCOL) genVcol(vcol, obr, vlr); -} - -void yafrayPluginRender_t::genCompleFace(vector<int> &faces,/*vector<string> &shaders,*/vector<int> &faceshader, - vector<yafray::GFLOAT> &uvcoords,vector<yafray::CFLOAT> &vcol, - map<VertRen*, int> &vert_idx,ObjectRen *obr,VlakRen *vlr, - int has_orco,bool has_uv) -{ - Material* fmat = vlr->mat; - bool EXPORT_VCOL = ((fmat->mode & (MA_VERTEXCOL|MA_VERTEXCOLP))!=0); - - faceshader.push_back(faceshader.back()); - MTFace* uvc = RE_vlakren_get_tface(obr, vlr, obr->actmtface, NULL, 0); // possible uvcoords (v upside down) - int idx1, idx2, idx3; - 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 (has_orco) { idx1*=2; idx2*=2; idx3*=2; } - - faces.push_back(idx1); faces.push_back(idx2); faces.push_back(idx3); - - if (has_uv) genUVcoords(uvcoords, obr, vlr, uvc, true); - if (EXPORT_VCOL) genVcol(vcol, obr, vlr, true); -} - -void yafrayPluginRender_t::genVertices(vector<yafray::point3d_t> &verts, int &vidx, - map<VertRen*, int> &vert_idx, ObjectRen *obr, VlakRen* vlr, int has_orco, Object* obj) -{ - VertRen* ver; - float tvec[3]; // for back2world transform - - // for deformed objects, object->imat is no longer valid, - // so have to create inverse render matrix ourselves here - float mat[4][4], imat[4][4]; - MTC_Mat4MulMat4(mat, obj->obmat, re->viewmat); - MTC_Mat4Invert(imat, mat); - - if (vert_idx.find(vlr->v1)==vert_idx.end()) - { - vert_idx[vlr->v1] = vidx++; - ver = vlr->v1; - MTC_cp3Float(ver->co, tvec); - MTC_Mat4MulVecfl(imat, tvec); - verts.push_back(yafray::point3d_t(tvec[0], tvec[1], tvec[2])); - // has_orco now an int, if 1 -> strand mapping, if 2 -> normal orco mapping - if (has_orco==1) - verts.push_back(yafray::point3d_t(ver->accum)); - else if (has_orco==2) - verts.push_back(yafray::point3d_t(ver->orco[0], ver->orco[1], ver->orco[2])); - } - if (vert_idx.find(vlr->v2)==vert_idx.end()) - { - vert_idx[vlr->v2] = vidx++; - ver = vlr->v2; - MTC_cp3Float(ver->co, tvec); - MTC_Mat4MulVecfl(imat, tvec); - verts.push_back(yafray::point3d_t(tvec[0], tvec[1], tvec[2])); - // has_orco now an int, if 1 -> strand mapping, if 2 -> normal orco mapping - if (has_orco==1) - verts.push_back(yafray::point3d_t(ver->accum)); - else if (has_orco==2) - verts.push_back(yafray::point3d_t(ver->orco[0], ver->orco[1], ver->orco[2])); - } - if (vert_idx.find(vlr->v3)==vert_idx.end()) - { - vert_idx[vlr->v3] = vidx++; - ver = vlr->v3; - MTC_cp3Float(ver->co, tvec); - MTC_Mat4MulVecfl(imat, tvec); - verts.push_back(yafray::point3d_t(tvec[0], tvec[1], tvec[2])); - // has_orco now an int, if 1 -> strand mapping, if 2 -> normal orco mapping - if (has_orco==1) - verts.push_back(yafray::point3d_t(ver->accum)); - else if (has_orco==2) - verts.push_back(yafray::point3d_t(ver->orco[0], ver->orco[1], ver->orco[2])); - } - if ((vlr->v4) && (vert_idx.find(vlr->v4)==vert_idx.end())) - { - vert_idx[vlr->v4] = vidx++; - ver = vlr->v4; - MTC_cp3Float(ver->co, tvec); - MTC_Mat4MulVecfl(imat, tvec); - verts.push_back(yafray::point3d_t(tvec[0], tvec[1], tvec[2])); - // has_orco now an int, if 1 -> strand mapping, if 2 -> normal orco mapping - if (has_orco==1) - verts.push_back(yafray::point3d_t(ver->accum)); - else if (has_orco==2) - verts.push_back(yafray::point3d_t(ver->orco[0], ver->orco[1], ver->orco[2])); - } -} - -void yafrayPluginRender_t::writeObject(Object* obj, ObjectRen *obr, const vector<VlakRen*> &VLR_list, const float obmat[4][4]) -{ - float mtr[4*4]; - mtr[0*4+0]=obmat[0][0]; mtr[0*4+1]=obmat[1][0]; mtr[0*4+2]=obmat[2][0]; mtr[0*4+3]=obmat[3][0]; - mtr[1*4+0]=obmat[0][1]; mtr[1*4+1]=obmat[1][1]; mtr[1*4+2]=obmat[2][1]; mtr[1*4+3]=obmat[3][1]; - mtr[2*4+0]=obmat[0][2]; mtr[2*4+1]=obmat[1][2]; mtr[2*4+2]=obmat[2][2]; mtr[2*4+3]=obmat[3][2]; - mtr[3*4+0]=obmat[0][3]; mtr[3*4+1]=obmat[1][3]; mtr[3*4+2]=obmat[2][3]; mtr[3*4+3]=obmat[3][3]; - yafrayGate->transformPush(mtr); - - VlakRen* face0 = VLR_list[0]; - Material* face0mat = face0->mat; - - bool castShadows = face0mat->mode & MA_TRACEBLE; - float caus_IOR=1.0; - yafray::color_t caus_tcolor(0.0, 0.0, 0.0), caus_rcolor(0.0, 0.0, 0.0); - bool caus = (((face0->mat->mode & MA_RAYTRANSP) | (face0->mat->mode & MA_RAYMIRROR))!=0); - if (caus) { - caus_IOR = face0mat->ang; - float tr = 1.0-face0mat->alpha; - caus_tcolor.set(face0mat->r*tr, face0mat->g*tr, face0mat->b*tr); - tr = face0mat->ray_mirror; - caus_rcolor.set(face0mat->mirr*tr, face0mat->mirg*tr, face0mat->mirb*tr); - } - - // Export orco coords test. - // Previously was done by checking orco pointer, however this can be non-null but still not initialized. - // Test the rendermaterial texco flag instead. - // update2: bug #3193 it seems it has changed again with the introduction of static 'hair' particles, - // now it uses the vert pointer again as an extra test to make sure there are orco coords available - int has_orco = 0; - if (face0mat->texco & TEXCO_STRAND) - has_orco = 1; - else - has_orco = (((face0mat->texco & TEXCO_ORCO)!=0) && (face0->v1->orco!=NULL)) ? 2 : 0; - - bool no_auto = true; //in case non-mesh, or mesh has no autosmooth - float sm_angle = 0.1f; - if (obj->type==OB_MESH) - { - Mesh* mesh = (Mesh*)obj->data; - if (mesh->flag & ME_AUTOSMOOTH) { - sm_angle = mesh->smoothresh; - no_auto = false; - } - } - // this for non-mesh as well - if (no_auto) { - // no per face smooth flag in yafray, if AutoSmooth not used, - // use smooth flag of the first face instead - if (face0->flag & ME_SMOOTH) sm_angle=180; - } - vector<yafray::point3d_t> verts; - vector<yafray::CFLOAT> vcol; - // now all vertices - map<VertRen*, int> vert_idx; // for removing duplicate verts and creating an index list - int vidx = 0; // vertex index counter - bool has_uv=false; - for (vector<VlakRen*>::const_iterator fci=VLR_list.begin(); - fci!=VLR_list.end();++fci) - { - VlakRen* vlr = *fci; - genVertices(verts, vidx, vert_idx, obr, vlr, has_orco, obj); - if(RE_vlakren_get_tface(obr, vlr, obr->actmtface, NULL, 0)) has_uv=true; - } - // all faces using the index list created above - vector<int> faces; - vector<string> shaders; - vector<int> faceshader; - vector<yafray::GFLOAT> uvcoords; - for (vector<VlakRen*>::const_iterator fci2=VLR_list.begin(); - fci2!=VLR_list.end();++fci2) - { - VlakRen* vlr = *fci2; - genFace(faces, shaders, faceshader, uvcoords, vcol, vert_idx, obr, vlr, has_orco, has_uv); - if (vlr->v4) - genCompleFace(faces, faceshader, uvcoords, vcol, vert_idx, obr, vlr, has_orco, has_uv); - } - - // using the ObjectRen database, contruct a new name if object has a parent. - // This is done to prevent name clashes (group/library link related) - string obname(obj->id.name); - // previous implementation, keep around, in case this is still useful - //if (obj->id.flag & (LIB_EXTERN|LIB_INDIRECT))obname = "lib_" + obname; - ObjectRen *obren; - for (obren = static_cast<ObjectRen*>(re->objecttable.first); - obren; obren=static_cast<ObjectRen*>(obren->next)) - { - Object *db_ob = obren->ob, *db_par = obren->par; - if (db_ob==obj) - if ((db_ob!=NULL) && (db_par!=NULL)) { - obname += "_" + string(db_par->id.name); - break; - } - } - - yafrayGate->addObject_trimesh(obname, verts, faces, uvcoords, vcol, - shaders, faceshader, sm_angle, castShadows, true, true, caus, has_orco, - caus_rcolor, caus_tcolor, caus_IOR); - yafrayGate->transformPop(); -} - - -// write all objects -void yafrayPluginRender_t::writeAllObjects() -{ - // first all objects except dupliverts (and main instance object for dups) - for (map<Object*, yafrayObjectRen >::const_iterator obi=all_objects.begin(); - obi!=all_objects.end(); ++obi) - { - // skip main duplivert object if in dupliMtx_list, written later - Object* obj = obi->first; - if (dupliMtx_list.find(string(obj->id.name))!=dupliMtx_list.end()) continue; - writeObject(obj, obi->second.obr, obi->second.faces, obj->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].obr, all_objects[obj].faces, obmat); - - // all others instances of first - for (unsigned 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 - - float mtr[4*4]; - mtr[0*4+0]=cmat[0][0]; mtr[0*4+1]=cmat[1][0]; mtr[0*4+2]=cmat[2][0]; mtr[0*4+3]=cmat[3][0]; - mtr[1*4+0]=cmat[0][1]; mtr[1*4+1]=cmat[1][1]; mtr[1*4+2]=cmat[2][1]; mtr[1*4+3]=cmat[3][1]; - mtr[2*4+0]=cmat[0][2]; mtr[2*4+1]=cmat[1][2]; mtr[2*4+2]=cmat[2][2]; mtr[2*4+3]=cmat[3][2]; - mtr[3*4+0]=cmat[0][3]; mtr[3*4+1]=cmat[1][3]; mtr[3*4+2]=cmat[2][3]; mtr[3*4+3]=cmat[3][3]; - yafrayGate->transformPush(mtr); - - // new name from original - string name=(obj->id.name); - char temp[16]; - sprintf(temp,"_dup%d",(curmtx>>4)); - name+=temp; - yafrayGate->addObject_reference(name,obj->id.name); - yafrayGate->transformPop(); - } - - } -} - -void yafrayPluginRender_t::writeAreaLamp(LampRen* lamp, int num, float iview[4][4]) -{ - yafray::paramMap_t params; - - if (lamp->area_shape!=LA_AREA_SQUARE) return; - float *a=lamp->area[0], *b=lamp->area[1], *c=lamp->area[2], *d=lamp->area[3]; - float power=lamp->energy; - - string md = "off"; - // if no GI used, the GIphotons flag can still be set, so only use when 'full' selected - if ((re->r.GImethod==2) && (re->r.GIphotons)) { md="on"; power*=re->r.GIpower; } - params["type"]=yafray::parameter_t("arealight"); - char temp[16]; - sprintf(temp,"LAMP%d",num+1); - params["name"]=yafray::parameter_t(temp); - params["dummy"]=yafray::parameter_t(md); - params["power"]=yafray::parameter_t(power); - // samples not used for GI with photons, can still be exported, is ignored - int psm=0, sm = lamp->ray_totsamp; - if (sm>=25) psm = sm/5; - params["samples"]=yafray::parameter_t(sm); - params["psamples"]=yafray::parameter_t(psm); - - // transform area lamp coords back to world - float lpco[4][3]; - MTC_cp3Float(a, lpco[0]); - MTC_Mat4MulVecfl(iview, lpco[0]); - MTC_cp3Float(b, lpco[1]); - MTC_Mat4MulVecfl(iview, lpco[1]); - MTC_cp3Float(c, lpco[2]); - MTC_Mat4MulVecfl(iview, lpco[2]); - MTC_cp3Float(d, lpco[3]); - MTC_Mat4MulVecfl(iview, lpco[3]); - params["a"] = yafray::parameter_t(yafray::point3d_t(lpco[0][0], lpco[0][1], lpco[0][2])); - params["b"] = yafray::parameter_t(yafray::point3d_t(lpco[1][0], lpco[1][1], lpco[1][2])); - params["c"] = yafray::parameter_t(yafray::point3d_t(lpco[2][0], lpco[2][1], lpco[2][2])); - params["d"] = yafray::parameter_t(yafray::point3d_t(lpco[3][0], lpco[3][1], lpco[3][2])); - - params["color"]=yafray::parameter_t(yafray::color_t(lamp->r,lamp->g,lamp->b)); - yafrayGate->addLight(params); -} - -void yafrayPluginRender_t::writeLamps() -{ - GroupObject *go; - int i=0; - - // inver viewmatrix needed for back2world transform - float iview[4][4]; - // re->viewinv != inv.re->viewmat because of possible ortho mode (see convertBlenderScene.c) - // have to invert it here - MTC_Mat4Invert(iview, re->viewmat); - - // all lamps - for(go=(GroupObject *)re->lights.first; go; go= go->next, i++) - { - LampRen* lamp = (LampRen *)go->lampren; - - yafray::paramMap_t params; - string type=""; - - if (lamp->type==LA_AREA) { writeAreaLamp(lamp, i, iview); continue; } - - // TODO: add decay setting in yafray - bool is_softL=false, is_sphereL=false; - if (lamp->type==LA_LOCAL) { - if (lamp->mode & LA_YF_SOFT) { - // shadowmapped omnidirectional light - params["type"] = yafray::parameter_t("softlight"); - is_softL = true; - } - else if ((lamp->mode & LA_SHAD_RAY) && (lamp->YF_ltradius>0.0)) { - // area sphere, only when ray shadows enabled and radius>0.0 - params["type"] = yafray::parameter_t("spherelight"); - is_sphereL = true; - } - else params["type"] = yafray::parameter_t("pointlight"); - params["glow_intensity"] = yafray::parameter_t(lamp->YF_glowint); - params["glow_offset"] = yafray::parameter_t(lamp->YF_glowofs); - params["glow_type"] = yafray::parameter_t(lamp->YF_glowtype); - } - else if (lamp->type==LA_SPOT) - params["type"] = yafray::parameter_t("spotlight"); - else if ((lamp->type==LA_SUN) || (lamp->type==LA_HEMI)) // hemi exported as sun - params["type"] = yafray::parameter_t("sunlight"); - else if (lamp->type==LA_YF_PHOTON) - params["type"] = yafray::parameter_t("photonlight"); - else { - // possibly unknown type, ignore - cout << "Unknown Blender lamp type: " << lamp->type << endl; - continue; - } - - //no name available here, create one - char temp[16]; - sprintf(temp,"LAMP%d",i+1); - params["name"] = yafray::parameter_t(temp); - - // color already premultiplied by energy, so only need distance here - float pwr = 1; // default for sun/hemi, distance irrelevant - if ((lamp->type!=LA_SUN) && (lamp->type!=LA_HEMI)) { - if (lamp->mode & LA_SPHERE) { - // best approx. as used in LFexport script (LF d.f.m. 4pi?) - pwr = lamp->dist*(lamp->dist+1)*(0.25/M_PI); - //decay = 2; - } - else { - pwr = lamp->dist; - //decay = 1; - } - } - - if (is_sphereL) { - // 'dummy' mode for spherelight when used with gpm - string md = "off"; - // if no GI used, the GIphotons flag can still be set, so only use when 'full' selected - if ((re->r.GImethod==2) && (re->r.GIphotons)) { md="on"; pwr*=re->r.GIpower; } - params["power"] = yafray::parameter_t(pwr); - params["dummy"] = yafray::parameter_t(md); - } - else params["power"] = yafray::parameter_t(pwr); - - // cast_shadows flag not used with softlight, spherelight or photonlight - if ((!is_softL) && (!is_sphereL) && (lamp->type!=LA_YF_PHOTON)) { - string lpmode="off"; - // Blender hemilights exported as sunlights which might have shadow flag set - // should have cast_shadows set to off (reported by varuag) - if (lamp->type!=LA_HEMI) { - if (re->r.mode & R_SHADOW) { - // old bug was here since the yafray lamp settings panel was added, - // blender spotlight shadbuf flag should be ignored, since it is not in the panel anymore - if (lamp->mode & LA_SHAD_RAY) lpmode="on"; - } - } - params["cast_shadows"] = yafray::parameter_t(lpmode); - } - - // spot specific stuff - bool has_halo = ((lamp->type==LA_SPOT) && (lamp->mode & LA_HALO) && (lamp->haint>0.0)); - 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; - params["size"] = yafray::parameter_t(acos(lamp->spotsi)*180.0/M_PI); - params["blend"] = yafray::parameter_t(lamp->spotbl*ld); - params["beam_falloff"] = yafray::parameter_t(2.0); - // halo params - if (has_halo) { - params["halo"] = yafray::parameter_t("on"); - params["res"] = yafray::parameter_t(lamp->YF_bufsize); - int hsmp = ((12-lamp->shadhalostep)*16)/12; - hsmp = (hsmp+1)*16; // makes range (16, 272) for halostep(12, 0), good enough? - // halo 'samples' now 'stepsize' - // convert from old integer samples value to some reasonable stepsize - params["stepsize"] = yafray::parameter_t(1.0/sqrt((float)hsmp)); - params["shadow_samples"] = yafray::parameter_t(lamp->samp*lamp->samp); - params["halo_blur"] = yafray::parameter_t(0.0); - params["shadow_blur"] = yafray::parameter_t(lamp->soft*0.01f); - params["fog_density"] = yafray::parameter_t(lamp->haint*0.2f); - } - } - else if (is_softL) { - // softlight - params["res"] = yafray::parameter_t(lamp->YF_bufsize); - params["radius"] = yafray::parameter_t(lamp->soft); - params["bias"] = yafray::parameter_t(lamp->bias); - } - else if (is_sphereL) { - // spherelight - int psm=0, sm = lamp->ray_samp*lamp->ray_samp; - if (sm>=25) psm = sm/5; - params["radius"] = yafray::parameter_t(lamp->YF_ltradius); - params["samples"] = yafray::parameter_t(sm); - params["psamples"] = yafray::parameter_t(psm); - params["qmc_method"] = yafray::parameter_t(1); - } - else if (lamp->type==LA_YF_PHOTON) { - string qmc="off"; - if (lamp->YF_useqmc) qmc="on"; - params["photons"] = yafray::parameter_t(lamp->YF_numphotons); - params["search"] = yafray::parameter_t(lamp->YF_numsearch); - params["depth"] = yafray::parameter_t(lamp->YF_phdepth); - params["use_QMC"] = yafray::parameter_t(qmc); - params["angle"] = yafray::parameter_t(acos(lamp->spotsi)*180.0/M_PI); - float cl = lamp->YF_causticblur/sqrt((float)lamp->YF_numsearch); - params["fixedradius"] = yafray::parameter_t(lamp->YF_causticblur); - params["cluster"] = yafray::parameter_t(cl); - } - - // transform lamp co & vec back to world - float lpco[3], lpvec[3]; - MTC_cp3Float(lamp->co, lpco); - MTC_Mat4MulVecfl(iview, lpco); - MTC_cp3Float(lamp->vec, lpvec); - MTC_Mat4Mul3Vecfl(iview, lpvec); - - // position, (==-blendir for sun/hemi) - if ((lamp->type==LA_SUN) || (lamp->type==LA_HEMI)) - params["from"] = yafray::parameter_t(yafray::point3d_t(-lpvec[0], -lpvec[1], -lpvec[2])); - else - params["from"] = yafray::parameter_t(yafray::point3d_t(lpco[0], lpco[1], lpco[2])); - // 'to' for spot/photonlight, already calculated by Blender - if ((lamp->type==LA_SPOT) || (lamp->type==LA_YF_PHOTON)) { - params["to"] = yafray::parameter_t(yafray::point3d_t(lpco[0] + lpvec[0], - lpco[1] + lpvec[1], - lpco[2] + lpvec[2])); - if (has_halo) params["fog"] = yafray::parameter_t(yafray::color_t(1.0, 1.0, 1.0)); - } - - // color - // rgb in LampRen is premultiplied by energy, power is compensated for that above - params["color"] = yafray::parameter_t(yafray::color_t(lamp->r, lamp->g, lamp->b)); - yafrayGate->addLight(params); - } -} - -// write main camera -void yafrayPluginRender_t::writeCamera() -{ - yafray::paramMap_t params; - params["name"]=yafray::parameter_t("MAINCAM"); - if (re->r.mode & R_ORTHO) - params["type"] = yafray::parameter_t("ortho"); - else - params["type"] = yafray::parameter_t("perspective"); - - params["resx"] = yafray::parameter_t(re->winx); - params["resy"] = yafray::parameter_t(re->winy); - - float f_aspect = 1; - if ((re->winx * re->r.xasp) <= (re->winy * re->r.yasp)) - f_aspect = float(re->winx * re->r.xasp) / float(re->winy * re->r.yasp); - params["focal"] = yafray::parameter_t(mainCamLens/(f_aspect*32.f)); - // bug #4532, when field rendering is enabled, ycor is doubled - if (re->r.mode & R_FIELDS) - params["aspect_ratio"] = yafray::parameter_t(re->ycor * 0.5f); - else - params["aspect_ratio"] = yafray::parameter_t(re->ycor); - - // dof params, only valid for real camera - float fdist = 1; // only changes for ortho - if (maincam_obj->type==OB_CAMERA) { - Camera* cam = (Camera*)maincam_obj->data; - if (re->r.mode & R_ORTHO) fdist = cam->ortho_scale*(mainCamLens/32.f); - params["dof_distance"] = yafray::parameter_t(cam->YF_dofdist); - params["aperture"] = yafray::parameter_t(cam->YF_aperture); - if (cam->flag & CAM_YF_NO_QMC) - params["use_qmc"] = yafray::parameter_t("off"); - else - params["use_qmc"] = yafray::parameter_t("on"); - // bokeh params - string st = "disk1"; - if (cam->YF_bkhtype==1) - st = "disk2"; - else if (cam->YF_bkhtype==2) - st = "triangle"; - else if (cam->YF_bkhtype==3) - st = "square"; - else if (cam->YF_bkhtype==4) - st = "pentagon"; - else if (cam->YF_bkhtype==5) - st = "hexagon"; - else if (cam->YF_bkhtype==6) - st = "ring"; - params["bokeh_type"] = yafray::parameter_t(st); - st = "uniform"; - if (cam->YF_bkhbias==1) - st = "center"; - else if (cam->YF_bkhbias==2) - st = "edge"; - params["bokeh_bias"] = yafray::parameter_t(st); - params["bokeh_rotation"] = yafray::parameter_t(cam->YF_bkhrot); - } - - params["from"]=yafray::parameter_t( - yafray::point3d_t(maincam_obj->obmat[3][0], maincam_obj->obmat[3][1], maincam_obj->obmat[3][2])); - params["to"]=yafray::parameter_t( - yafray::point3d_t(maincam_obj->obmat[3][0] - fdist * re->viewmat[0][2], - maincam_obj->obmat[3][1] - fdist * re->viewmat[1][2], - maincam_obj->obmat[3][2] - fdist * re->viewmat[2][2])); - params["up"]=yafray::parameter_t( - yafray::point3d_t(maincam_obj->obmat[3][0] + re->viewmat[0][1], - maincam_obj->obmat[3][1] + re->viewmat[1][1], - maincam_obj->obmat[3][2] + re->viewmat[2][1])); - - yafrayGate->addCamera(params); -} - -void yafrayPluginRender_t::writeHemilight() -{ - yafray::paramMap_t params; - World *world = re->scene->world; - bool fromAO = false; - if (re->r.GIquality==6){ - // use Blender AO params is possible - if (world==NULL) return; - if ((world->mode & WO_AMB_OCC)==0) { - // no AO, use default GIquality - cout << "[Warning]: Can't use AO parameters\nNo ambient occlusion enabled, using default values instead" << endl; - } - else fromAO = true; - } - if (re->r.GIcache) { - params["type"] = yafray::parameter_t("pathlight"); - params["name"] = yafray::parameter_t("path_LT"); - params["power"] = yafray::parameter_t(re->r.GIpower); - params["mode"] = yafray::parameter_t("occlusion"); - params["ignore_bumpnormals"] = yafray::parameter_t(re->r.YF_nobump ? "on" : "off"); - if (fromAO) { - // for AO, with cache, using range of 32*1 to 32*16 seems good enough - params["samples"] = yafray::parameter_t(32*world->aosamp); - params["maxdistance"] = yafray::parameter_t(world->aodist); - } - else { - switch (re->r.GIquality) - { - case 1 : params["samples"] = yafray::parameter_t(128); break; - case 2 : params["samples"] = yafray::parameter_t(256); break; - case 3 : params["samples"] = yafray::parameter_t(512); break; - case 4 : params["samples"] = yafray::parameter_t(1024); break; - case 5 : params["samples"] = yafray::parameter_t(2048); break; - default: params["samples"] = yafray::parameter_t(256); - } - } - params["cache"] = yafray::parameter_t("on"); - params["use_QMC"] = yafray::parameter_t("on"); - params["threshold"] = yafray::parameter_t(re->r.GIrefinement); - params["cache_size"] = yafray::parameter_t((2.0/float(re->winx))*re->r.GIpixelspersample); - params["shadow_threshold"] = yafray::parameter_t(1.0 - re->r.GIshadowquality); - params["grid"] = yafray::parameter_t(82); - params["search"] = yafray::parameter_t(35); - } - else { - params["type"] = yafray::parameter_t("hemilight"); - params["name"] = yafray::parameter_t("hemi_LT"); - params["power"] = yafray::parameter_t(re->r.GIpower); - if (fromAO) { - // use minimum of 4 samples for lowest sample setting, single sample way too noisy - params["samples"] = yafray::parameter_t(3 + world->aosamp*world->aosamp); - params["maxdistance"] = yafray::parameter_t(world->aodist); - params["use_QMC"] = yafray::parameter_t((world->aomode & WO_AORNDSMP) ? "off" : "on"); - } - else { - switch (re->r.GIquality) - { - case 1 : - case 2 : params["samples"]=yafray::parameter_t(16); break; - case 3 : params["samples"]=yafray::parameter_t(36); break; - case 4 : params["samples"]=yafray::parameter_t(64); break; - case 5 : params["samples"]=yafray::parameter_t(128); break; - default: params["samples"]=yafray::parameter_t(25); - } - } - } - yafrayGate->addLight(params); -} - -void yafrayPluginRender_t::writePathlight() -{ - if (re->r.GIphotons) - { - yafray::paramMap_t params; - params["type"] = yafray::parameter_t("globalphotonlight"); - params["name"] = yafray::parameter_t("gpm"); - params["photons"] = yafray::parameter_t(re->r.GIphotoncount); - params["radius"] = yafray::parameter_t(re->r.GIphotonradius); - params["depth"] = yafray::parameter_t(((re->r.GIdepth>2) ? (re->r.GIdepth-1) : 1)); - params["caus_depth"] = yafray::parameter_t(re->r.GIcausdepth); - params["search"] = yafray::parameter_t(re->r.GImixphotons); - yafrayGate->addLight(params); - } - yafray::paramMap_t params; - params["type"] = yafray::parameter_t("pathlight"); - params["name"] = yafray::parameter_t("path_LT"); - params["power"] = yafray::parameter_t(re->r.GIindirpower); - params["depth"] = yafray::parameter_t(((re->r.GIphotons) ? 1 : re->r.GIdepth)); - params["caus_depth"] = yafray::parameter_t(re->r.GIcausdepth); - if (re->r.GIdirect && re->r.GIphotons) params["direct"] = yafray::parameter_t("on"); - if (re->r.GIcache && !(re->r.GIdirect && re->r.GIphotons)) - { - switch (re->r.GIquality) - { - case 1 : params["samples"] = yafray::parameter_t(128); break; - case 2 : params["samples"] = yafray::parameter_t(256); break; - case 3 : params["samples"] = yafray::parameter_t(512); break; - case 4 : params["samples"] = yafray::parameter_t(1024); break; - case 5 : params["samples"] = yafray::parameter_t(2048); break; - default: params["samples"] = yafray::parameter_t(256); - } - params["cache"] = yafray::parameter_t("on"); - params["use_QMC"] = yafray::parameter_t("on"); - params["threshold"] = yafray::parameter_t(re->r.GIrefinement); - params["cache_size"] = yafray::parameter_t((2.0/float(re->recty))*re->r.GIpixelspersample); - params["shadow_threshold"] = yafray::parameter_t(1.0 - re->r.GIshadowquality); - params["grid"] = yafray::parameter_t(82); - params["search"] = yafray::parameter_t(35); - params["ignore_bumpnormals"] = yafray::parameter_t(re->r.YF_nobump ? "on" : "off"); - } - else - { - switch (re->r.GIquality) - { - case 1 : params["samples"] = yafray::parameter_t(16); break; - case 2 : params["samples"] = yafray::parameter_t(36); break; - case 3 : params["samples"] = yafray::parameter_t(64); break; - case 4 : params["samples"] = yafray::parameter_t(128); break; - case 5 : params["samples"] = yafray::parameter_t(256); break; - default: params["samples"] = yafray::parameter_t(25); - } - } - yafrayGate->addLight(params); -} - -bool yafrayPluginRender_t::writeWorld() -{ - World *world = re->scene->world; - if (re->r.GIquality!=0) { - if (re->r.GImethod==1) { - if (world==NULL) cout << "WARNING: need world background for skydome!\n"; - writeHemilight(); - } - else if (re->r.GImethod==2) writePathlight(); - } - if (world==NULL) return false; - - yafray::paramMap_t params; - for (int i=0;i<MAX_MTEX;i++) { - MTex* wtex = world->mtex[i]; - if (!wtex) continue; - Image* wimg = wtex->tex->ima; - // now always exports if image used as world texture (and 'Hori' mapping enabled) - if ((wtex->tex->type==TEX_IMAGE) && (wimg!=NULL) && (wtex->mapto & WOMAP_HORIZ)) { - string wt_path = wimg->name; - adjustPath(wt_path); - params["type"] = yafray::parameter_t("image"); - params["name"] = yafray::parameter_t("world_background"); - // exposure_adjust not restricted to integer range anymore - params["exposure_adjust"] = yafray::parameter_t(wtex->tex->bright-1.f); - if (wtex->texco & TEXCO_ANGMAP) - params["mapping"] = yafray::parameter_t("probe"); - else if (wtex->texco & TEXCO_H_SPHEREMAP) // in yafray full sphere - params["mapping"] = yafray::parameter_t("sphere"); - else // assume 'tube' for anything else - params["mapping"] = yafray::parameter_t("tube"); - params["filename"] = yafray::parameter_t(wt_path); - params["interpolate"] = yafray::parameter_t((wtex->tex->imaflag & TEX_INTERPOL) ? "bilinear" : "none"); - if (wtex->tex->filtersize>1.f) params["prefilter"] = yafray::parameter_t("on"); - yafrayGate->addBackground(params); - return true; - } - } - - params.clear(); - params["type"] = yafray::parameter_t("constant"); - params["name"] = yafray::parameter_t("world_background"); - // if no GI used, the GIpower parameter is not always initialized, so in that case ignore it - // (have to change method to init yafray vars in Blender) - float bg_mult = (re->r.GImethod==0) ? 1 : re->r.GIpower; - params["color"]=yafray::parameter_t(yafray::color_t(world->horr * bg_mult, - world->horg * bg_mult, - world->horb * bg_mult)); - yafrayGate->addBackground(params); - return true; -} - -bool blenderYafrayOutput_t::putPixel(int x, int y, const yafray::color_t &c, - yafray::CFLOAT alpha, yafray::PFLOAT depth) -{ - // XXX how to get the image from Blender and write to it. This call doesn't allow to change buffer rects - RenderResult rres; - RE_GetResultImage(re, &rres); - // rres.rectx, rres.recty is width/height - // rres.rectf is float buffer, scanlines starting in bottom - // rres.rectz is zbuffer, available when associated pass is set - - const unsigned int maxy = rres.recty-1; - - if (re->r.mode & R_BORDER) { - // border render, blender renderwin is size of border region, - // but yafray returns coords relative to full resolution - x -= int(re->r.border.xmin * re->winx); - y -= int((1.f-re->r.border.ymax) * re->winy); - if ((x >= 0) && (x < re->rectx) && (y >= 0) && (y < re->recty)) - { - const unsigned int px = rres.rectx*(maxy - y); - // rgba - float* fpt = rres.rectf + ((px + x) << 2); - *fpt++ = c.R; - *fpt++ = c.G; - *fpt++ = c.B; - *fpt = alpha; - // depth values - if (rres.rectz) rres.rectz[px + x] = depth; - // to simplify things a bit, just do complete redraw here... - out++; - if ((out==4096) || ((x+y*re->rectx) == ((re->rectx-1)+(re->recty-1)*re->rectx))) { - re->result->renlay = render_get_active_layer(re, re->result); - re->display_draw(re->ddh, re->result, NULL); - out = 0; - } - } - if (re->test_break(re->tbh)) return false; - return true; - } - - const unsigned int px = (maxy - y)*rres.rectx; - - // rgba - float* fpt = rres.rectf + ((px + x) << 2); - *fpt++ = c.R; - *fpt++ = c.G; - *fpt++ = c.B; - *fpt = alpha; - - // depth values - if (rres.rectz) rres.rectz[px + x] = depth; - - // attempt to optimize drawing, by only drawing the tile currently rendered by yafray, - // and not the entire display every time (blender has to to do float->char conversion), - // but since the tile is not actually known, it has to be calculated from the coords. - // not sure if it really makes all that much difference at all... unless rendering really large pictures - // (renderwin.c also had to be adapted for this) - // tile start & end coords - const int txs = x & 0xffffffc0, tys = y & 0xffffffc0; - int txe = txs + 63, tye = tys + 63; - // tile border clip - if (txe >= rres.rectx) txe = rres.rectx-1; - if (tye >= rres.recty) tye = maxy; - // draw tile if last pixel reached - if ((y*rres.rectx + x) == (tye*rres.rectx + txe)) { - re->result->renlay = render_get_active_layer(re, re->result); - // note: ymin/ymax swapped here, img. upside down! - rcti rt = {txs, txe+1, maxy-tye, ((tys==0) ? maxy : (rres.recty-tys))}; // !!! tys can be zero - re->display_draw(re->ddh, re->result, &rt); - } - - if (re->test_break(re->tbh)) return false; - return true; -} |