diff options
-rw-r--r-- | source/blender/makesdna/DNA_scene_types.h | 6 | ||||
-rw-r--r-- | source/blender/python/api2_2x/sceneRender.c | 19 | ||||
-rw-r--r-- | source/blender/renderconverter/intern/convertBlenderScene.c | 4 | ||||
-rw-r--r-- | source/blender/src/buttons_scene.c | 12 | ||||
-rwxr-xr-x | source/blender/yafray/intern/export_File.cpp | 743 | ||||
-rwxr-xr-x | source/blender/yafray/intern/export_File.h | 6 | ||||
-rw-r--r-- | source/blender/yafray/intern/export_Plugin.cpp | 839 | ||||
-rw-r--r-- | source/blender/yafray/intern/export_Plugin.h | 12 | ||||
-rw-r--r-- | source/blender/yafray/intern/yafray_Render.cpp | 43 | ||||
-rw-r--r-- | source/blender/yafray/intern/yafray_Render.h | 6 |
10 files changed, 1035 insertions, 655 deletions
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index e674da04733..18c596f67e4 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -212,13 +212,13 @@ typedef struct RenderData { float postmul, postgamma, postadd, postigamma; /* yafray: global panel params. TODO: move elsewhere */ - short GIquality, GIcache, GImethod, GIgradient, GIphotons, GIdirect; - short YF_AA, YFexportxml; + short GIquality, GIcache, GImethod, GIphotons, GIdirect; + short YF_AA, YFexportxml, yfpad1[3]; int GIdepth, GIcausdepth, GIpixelspersample; int GIphotoncount, GImixphotons; float GIphotonradius; int YF_numprocs, YF_raydepth, YF_AApasses, YF_AAsamples; - float GIshadowquality, GIrefinement, GIpower; + float GIshadowquality, GIrefinement, GIpower, GIindirpower; float YF_gamma, YF_exposure, YF_raybias, YF_AApixelsize, YF_AAthreshold; char backbuf[160], pic[160], ftype[160]; diff --git a/source/blender/python/api2_2x/sceneRender.c b/source/blender/python/api2_2x/sceneRender.c index 7d6ba0cb7f7..d4a23c9e464 100644 --- a/source/blender/python/api2_2x/sceneRender.c +++ b/source/blender/python/api2_2x/sceneRender.c @@ -221,8 +221,6 @@ static PyObject *RenderData_YafrayGIShadowQuality( BPy_RenderData * self, PyObject * args ); static PyObject *RenderData_YafrayGIPixelsPerSample( BPy_RenderData * self, PyObject * args ); -static PyObject *RenderData_EnableYafrayGIGradient( BPy_RenderData * self, - PyObject * args ); static PyObject *RenderData_YafrayGIRefinement( BPy_RenderData * self, PyObject * args ); static PyObject *RenderData_YafrayRayBias( BPy_RenderData * self, @@ -451,9 +449,6 @@ static PyMethodDef BPy_RenderData_methods[] = { {"yafrayGIPixelsPerSample", ( PyCFunction ) RenderData_YafrayGIPixelsPerSample, METH_VARARGS, "(int) - get/set maximum number of pixels without samples, the lower the better and slower\n"}, - {"enableYafrayGIGradient", - ( PyCFunction ) RenderData_EnableYafrayGIGradient, METH_VARARGS, - "(bool) - enable/disable try to smooth lighting using a gradient\n"}, {"yafrayGIRefinement", ( PyCFunction ) RenderData_YafrayGIRefinement, METH_VARARGS, "(float) - get/setthreshold to refine shadows EXPERIMENTAL. 1 = no refinement\n"}, @@ -1793,20 +1788,6 @@ PyObject *RenderData_YafrayGIPixelsPerSample( BPy_RenderData * self, "YafrayGIMethod must be set to 'FULL' and GICache must be enabled\n" ) ); } -//------------------------------------RenderData.EnableYafrayGIGradient() -PyObject *RenderData_EnableYafrayGIGradient( BPy_RenderData * self, - PyObject * args ) -{ - if( self->renderContext->GImethod == 2 - && self->renderContext->GIcache == 1 ) { - return M_Render_BitToggleShort( args, 1, - &self->renderContext-> - GIgradient );; - } else - return ( EXPP_ReturnPyObjError( PyExc_StandardError, - "YafrayGIMethod must be set to 'FULL' and GICache must be enabled" ) ); -} - //------------------------------------RenderData.YafrayGIRefinement() ---- PyObject *RenderData_YafrayGIRefinement( BPy_RenderData * self, PyObject * args ) diff --git a/source/blender/renderconverter/intern/convertBlenderScene.c b/source/blender/renderconverter/intern/convertBlenderScene.c index 28fec81b491..5facd9081ec 100644 --- a/source/blender/renderconverter/intern/convertBlenderScene.c +++ b/source/blender/renderconverter/intern/convertBlenderScene.c @@ -3016,7 +3016,7 @@ void RE_rotateBlenderScene(void) free_duplilist(); } else { - /* yafray: if there are linked data objects (except lamps or empties), + /* yafray: if there are linked data objects (except lamps, empties or armatures), yafray only needs to know about one, the rest can be instanciated. The dupliMtx list is used for this purpose */ if (R.r.renderer==R_YAFRAY) { @@ -3027,7 +3027,7 @@ void RE_rotateBlenderScene(void) else init_render_object(ob); } - else if ((ob->type!=OB_EMPTY) && (ob->type!=OB_LAMP) && YAF_objectKnownData(ob)) + else if ((ob->type!=OB_EMPTY) && (ob->type!=OB_LAMP) && (ob->type!=OB_ARMATURE) && YAF_objectKnownData(ob)) printf("Added dupli matrix for linked data object %s\n", ob->id.name); else init_render_object(ob); diff --git a/source/blender/src/buttons_scene.c b/source/blender/src/buttons_scene.c index 232b30bffcf..a25472bc120 100644 --- a/source/blender/src/buttons_scene.c +++ b/source/blender/src/buttons_scene.c @@ -1281,10 +1281,9 @@ static void render_panel_yafrayGI() 70,150,89,20, &G.scene->r.GIquality, 0, 0, 0, 0, "Global Illumination Quality"); if (G.scene->r.GImethod>0) { - if (G.scene->r.GIpower==0) G.scene->r.GIpower=1; - uiDefButF(block, NUM, B_DIFF, "Power:", 5,10,154,20, &G.scene->r.GIpower, 0.01, 100.0, 10, 0, "GI lighting intensity scale, 1 is normal"); + uiDefButF(block, NUM, B_DIFF, "EmitPwr:", 5,35,154,20, &G.scene->r.GIpower, 0.01, 100.0, 10, 0, "arealight, material emit and background intensity scaling, 1 is normal"); + if (G.scene->r.GImethod==2) uiDefButF(block, NUM, B_DIFF, "GI Pwr:", 5,10,154,20, &G.scene->r.GIindirpower, 0.01, 100.0, 10, 0, "GI indirect lighting intensity scaling, 1 is normal"); } - if (G.scene->r.GImethod==2) { @@ -1300,9 +1299,8 @@ static void render_panel_yafrayGI() uiDefButF(block, NUM, B_DIFF,"ShadQu:", 5,85,154,20, &(G.scene->r.GIshadowquality), 0.01, 1.0 ,1,0, "Sets the shadow quality, keep it under 0.95 :-) "); if (G.scene->r.GIpixelspersample==0) G.scene->r.GIpixelspersample=10; uiDefButI(block, NUM, B_DIFF, "Prec:", 5,60,75,20, &G.scene->r.GIpixelspersample, 1, 50, 10, 10, "Maximum number of pixels without samples, the lower the better and slower"); - uiDefButS(block,TOG|BIT|0, B_DIFF, "Gradient", 84,60,75,20, &G.scene->r.GIgradient, 0, 0, 0, 0, "Try to smooth lighting using a gradient"); if (G.scene->r.GIrefinement==0) G.scene->r.GIrefinement=1.0; - uiDefButF(block, NUM, B_DIFF, "Refinement:", 5,35,154,20, &G.scene->r.GIrefinement, 0.001, 1.0, 1, 0, "Threshold to refine shadows EXPERIMENTAL. 1 = no refinement"); + uiDefButF(block, NUM, B_DIFF, "Ref:", 80,60,75,20, &G.scene->r.GIrefinement, 0.001, 1.0, 1, 0, "Threshold to refine shadows EXPERIMENTAL. 1 = no refinement"); } if (G.scene->r.GIphotons) { @@ -1315,7 +1313,7 @@ static void render_panel_yafrayGI() 0.00001, 100.0 ,0,0, "Radius to search for photons to mix (blur)"); if(G.scene->r.GImixphotons==0) G.scene->r.GImixphotons=100; uiDefButI(block, NUM, B_DIFF, "MixCount:", 170,35,140,20, &G.scene->r.GImixphotons, - 0, 1000, 10, 10, "Number of photons to shoot"); + 0, 1000, 10, 10, "Number of photons to mix"); uiDefButS(block,TOG|BIT|0, B_REDR, "Tune Photons",170,10,140,20, &G.scene->r.GIdirect, 0, 0, 0, 0, "Show the photonmap directly in the render for tuning"); } @@ -1373,6 +1371,8 @@ void render_panels() if (G.scene->r.YF_raydepth==0) G.scene->r.YF_raydepth=5; if (G.scene->r.YF_AApixelsize==0.0) G.scene->r.YF_AApixelsize=1.5; if (G.scene->r.YF_AAthreshold==0.0) G.scene->r.YF_AAthreshold=0.05; + if (G.scene->r.GIpower==0.0) G.scene->r.GIpower=1.0; + if (G.scene->r.GIindirpower==0.0) G.scene->r.GIindirpower=1.0; render_panel_yafrayGlobal(); render_panel_yafrayGI(); } diff --git a/source/blender/yafray/intern/export_File.cpp b/source/blender/yafray/intern/export_File.cpp index 5584ac47bd3..eca34a65504 100755 --- a/source/blender/yafray/intern/export_File.cpp +++ b/source/blender/yafray/intern/export_File.cpp @@ -313,13 +313,47 @@ static void adjustPath(string &path) } +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 yafrayFileRender_t::writeTextures() { - for (map<string, pair<Material*, MTex*> >::const_iterator blendtex=used_textures.begin(); + string ts; + for (map<string, MTex*>::const_iterator blendtex=used_textures.begin(); blendtex!=used_textures.end();++blendtex) { - //Material* matr = blendtex->second.first; - MTex* mtex = blendtex->second.second; + MTex* mtex = blendtex->second; Tex* tex = mtex->tex; + + float nsz = tex->noisesize; + if (nsz!=0.f) nsz=1.f/nsz; + + // noisebasis type + string ntype = noise2string(tex->noisebasis); + 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. @@ -329,8 +363,9 @@ void yafrayFileRender_t::writeTextures() 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"; + ostr << "\t\t<size value=\"" << nsz << "\" />\n"; + ostr << "\t\t<noise_type value=\"" << ntype << "\" />\n"; + ostr << "\t</attributes>\n</shader >\n\n"; xmlfile << ostr.str(); break; } @@ -342,11 +377,10 @@ void yafrayFileRender_t::writeTextures() 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"; + ts = "on"; if (tex->noisetype==TEX_NOISESOFT) ts = "off"; ostr << "\t\t<hard value=\"" << ts << "\" />\n"; - ostr << "\t</attributes>\n"; - ostr << "</shader>\n\n"; + ostr << "\t</attributes>\n</shader>\n\n"; xmlfile << ostr.str(); break; } @@ -356,28 +390,115 @@ void yafrayFileRender_t::writeTextures() ostr << "\t<attributes>\n"; ostr << "\t\t<depth value=\"" << tex->noisedepth+1 << "\" />\n"; ostr << "\t\t<turbulence value=\"" << tex->turbul << "\" />\n"; - string ts = "on"; + 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"; + ostr << "\t</attributes>\n</shader>\n\n"; + xmlfile << ostr.str(); + break; + } + case TEX_VORONOI: { + ostr.str(""); + ostr << "<shader type=\"voronoi\" name=\"" << blendtex->first << "\" >\n"; + ostr << "\t<attributes>\n"; + 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"; + ostr << "\t\t<color_type value=\"" << ts << "\" />\n"; + ostr << "\t\t<weight1 value=\"" << tex->vn_w1 << "\" />\n"; + ostr << "\t\t<weight2 value=\"" << tex->vn_w2 << "\" />\n"; + ostr << "\t\t<weight3 value=\"" << tex->vn_w3 << "\" />\n"; + ostr << "\t\t<weight4 value=\"" << tex->vn_w4 << "\" />\n"; + ostr << "\t\t<mk_exponent value=\"" << tex->vn_mexp << "\" />\n"; + ostr << "\t\t<intensity value=\"" << tex->ns_outscale << "\" />\n"; + ostr << "\t\t<size value=\"" << nsz << "\" />\n"; + 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"; + ostr << "\t\t<distance_metric value=\"" << ts << "\" />\n"; + ostr << "\t</attributes>\n</shader>\n\n"; + xmlfile << ostr.str(); + break; + } + case TEX_MUSGRAVE: { + ostr.str(""); + ostr << "<shader type=\"musgrave\" name=\"" << blendtex->first << "\" >\n"; + ostr << "\t<attributes>\n"; + 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"; + } + ostr << "\t\t<musgrave_type value=\"" << ts << "\" />\n"; + ostr << "\t\t<noise_type value=\"" << ntype << "\" />\n"; + ostr << "\t\t<H value=\"" << tex->mg_H << "\" />\n"; + ostr << "\t\t<lacunarity value=\"" << tex->mg_lacunarity << "\" />\n"; + ostr << "\t\t<octaves value=\"" << tex->mg_octaves << "\" />\n"; + if ((tex->stype==TEX_HTERRAIN) || (tex->stype==TEX_RIDGEDMF) || (tex->stype==TEX_HYBRIDMF)) { + ostr << "\t\t<offset value=\"" << tex->mg_offset << "\" />\n"; + if ((tex->stype==TEX_RIDGEDMF) || (tex->stype==TEX_HYBRIDMF)) + ostr << "\t\t<gain value=\"" << tex->mg_gain << "\" />\n"; + } + ostr << "\t\t<size value=\"" << nsz << "\" />\n"; + ostr << "\t\t<intensity value=\"" << tex->ns_outscale << "\" />\n"; + ostr << "\t</attributes>\n</shader>\n\n"; + xmlfile << ostr.str(); + break; + } + case TEX_DISTNOISE: { + ostr.str(""); + ostr << "<shader type=\"distorted_noise\" name=\"" << blendtex->first << "\" >\n"; + ostr << "\t<attributes>\n"; + ostr << "\t\t<distort value=\"" << tex->dist_amount << "\" />\n"; + ostr << "\t\t<size value=\"" << nsz << "\" />\n"; + ostr << "\t\t<noise_type1 value=\"" << ntype << "\" />\n"; + ostr << "\t\t<noise_type2 value=\"" << noise2string(tex->noisebasis2) << "\" />\n"; + ostr << "\t</attributes>\n</shader>\n\n"; xmlfile << ostr.str(); break; } case TEX_IMAGE: { Image* ima = tex->ima; if (ima) { + // remove from imagetex list to avoid possible duplicates when TexFace used + imagetex.erase(ima); ostr.str(""); - ostr << "<shader type=\"image\" name=\"" << blendtex->first << "\" >\n"; + // use image name instead of texname here + ostr << "<shader type=\"image\" name=\"" << ima->id.name << "\" >\n"; ostr << "\t<attributes>\n"; - string texpath = ima->name; + string texpath(ima->name); adjustPath(texpath); ostr << "\t\t<filename value=\"" << texpath << "\" />\n"; - ostr << "\t</attributes>\n"; - ostr << "</shader>\n\n"; + ostr << "\t</attributes>\n</shader>\n\n"; xmlfile << ostr.str(); } break; @@ -409,19 +530,235 @@ void yafrayFileRender_t::writeTextures() } } + + // If used, textures for the material 'TexFace' case + if (!imagetex.empty()) { + for (map<Image*, Material*>::const_iterator imgtex=imagetex.begin(); + imgtex!=imagetex.end();++imgtex) + { + ostr.str(""); + ostr << "<shader type=\"image\" name=\"" << imgtex->first->id.name << "\" >\n"; + ostr << "\t<attributes>\n"; + string texpath(imgtex->first->name); + adjustPath(texpath); + ostr << "\t\t<filename value=\"" << texpath << "\" />\n"; + ostr << "\t</attributes>\n</shader>\n\n"; + xmlfile << ostr.str(); + } + } + +} + +void yafrayFileRender_t::writeShader(const string &shader_name, Material* matr, const string &facetexname) +{ + ostr.str(""); + ostr << "<shader type=\"blendershader\" name=\"" << shader_name << "\" >\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"; + // if no GI used, the GIpower parameter is not always initialized, so in that case ignore it + float bg_mult = (R.r.GImethod==0) ? 1 : R.r.GIpower; + ostr << "\t\t<emit value=\"" << (matr->emit * bg_mult) << "\" />\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 + // first modulator is the texture of the face, if used (TexFace mode) + if (facetexname.length()!=0) { + ostr.str(""); + ostr << "\t<modulator>\n"; + ostr << "\t\t<input value=\"" << facetexname << "\" />\n"; + ostr << "\t\t<color value=\"1\" />\n"; + ostr << "\t</modulator>\n"; + xmlfile << ostr.str(); + } + + 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, MTex*>::const_iterator mtexL = used_textures.find(string(tex->id.name)); + if (mtexL!=used_textures.end()) { + + ostr.str(""); + ostr << "\t<modulator>\n"; + // when no facetex used, shader_name is created from original material name + if (facetexname.length()!=0) + ostr << "\t\t<input value=\"" << matr->id.name << "_map" << m2 << "\" />\n"; + else + ostr << "\t\t<input value=\"" << shader_name << "_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 + float nf = -mtex->norfac; + if (mtex->maptoneg & MAP_NORM) nf *= -1.f; + ostr << "\t\t<normal value=\"" << (nf/60.f) << "\" />\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"; + } // write all materials & modulators void yafrayFileRender_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 for (map<string, Material*>::const_iterator blendmat=used_materials.begin(); - blendmat!=used_materials.end();++blendmat) { + blendmat!=used_materials.end();++blendmat) + { Material* matr = blendmat->second; - // blendermappers - for (int m=0;m<8;m++) { + // mapper(s) + for (int m=0;m<8;m++) + { if (matr->septex & (1<<m)) continue;// all active channels @@ -432,8 +769,7 @@ void yafrayFileRender_t::writeMaterialsAndModulators() Tex* tex = mtex->tex; if (tex==NULL) continue; - // now included the full name - map<string, pair<Material*, MTex*> >::const_iterator mtexL = used_textures.find(string(tex->id.name)); + map<string, MTex*>::const_iterator mtexL = used_textures.find(string(tex->id.name)); if (mtexL!=used_textures.end()) { ostr.str(""); ostr << "<shader type=\"blendermapper\" name=\"" << blendmat->first + "_map" << m <<"\""; @@ -448,34 +784,30 @@ void yafrayFileRender_t::writeMaterialsAndModulators() 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"; + ostr << "\n\t\tm00=\"" << itexmat[0][0] << "\" m01=\"" << itexmat[1][0] + << "\" m02=\"" << itexmat[2][0] << "\" m03=\"" << itexmat[3][0] << "\"\n"; + ostr << "\t\tm10=\"" << itexmat[0][1] << "\" m11=\"" << itexmat[1][1] + << "\" m12=\"" << itexmat[2][1] << "\" m13=\"" << itexmat[3][1] << "\"\n"; + ostr << "\t\tm20=\"" << itexmat[0][2] << "\" m21=\"" << itexmat[1][2] + << "\" m22=\"" << itexmat[2][2] << "\" m23=\"" << itexmat[3][2] << "\"\n"; + ostr << "\t\tm30=\"" << 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)) + // use image name instead of texname when texture is image + if ((tex->type==TEX_IMAGE) && tex->ima) + ostr << "\t\t<input value=\"" << tex->ima->id.name << "\" />\n"; + else 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"; + ostr << "\t\t<sizex value=\"" << mtex->size[0] << "\" />\n"; + ostr << "\t\t<sizey value=\"" << mtex->size[1] << "\" />\n"; + ostr << "\t\t<sizez value=\"" << mtex->size[2] << "\" />\n"; // texture offset ostr << "\t\t<ofsx value=\"" << mtex->ofs[0] << "\" />\n"; @@ -483,7 +815,7 @@ void yafrayFileRender_t::writeMaterialsAndModulators() 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)) + if (mtex->texco & TEXCO_UV) 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..> @@ -497,6 +829,12 @@ void yafrayFileRender_t::writeMaterialsAndModulators() else if (mtex->texco & TEXCO_REFL) ostr << "\t\t<texco value=\"reflect\" />\n"; + // texture projection axes, both image & procedural + 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"; + // texture mapping parameters only relevant to image type if (tex->type==TEX_IMAGE) { if (mtex->mapping==MTEX_FLAT) @@ -508,12 +846,6 @@ void yafrayFileRender_t::writeMaterialsAndModulators() 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"; @@ -547,185 +879,45 @@ void yafrayFileRender_t::writeMaterialsAndModulators() } } - // 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"; - // if no GI used, the GIpower parameter is not always initialized, so in that case ignore it - float bg_mult; - if (R.r.GImethod==0) bg_mult=1; else bg_mult=R.r.GIpower; - ostr << "\t\t<emit value=\"" << (matr->emit * bg_mult) << "\" />\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)); - 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 - float nf = -mtex->norfac; - if (mtex->maptoneg & MAP_NORM) nf *= -1.f; - if (tex->type==TEX_IMAGE) nf/=60.f; else nf/=30.f; - ostr << "\t\t<normal value=\"" << nf << "\" />\n"; - - } + // shader + modulators + writeShader(blendmat->first, matr); - // 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"; + // 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 + int snum = 0; + for (map<Image*, Material*>::const_iterator imgtex=imagetex.begin(); + imgtex!=imagetex.end();++imgtex) + { + Material* matr = imgtex->second; - //varfac - ostr << "\t\t<varfac value=\"" << mtex->varfac << "\" />\n"; + // mapper + ostr.str(""); + ostr << "<shader type=\"blendermapper\" name=\"" << string(matr->id.name) + "_ftex_mp" << snum << "\" >\n"; + ostr << "\t<attributes>\n"; + ostr << "\t\t<input value=\"" << imgtex->first->id.name << "\" />\n"; + // all yafray default settings, except for texco, so no need to set others + ostr << "\t\t<texco value=\"uv\" />\n"; + ostr << "\t</attributes>\n"; + ostr << "</shader>\n\n"; + xmlfile << ostr.str(); - 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"; - } + // shader, remember name, used later when writing per-face-shaders + ostr.str(""); + ostr << matr->id.name << "_ftex_sh" << snum; + string shader_name = ostr.str(); + imgtex_shader[imgtex->first] = shader_name; - ostr << "\t</modulator>\n"; - xmlfile << ostr.str(); + ostr.str(""); + ostr << matr->id.name << "_ftex_mp" << snum++; + writeShader(shader_name, matr, ostr.str()); - } } - xmlfile << "</shader>\n\n"; } + } @@ -744,35 +936,45 @@ void yafrayFileRender_t::writeObject(Object* obj, const vector<VlakRen*> &VLR_li 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" )<<"\" "; - bool caus = (((VLR_list[0]->mat->mode & MA_RAYTRANSP) | (VLR_list[0]->mat->mode & MA_RAYMIRROR))!=0); - if (caus) ostr << "caus_IOR=\"" << VLR_list[0]->mat->ang << "\""; - if (strlen(matname)==0) matname = "blender_default"; + ostr << "<object name=\"" << obj->id.name << "\""; + // 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 material. + VlakRen* face0 = VLR_list[0]; + Material* face0mat = face0->mat; + string matname(face0mat->id.name); + // use name in imgtex_shader list if 'TexFace' enabled for this material + if (face0mat->mode & MA_FACETEXTURE) { + TFace* tface = face0->tface; + if (tface) { + Image* fimg = (Image*)tface->tpage; + if (fimg) matname = imgtex_shader[fimg]; + } + } + bool shadow = face0mat->mode & MA_TRACEBLE; + ostr <<" shadow=\""<< (shadow ? "on" : "off" ) << "\" "; + bool caus = (((face0mat->mode & MA_RAYTRANSP) | (face0->mat->mode & MA_RAYMIRROR))!=0); + if (caus) ostr << "caus_IOR=\"" << face0mat->ang << "\""; + if (matname.length()==0) matname = "blender_default"; ostr << " shader_name=\"" << matname << "\" >\n"; ostr << "\t<attributes>\n"; if (caus) { - 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"; - tr = VLR_list[0]->mat->ray_mirror; - ostr << "\t\t<caus_rcolor r=\"" << VLR_list[0]->mat->mirr*tr - << "\" g=\"" << VLR_list[0]->mat->mirg*tr - << "\" b=\"" << VLR_list[0]->mat->mirb*tr << "\" />\n"; + float tr = 1.0-face0mat->alpha; + ostr << "\t\t<caus_tcolor r=\"" << face0mat->r*tr + << "\" g=\"" << face0mat->g*tr + << "\" b=\"" << face0mat->b*tr << "\" />\n"; + tr = face0mat->ray_mirror; + ostr << "\t\t<caus_rcolor r=\"" << face0mat->mirr*tr + << "\" g=\"" << face0mat->mirg*tr + << "\" b=\"" << face0mat->mirb*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); + bool EXPORT_ORCO = (face0->v1->orco!=NULL); string has_orco = "off"; if (EXPORT_ORCO) has_orco = "on"; @@ -793,7 +995,7 @@ void yafrayFileRender_t::writeObject(Object* obj, const vector<VlakRen*> &VLR_li // 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) + if (face0->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 @@ -885,33 +1087,38 @@ void yafrayFileRender_t::writeObject(Object* obj, const vector<VlakRen*> &VLR_li 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"; - 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; - + string fmatname(fmat->id.name); + // use name in imgtex_shader list if 'TexFace' enabled for this face material + if (fmat->mode & MA_FACETEXTURE) { + TFace* tface = vlr->tface; + if (tface) { + Image* fimg = (Image*)tface->tpage; + if (fimg) fmatname = imgtex_shader[fimg]; + } + } + else if (fmatname.length()==0) fmatname = "blender_default"; + + int idx1 = vert_idx.find(vlr->v1)->second; + int idx2 = vert_idx.find(vlr->v2)->second; + int 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 << "\""; + TFace* uvc = vlr->tface; // possible uvcoords (v upside down) 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] << "\""; + 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++; } + ostr << " u_a=\"" << uvc->uv[ui1][0] << "\" v_a=\"" << 1-uvc->uv[ui1][1] << "\"" + << " u_b=\"" << uvc->uv[ui2][0] << "\" v_b=\"" << 1-uvc->uv[ui2][1] << "\"" + << " u_c=\"" << uvc->uv[ui3][0] << "\" v_c=\"" << 1-uvc->uv[ui3][1] << "\""; } // since Blender seems to need vcols when uvs are used, for yafray only export when the material actually uses vcols @@ -982,7 +1189,7 @@ void yafrayFileRender_t::writeAllObjects() for (map<Object*, vector<VlakRen*> >::const_iterator obi=all_objects.begin(); obi!=all_objects.end(); ++obi) { - // skip main duplivert object if in dupliMtx_list, written later + // 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, obj->obmat); @@ -1031,7 +1238,7 @@ void yafrayFileRender_t::writeAllObjects() // new name from original ostr.str(""); - ostr << "<object name=\"" << obj->id.name+2 << "_dup" << (curmtx>>4) << "\" original=\"" << obj->id.name+2 << "\" >\n"; + ostr << "<object name=\"" << obj->id.name << "_dup" << (curmtx>>4) << "\" original=\"" << obj->id.name << "\" >\n"; xmlfile << ostr.str(); xmlfile << "\t<attributes>\n\t</attributes>\n\t<null/>\n</object>\n</transform>\n\n"; @@ -1150,11 +1357,16 @@ void yafrayFileRender_t::writeLamps() // cast_shadows flag not used with softlight, spherelight or photonlight if ((!is_softL) && (!is_sphereL) && (lamp->type!=LA_YF_PHOTON)) { string lpmode="off"; - // shadows only when Blender has shadow button enabled, only spots use LA_SHAD flag - if (R.r.mode & R_SHADOW) - if (((lamp->type==LA_SPOT) && (lamp->mode & LA_SHAD)) || (lamp->mode & LA_SHAD_RAY)) lpmode="on"; + // Shadows only when Blender has shadow button enabled, only spots use LA_SHAD flag. + // Also 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 (R.r.mode & R_SHADOW) + if (((lamp->type==LA_SPOT) && (lamp->mode & LA_SHAD)) || (lamp->mode & LA_SHAD_RAY)) lpmode="on"; + } ostr << " cast_shadows=\"" << lpmode << "\""; } + // spot specific stuff bool has_halo = ((lamp->type==LA_SPOT) && (lamp->mode & LA_HALO) && (lamp->haint>0.0)); @@ -1287,7 +1499,7 @@ void yafrayFileRender_t::writeCamera() void yafrayFileRender_t::writeHemilight() { ostr.str(""); - ostr << "<light type=\"hemilight\" name=\"hemi_LT\" power=\"1.0\" "; + ostr << "<light type=\"hemilight\" name=\"hemi_LT\" power=\"" << R.r.GIpower << "\""; switch (R.r.GIquality) { case 1 : @@ -1311,7 +1523,7 @@ void yafrayFileRender_t::writePathlight() << "\" caus_depth=\""<<R.r.GIcausdepth<< "\" search=\""<< R.r.GImixphotons<<"\" >"<<endl; ostr << "</light>"<<endl; } - ostr << "<light type=\"pathlight\" name=\"path_LT\" power=\"1.0\" "; + ostr << "<light type=\"pathlight\" name=\"path_LT\" power=\"" << R.r.GIindirpower << "\""; ostr << " depth=\"" << ((R.r.GIphotons) ? 1 : R.r.GIdepth) << "\" caus_depth=\"" << R.r.GIcausdepth <<"\"\n"; if(R.r.GIdirect && R.r.GIphotons) ostr << "direct=\"on\"" << endl; if (R.r.GIcache && ! (R.r.GIdirect && R.r.GIphotons)) @@ -1327,12 +1539,10 @@ void yafrayFileRender_t::writePathlight() } 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); float sbase = 2.0/float(R.r.xsch); ostr << " cache=\"on\" use_QMC=\"on\" threshold=\"" <<R.r.GIrefinement<<"\""<<endl; ostr << " cache_size=\"" << sbase*R.r.GIpixelspersample << "\" shadow_threshold=\"" << - 1.0 - R.r.GIshadowquality << "\" grid=\"82\" search=\"35\" gradient=\"" << - ((R.r.GIgradient)? "on" : "off") << "\" >\n"; + 1.0 - R.r.GIshadowquality << "\" grid=\"82\" search=\"35\" >\n"; } else { @@ -1404,8 +1614,7 @@ bool yafrayFileRender_t::writeWorld() ostr << "<background type=\"constant\" name=\"world_background\" >\n"; // 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; - if (R.r.GImethod==0) bg_mult=1; else bg_mult=R.r.GIpower; + float bg_mult = (R.r.GImethod==0) ? 1 : R.r.GIpower; ostr << "\t<color r=\"" << (world->horr * bg_mult) << "\" g=\"" << (world->horg * bg_mult) << "\" b=\"" << (world->horb * bg_mult) << "\" />\n"; diff --git a/source/blender/yafray/intern/export_File.h b/source/blender/yafray/intern/export_File.h index c9d650f578f..5d2e0c53a21 100755 --- a/source/blender/yafray/intern/export_File.h +++ b/source/blender/yafray/intern/export_File.h @@ -16,11 +16,11 @@ class yafrayFileRender_t : public yafrayRender_t void displayImage(); bool executeYafray(const std::string &xmlpath); virtual void writeTextures(); + virtual void writeShader(const std::string &shader_name, Material* matr, const std::string &facetexname=""); virtual void writeMaterialsAndModulators(); - virtual void writeObject(Object* obj, - const std::vector<VlakRen*> &VLR_list, const float obmat[4][4]); + virtual void writeObject(Object* obj, const std::vector<VlakRen*> &VLR_list, const float obmat[4][4]); virtual void writeAllObjects(); - void writeAreaLamp(LampRen* lamp, int num, float iview[4][4]); + virtual void writeAreaLamp(LampRen* lamp, int num, float iview[4][4]); virtual void writeLamps(); virtual void writeCamera(); virtual void writeHemilight(); diff --git a/source/blender/yafray/intern/export_Plugin.cpp b/source/blender/yafray/intern/export_Plugin.cpp index 960e65c13c2..40e87d3856f 100644 --- a/source/blender/yafray/intern/export_Plugin.cpp +++ b/source/blender/yafray/intern/export_Plugin.cpp @@ -317,34 +317,74 @@ static void adjustPath(string &path) } +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() { - for (map<string, pair<Material*, MTex*> >::const_iterator blendtex=used_textures.begin(); + string ts; + yafray::paramMap_t params; + list<yafray::paramMap_t> lparams; + for (map<string, MTex*>::const_iterator blendtex=used_textures.begin(); blendtex!=used_textures.end();++blendtex) { - yafray::paramMap_t params; - list<yafray::paramMap_t> lparams; - MTex* mtex = blendtex->second.second; + MTex* mtex = blendtex->second; Tex* tex = mtex->tex; - params["name"]=yafray::parameter_t(blendtex->first); + // 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); + 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: - params["type"]=yafray::parameter_t("clouds"); - params["depth"]=yafray::parameter_t(tex->noisedepth+1); + case TEX_CLOUDS: { + params["type"] = yafray::parameter_t("clouds"); + params["depth"] = yafray::parameter_t(tex->noisedepth+1); + params["size"] = yafray::parameter_t(nsz); + params["noise_type"] = ntype; break; + } case TEX_WOOD: { - params["type"]=yafray::parameter_t("wood"); - params["depth"]=yafray::parameter_t(tex->noisedepth+1); - params["turbulence"]=yafray::parameter_t(tex->turbul); - params["ringscale_x"]=yafray::parameter_t(mtex->size[0]); - params["ringscale_y"]=yafray::parameter_t(mtex->size[1]); - string ts = "on"; + params["type"] = yafray::parameter_t("wood"); + params["depth"] = yafray::parameter_t(tex->noisedepth+1); + params["turbulence"] = yafray::parameter_t(tex->turbul); + params["ringscale_x"] = yafray::parameter_t(mtex->size[0]); + params["ringscale_y"] = yafray::parameter_t(mtex->size[1]); + ts = "on"; if (tex->noisetype==TEX_NOISESOFT) ts = "off"; - params["hard"]=yafray::parameter_t(ts); + params["hard"] = yafray::parameter_t(ts); break; } case TEX_MARBLE: @@ -352,7 +392,7 @@ void yafrayPluginRender_t::writeTextures() params["type"]=yafray::parameter_t("marble"); params["depth"]=yafray::parameter_t(tex->noisedepth+1); params["turbulence"]=yafray::parameter_t(tex->turbul); - string ts = "on"; + ts = "on"; if (tex->noisetype==TEX_NOISESOFT) ts = "off"; params["hard"]=yafray::parameter_t(ts); if (tex->stype==1) @@ -367,17 +407,97 @@ void yafrayPluginRender_t::writeTextures() { Image* ima = tex->ima; if (ima) { - params["type"]=yafray::parameter_t("image"); + // remove from imagetex list to avoid possible duplicates when TexFace used + imagetex.erase(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); } 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)); + } default: cout << "Unsupported texture type\n"; } - yafrayGate->addShader(params,lparams); + yafrayGate->addShader(params, lparams); + // colorbands if (tex->flag & TEX_COLORBAND) { @@ -398,23 +518,231 @@ void yafrayPluginRender_t::writeTextures() cb->data[i].a)); lparams.push_back(mparams); } - yafrayGate->addShader(params,lparams); + yafrayGate->addShader(params, lparams); } } } + + // If used, textures for the material 'TexFace' case + if (!imagetex.empty()) { + for (map<Image*, Material*>::const_iterator imgtex=imagetex.begin(); + imgtex!=imagetex.end();++imgtex) + { + 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; + params["type"] = yafray::parameter_t("blendershader"); + params["name"] = yafray::parameter_t(shader_name); + float diff = matr->alpha; + params["color"] = yafray::parameter_t(yafray::color_t(matr->r*diff, matr->g*diff, matr->b*diff)); + params["specular_color"] = yafray::parameter_t(yafray::color_t(matr->specr, matr->specg, matr->specb)); + 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["hard"] = yafray::parameter_t(matr->har); + 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 = (R.r.GImethod==0) ? 1 : R.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) + { + float rf = matr->ray_mirror; + // blender uses mir color for reflection as well + params["reflected"] = yafray::parameter_t(yafray::color_t(matr->mirr, matr->mirg, matr->mirb)); + params["min_refle"] = yafray::parameter_t(rf); + if (matr->ray_depth>maxraydepth) maxraydepth = matr->ray_depth; + } + if (matr->mode & MA_RAYTRANSP) + { + float tr = 1.0-matr->alpha; + params["transmitted"]=yafray::parameter_t(yafray::color_t(matr->r*tr, matr->g*tr, matr->b*tr)); + // tir on by default + params["tir"] = yafray::parameter_t("on"); + 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!="") params["matmodes"] = yafray::parameter_t(Mmode); + + // modulators + list<yafray::paramMap_t> lparams; + + // 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<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, 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 + 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"; + mparams["mode"]=yafray::parameter_t(ts); + + // 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 negative option of 'Nor', + // is not affected by 'Neg') + // scaled down quite a bit for yafray + float nf = -mtex->norfac; + 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); + } + + // 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"; + 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); + } + 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; - // blendermappers + // mapper(s) for (int m=0;m<8;m++) { if (matr->septex & (1<<m)) continue;// all active channels @@ -425,18 +753,13 @@ void yafrayPluginRender_t::writeMaterialsAndModulators() Tex* tex = mtex->tex; if (tex==NULL) continue; - // now included the full name - map<string, pair<Material*, MTex*> >::const_iterator mtexL = used_textures.find(string(tex->id.name)); + map<string, MTex*>::const_iterator mtexL = used_textures.find(string(tex->id.name)); if (mtexL!=used_textures.end()) { - yafray::paramMap_t params; - list<yafray::paramMap_t> lparams; - //params.clear(); - //lparams.clear(); - char temp[16]; - sprintf(temp,"%d",m); - params["type"]=yafray::parameter_t("blendermapper"); - params["name"]=yafray::parameter_t(blendmat->first + "_map"+temp); + 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)) { // For object & reflection mapping, add the object matrix to the modulator, @@ -449,327 +772,171 @@ void yafrayPluginRender_t::writeMaterialsAndModulators() 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]); + 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 } - if ((tex->flag & TEX_COLORBAND) & (tex->coba!=NULL)) - params["input"]=yafray::parameter_t(mtexL->first + "_coba"); + // 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); + params["input"] = yafray::parameter_t(mtexL->first); - // 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 - params["sizex"]=yafray::parameter_t(mtex->size[0]*sc); - params["sizey"]=yafray::parameter_t(mtex->size[1]*sc); - params["sizez"]=yafray::parameter_t(mtex->size[2]*sc); + 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]*sc); - params["ofsy"]=yafray::parameter_t(mtex->ofs[1]*sc); - params["ofsz"]=yafray::parameter_t(mtex->ofs[2]*sc); + 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) || (matr->mode & MA_FACETEXTURE)) - params["texco"]=yafray::parameter_t("uv"); + 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"); + params["texco"] = yafray::parameter_t("global"); else if (mtex->texco & TEXCO_ORCO) - params["texco"]=yafray::parameter_t("orco"); + params["texco"] = yafray::parameter_t("orco"); else if (mtex->texco & TEXCO_WINDOW) - params["texco"]=yafray::parameter_t("window"); + params["texco"] = yafray::parameter_t("window"); else if (mtex->texco & TEXCO_NORM) - params["texco"]=yafray::parameter_t("normal"); + params["texco"] = yafray::parameter_t("normal"); else if (mtex->texco & TEXCO_REFL) - params["texco"]=yafray::parameter_t("reflect"); + 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"); + params["mapping"] = yafray::parameter_t("flat"); else if (mtex->mapping==MTEX_CUBE) - params["mapping"]=yafray::parameter_t("cube"); + params["mapping"] = yafray::parameter_t("cube"); else if (mtex->mapping==MTEX_TUBE) - params["mapping"]=yafray::parameter_t("tube"); + params["mapping"] = yafray::parameter_t("tube"); else if (mtex->mapping==MTEX_SPHERE) - params["mapping"]=yafray::parameter_t("sphere"); - - // texture projection axes - 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])); + params["mapping"] = yafray::parameter_t("sphere"); // repeat - params["xrepeat"]=yafray::parameter_t(tex->xrepeat); - params["yrepeat"]=yafray::parameter_t(tex->yrepeat); + 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"); + params["clipping"] = yafray::parameter_t("extend"); else if (tex->extend==TEX_CLIP) - params["clipping"]=yafray::parameter_t("clip"); + params["clipping"] = yafray::parameter_t("clip"); else if (tex->extend==TEX_CLIPCUBE) - params["clipping"]=yafray::parameter_t("clipcube"); + params["clipping"] = yafray::parameter_t("clipcube"); else - params["clipping"]=yafray::parameter_t("repeat"); + 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); + 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"); + params["rot90"] = yafray::parameter_t("on"); else - params["rot90"]=yafray::parameter_t("off"); + params["rot90"] = yafray::parameter_t("off"); } - yafrayGate->addShader(params,lparams); + yafrayGate->addShader(params, lparams); } } - yafray::paramMap_t params; - // blendershaders + modulators - params["type"]=yafray::parameter_t("blendershader"); - params["name"]=yafray::parameter_t(blendmat->first); - float diff=matr->alpha; - - params["color"]=yafray::parameter_t(yafray::color_t(matr->r*diff,matr->g*diff,matr->b*diff)); - - params["specular_color"]=yafray::parameter_t(yafray::color_t(matr->specr, - matr->specg, - matr->specb)); - 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["hard"]=yafray::parameter_t(matr->har); - 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; - if (R.r.GImethod==0) bg_mult=1; else bg_mult=R.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) - { - float rf = matr->ray_mirror; - // blender uses mir color for reflection as well - params["reflected"]=yafray::parameter_t(yafray::color_t(matr->mirr, matr->mirg,matr->mirb)); - params["min_refle"]=yafray::parameter_t(rf); - if (matr->ray_depth>maxraydepth) maxraydepth = matr->ray_depth; - } - if (matr->mode & MA_RAYTRANSP) - { - float tr=1.0-matr->alpha; - params["transmitted"]=yafray::parameter_t(yafray::color_t(matr->r*tr,matr->g*tr,matr->b*tr)); - // tir on by default - params["tir"]=yafray::parameter_t("on"); - 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!="") params["matmodes"]=yafray::parameter_t(Mmode); - - // modulators - list<yafray::paramMap_t> lparams; - 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; + // shader + modulators + writeShader(blendmat->first, matr); - map<string, pair<Material*, MTex*> >::const_iterator mtexL = used_textures.find(string(tex->id.name)); - if (mtexL!=used_textures.end()) - { - yafray::paramMap_t mparams; - char temp[16]; - sprintf(temp,"%d",m2); - mparams["input"]=yafray::parameter_t(blendmat->first + "_map" + temp); - // 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"; - mparams["mode"]=yafray::parameter_t(ts); - - // 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 negative option of 'Nor', - // is not affected by 'Neg') - // scaled down quite a bit for yafray - float nf = -mtex->norfac; - if (mtex->maptoneg & MAP_NORM) nf *= -1.f; - if (tex->type==TEX_IMAGE) nf/=60.f; else nf/=30.f; - mparams["normal"]=yafray::parameter_t(nf); - } - - // 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); - } - - // 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"; - 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); + // 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*, Material*>::const_iterator imgtex=imagetex.begin(); + imgtex!=imagetex.end();++imgtex) + { + Material* matr = imgtex->second; + + // mapper + params["type"] = yafray::parameter_t("blendermapper"); + char temp[32]; + sprintf(temp, "_ftex_mp%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, "_ftex_sh%d", snum); + string shader_name = string(matr->id.name) + string(temp); + imgtex_shader[imgtex->first] = shader_name; + + sprintf(temp, "_ftex_mp%d", snum++); + string facetexname = string(matr->id.name) + string(temp); + writeShader(shader_name, matr, facetexname); - 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); - } - lparams.push_back(mparams); - } } - yafrayGate->addShader(params,lparams); } + } -void yafrayPluginRender_t::genUVcoords(vector<yafray::GFLOAT> &uvcoords,VlakRen *vlr,TFace* uvc) +void yafrayPluginRender_t::genUVcoords(vector<yafray::GFLOAT> &uvcoords, VlakRen *vlr, TFace* uvc, bool comple) { if (uvc) { - // use correct uv coords for this triangle - if (vlr->flag & R_FACE_SPLIT) - { - uvcoords.push_back(uvc->uv[0][0]);uvcoords.push_back(1-uvc->uv[0][1]); - uvcoords.push_back(uvc->uv[2][0]);uvcoords.push_back(1-uvc->uv[2][1]); - uvcoords.push_back(uvc->uv[3][0]);uvcoords.push_back(1-uvc->uv[3][1]); + // use correct uv coords for this triangle + int ui1=0, ui2=1, ui3=2; + if (vlr->flag & R_DIVIDE_24) { + ui3++; + if (vlr->flag & R_FACE_SPLIT) { ui1++; ui2++; } } - else - { - uvcoords.push_back(uvc->uv[0][0]);uvcoords.push_back(1-uvc->uv[0][1]); - uvcoords.push_back(uvc->uv[1][0]);uvcoords.push_back(1-uvc->uv[1][1]); - uvcoords.push_back(uvc->uv[2][0]);uvcoords.push_back(1-uvc->uv[2][1]); + 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::genCompleUVcoords(vector<yafray::GFLOAT> &uvcoords,/*VlakRen *vlr,*/TFace* uvc) -{ - if (uvc) - { - // use correct uv coords for this triangle - uvcoords.push_back(uvc->uv[2][0]);uvcoords.push_back(1-uvc->uv[2][1]); - uvcoords.push_back(uvc->uv[3][0]);uvcoords.push_back(1-uvc->uv[3][1]); - uvcoords.push_back(uvc->uv[0][0]);uvcoords.push_back(1-uvc->uv[0][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); + 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,VlakRen *vlr, - int p1,int p2,int p3,bool EXPORT_VCOL) + int p1,int p2,int p3) { - if ((EXPORT_VCOL) && (vlr->vcol)) + if (vlr->vcol) { // vertex colors float vr, vg, vb; @@ -797,12 +964,20 @@ void yafrayPluginRender_t::genVcol(vector<yafray::CFLOAT> &vcol,VlakRen *vlr, 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,VlakRen *vlr, - bool has_orco,bool has_uv, bool has_vcol) + bool has_orco,bool has_uv) { Material* fmat = vlr->mat; bool EXPORT_VCOL = ((fmat->mode & (MA_VERTEXCOL|MA_VERTEXCOLP))!=0); - string fmatname = fmat->id.name; - if (fmatname=="") fmatname = "blender_default"; + string fmatname(fmat->id.name); + // use name in imgtex_shader list if 'TexFace' enabled for this face material + if (fmat->mode & MA_FACETEXTURE) { + TFace* tface = vlr->tface; + if (tface) { + Image* fimg = (Image*)tface->tpage; + if (fimg) fmatname = imgtex_shader[fimg]; + } + } + else if (fmatname.length()==0) fmatname = "blender_default"; bool newmat=true; for(unsigned int i=0;i<shaders.size();++i) if(shaders[i]==fmatname) @@ -826,18 +1001,18 @@ void yafrayPluginRender_t::genFace(vector<int> &faces,vector<string> &shaders,ve // 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); + faces.push_back(idx1); faces.push_back(idx2); faces.push_back(idx3); if(has_uv) genUVcoords(uvcoords,vlr,uvc); // since Blender seems to need vcols when uvs are used, for yafray only export when the material actually uses vcols - if (has_vcol) genVcol(vcol,vlr,0,1,2,EXPORT_VCOL); + if (EXPORT_VCOL) genVcol(vcol, vlr, 0, 1, 2); } 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,VlakRen *vlr, - bool has_orco,bool has_uv, bool has_vcol) + bool has_orco,bool has_uv) { Material* fmat = vlr->mat; bool EXPORT_VCOL = ((fmat->mode & (MA_VERTEXCOL|MA_VERTEXCOLP))!=0); @@ -852,10 +1027,10 @@ void yafrayPluginRender_t::genCompleFace(vector<int> &faces,/*vector<string> &sh // 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); + faces.push_back(idx1); faces.push_back(idx2); faces.push_back(idx3); - if(has_uv) genCompleUVcoords(uvcoords,/*vlr,*/uvc); - if (has_vcol) genVcol(vcol,vlr,2,3,0,EXPORT_VCOL); + if (has_uv) genUVcoords(uvcoords, vlr, uvc, true); + if (EXPORT_VCOL) genVcol(vcol, vlr, 2, 3, 0); } void yafrayPluginRender_t::genVertices(vector<yafray::point3d_t> &verts, int &vidx, @@ -913,19 +1088,22 @@ void yafrayPluginRender_t::writeObject(Object* obj, const vector<VlakRen*> &VLR_ 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); - string name=string(obj->id.name+2); - bool castShadows=VLR_list[0]->mat->mode & MA_TRACEBLE; + + 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 = (((VLR_list[0]->mat->mode & MA_RAYTRANSP) | (VLR_list[0]->mat->mode & MA_RAYMIRROR))!=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 = VLR_list[0]->mat->ang; - float tr = 1.0-VLR_list[0]->mat->alpha; - caus_tcolor.set(VLR_list[0]->mat->r*tr, VLR_list[0]->mat->g*tr, VLR_list[0]->mat->b*tr); - tr = VLR_list[0]->mat->ray_mirror; - caus_rcolor.set(VLR_list[0]->mat->mirr*tr, VLR_list[0]->mat->mirg*tr, VLR_list[0]->mat->mirb*tr); + 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); } - bool has_orco = (VLR_list[0]->v1->orco!=NULL); + bool has_orco = (face0->v1->orco!=NULL); bool no_auto = true; //in case non-mesh, or mesh has no autosmooth float sm_angle = 0.1f; if (obj->type==OB_MESH) @@ -940,12 +1118,8 @@ void yafrayPluginRender_t::writeObject(Object* obj, const vector<VlakRen*> &VLR_ if (no_auto) { // no per face smooth flag in yafray, if AutoSmooth not used, // use smooth flag of the first face instead - if (VLR_list[0]->flag & ME_SMOOTH) sm_angle=90; + if (face0->flag & ME_SMOOTH) sm_angle=90; } - // Guess if we need to set vertex colors Could be faster? sure - bool has_vcol=false; - if ((obj->type==OB_MESH) && (obj->data!=NULL)) - has_vcol = (((Mesh*)obj->data)->mcol!=NULL); vector<yafray::point3d_t> verts; vector<yafray::CFLOAT> vcol; // now all vertices @@ -968,14 +1142,14 @@ void yafrayPluginRender_t::writeObject(Object* obj, const vector<VlakRen*> &VLR_ fci2!=VLR_list.end();++fci2) { VlakRen* vlr = *fci2; - genFace(faces, shaders, faceshader, uvcoords, vcol, vert_idx, vlr, has_orco, has_uv, has_vcol); + genFace(faces, shaders, faceshader, uvcoords, vcol, vert_idx, vlr, has_orco, has_uv); if (vlr->v4) - genCompleFace(faces, /*shaders,*/ faceshader, uvcoords, vcol, vert_idx, vlr, has_orco, has_uv, has_vcol); + genCompleFace(faces, faceshader, uvcoords, vcol, vert_idx, vlr, has_orco, has_uv); } - yafrayGate->addObject_trimesh(name,verts,faces,uvcoords,vcol, - shaders,faceshader,sm_angle,castShadows,true,true,caus,has_orco, - caus_rcolor,caus_tcolor,caus_IOR); + yafrayGate->addObject_trimesh(string(obj->id.name), verts, faces, uvcoords, vcol, + shaders, faceshader, sm_angle, castShadows, true, true, caus, has_orco, + caus_rcolor, caus_tcolor, caus_IOR); yafrayGate->transformPop(); } @@ -1029,11 +1203,11 @@ void yafrayPluginRender_t::writeAllObjects() yafrayGate->transformPush(mtr); // new name from original - string name=(obj->id.name+2); + string name=(obj->id.name); char temp[16]; sprintf(temp,"_dup%d",(curmtx>>4)); name+=temp; - yafrayGate->addObject_reference(name,obj->id.name+2); + yafrayGate->addObject_reference(name,obj->id.name); yafrayGate->transformPop(); } @@ -1159,9 +1333,13 @@ void yafrayPluginRender_t::writeLamps() // cast_shadows flag not used with softlight, spherelight or photonlight if ((!is_softL) && (!is_sphereL) && (lamp->type!=LA_YF_PHOTON)) { string lpmode="off"; - // shadows only when Blender has shadow button enabled, only spots use LA_SHAD flag - if (R.r.mode & R_SHADOW) - if (((lamp->type==LA_SPOT) && (lamp->mode & LA_SHAD)) || (lamp->mode & LA_SHAD_RAY)) lpmode="on"; + // Shadows only when Blender has shadow button enabled, only spots use LA_SHAD flag. + // Also 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 (R.r.mode & R_SHADOW) + if (((lamp->type==LA_SPOT) && (lamp->mode & LA_SHAD)) || (lamp->mode & LA_SHAD_RAY)) lpmode="on"; + } params["cast_shadows"] = yafray::parameter_t(lpmode); } @@ -1289,9 +1467,9 @@ void yafrayPluginRender_t::writeCamera() void yafrayPluginRender_t::writeHemilight() { yafray::paramMap_t params; - params["type"]=yafray::parameter_t("hemilight"); - params["name"]=yafray::parameter_t("hemi_LT"); - params["power"]=yafray::parameter_t(1.0); + params["type"] = yafray::parameter_t("hemilight"); + params["name"] = yafray::parameter_t("hemi_LT"); + params["power"] = yafray::parameter_t(R.r.GIpower); switch (R.r.GIquality) { case 1 : @@ -1321,7 +1499,7 @@ void yafrayPluginRender_t::writePathlight() yafray::paramMap_t params; params["type"]=yafray::parameter_t("pathlight"); params["name"]=yafray::parameter_t("path_LT"); - params["power"]=yafray::parameter_t(1.0); + params["power"]=yafray::parameter_t(R.r.GIindirpower); params["depth"]=yafray::parameter_t(((R.r.GIphotons) ? 1 : R.r.GIdepth)); params["caus_depth"]=yafray::parameter_t(R.r.GIcausdepth); if(R.r.GIdirect && R.r.GIphotons) params["direct"]=yafray::parameter_t("on"); @@ -1338,7 +1516,6 @@ void yafrayPluginRender_t::writePathlight() } 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); float sbase = 2.0/float(R.r.xsch); params["cache"]=yafray::parameter_t("on"); params["use_QMC"]=yafray::parameter_t("on"); @@ -1347,7 +1524,6 @@ void yafrayPluginRender_t::writePathlight() params["shadow_threshold"]=yafray::parameter_t(1.0 - R.r.GIshadowquality); params["grid"]=yafray::parameter_t(82); params["search"]=yafray::parameter_t(35); - //params["gradient"]=yafray::parameter_t("off"); } else { @@ -1418,8 +1594,7 @@ bool yafrayPluginRender_t::writeWorld() 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; - if (R.r.GImethod==0) bg_mult=1; else bg_mult=R.r.GIpower; + float bg_mult = (R.r.GImethod==0) ? 1 : R.r.GIpower; params["color"]=yafray::parameter_t(yafray::color_t(world->horr * bg_mult, world->horg * bg_mult, world->horb * bg_mult)); diff --git a/source/blender/yafray/intern/export_Plugin.h b/source/blender/yafray/intern/export_Plugin.h index c7adab723a6..d2d9128d824 100644 --- a/source/blender/yafray/intern/export_Plugin.h +++ b/source/blender/yafray/intern/export_Plugin.h @@ -31,11 +31,12 @@ class yafrayPluginRender_t : public yafrayRender_t void displayImage(); virtual void writeTextures(); + virtual void writeShader(const std::string &shader_name, Material* matr, const std::string &facetexname=""); virtual void writeMaterialsAndModulators(); virtual void writeObject(Object* obj, const std::vector<VlakRen*> &VLR_list, const float obmat[4][4]); virtual void writeAllObjects(); - void writeAreaLamp(LampRen* lamp, int num, float iview[4][4]); + virtual void writeAreaLamp(LampRen* lamp, int num, float iview[4][4]); virtual void writeLamps(); virtual void writeCamera(); virtual void writeHemilight(); @@ -45,18 +46,17 @@ class yafrayPluginRender_t : public yafrayRender_t virtual bool initExport(); virtual bool finishExport(); - void genUVcoords(std::vector<yafray::GFLOAT> &uvcoords,VlakRen *vlr,TFace* uvc); - void genCompleUVcoords(std::vector<yafray::GFLOAT> &uvcoords,/*VlakRen *vlr,*/TFace* uvc); + void genUVcoords(std::vector<yafray::GFLOAT> &uvcoords,VlakRen *vlr,TFace* uvc, bool comple=false); void genVcol(std::vector<yafray::CFLOAT> &vcol,VlakRen *vlr, - int p1,int p2,int p3,bool EXPORT_VCOL); + int p1,int p2,int p3); void genFace(std::vector<int> &faces,std::vector<std::string> &shaders,std::vector<int> &faceshader, std::vector<yafray::GFLOAT> &uvcoords,std::vector<yafray::CFLOAT> &vcol, std::map<VertRen*, int> &vert_idx,VlakRen *vlr, - bool has_orco,bool has_uv, bool has_vcol); + bool has_orco,bool has_uv); void genCompleFace(std::vector<int> &faces,/*std::vector<std::string> &shaders,*/std::vector<int> &faceshader, std::vector<yafray::GFLOAT> &uvcoords,std::vector<yafray::CFLOAT> &vcol, std::map<VertRen*, int> &vert_idx,VlakRen *vlr, - bool has_orco,bool has_uv, bool has_vcol); + bool has_orco,bool has_uv); void genVertices(std::vector<yafray::point3d_t> &verts, int &vidx, std::map<VertRen*, int> &vert_idx, VlakRen* vlr, bool has_orco, Object* obj); }; diff --git a/source/blender/yafray/intern/yafray_Render.cpp b/source/blender/yafray/intern/yafray_Render.cpp index 461e5d5dfe5..bbb5855b964 100644 --- a/source/blender/yafray/intern/yafray_Render.cpp +++ b/source/blender/yafray/intern/yafray_Render.cpp @@ -18,6 +18,8 @@ void yafrayRender_t::clearAll() dupliMtx_list.clear(); dup_srcob.clear(); objectData.clear(); + imagetex.clear(); + imgtex_shader.clear(); } bool yafrayRender_t::exportScene() @@ -102,8 +104,7 @@ bool yafrayRender_t::getAllMatTexObs() if (strlen(matr->id.name)==0) used_materials["blender_default"] = matr; else - used_materials[matr->id.name] = matr; // <-- full name to avoid name collision in yafray - //used_materials[matr->id.name+2] = matr; // skip 'MA' id + used_materials[matr->id.name] = matr; // textures, all active channels for (int m=0;m<8;m++) { if (matr->septex & (1<<m)) continue; // only active channels @@ -115,26 +116,36 @@ bool yafrayRender_t::getAllMatTexObs() if (tx==NULL) continue; short txtp = tx->type; // if texture type not available in yafray, ignore - if ((txtp!=TEX_STUCCI) && - (txtp!=TEX_CLOUDS) && - (txtp!=TEX_WOOD) && - (txtp!=TEX_MARBLE) && - (txtp!=TEX_IMAGE)) continue; - // in the case of an image texture, check that there is an actual image, otherwise ignore - if ((txtp & TEX_IMAGE) && (!tx->ima)) continue; - used_textures[tx->id.name] = make_pair(matr, mx); // <-- full name to avoid name collision in yafray - //used_textures[tx->id.name+2] = make_pair(matr, mx); + if ((txtp==0) || + (txtp==TEX_MAGIC) || + (txtp==TEX_BLEND) || + (txtp==TEX_NOISE) || + (txtp==TEX_PLUGIN) || + (txtp==TEX_ENVMAP)) continue; + // In the case of an image texture, check that there is an actual image, otherwise ignore. + // Stupid error was here (...if (txtp & TEX_IMAGE)...), + // which happened to work sofar, but not anymore with the extended texture support.. + if ((txtp==TEX_IMAGE) && (!tx->ima)) continue; + used_textures[tx->id.name] = mx; } } - // make list of faces per object, ignore <3 vert faces, duplicate vertex sorting done later - // make sure null object pointers are ignored + // Make list of faces per object, ignore <3 vert faces, duplicate vertex sorting done later. + // ignore null object pointers. + // Also make list of facetexture images (material 'TexFace'). if (vlr->ob) { int nv = 0; // number of vertices if (vlr->v4) nv=4; else if (vlr->v3) nv=3; if (nv) all_objects[vlr->ob].push_back(vlr); + if (vlr->tface) { + Image* fc_img = (Image*)vlr->tface->tpage; + if (fc_img) { + Material* fmat = vlr->mat; + // only save if TexFace enabled + if (fmat && (fmat->mode & MA_FACETEXTURE)) imagetex[fc_img] = fmat; + } + } } - //else cout << "WARNING: VlakRen struct with null obj.ptr!\n"; } @@ -167,7 +178,7 @@ void yafrayRender_t::addDupliMtx(Object* obj) { for (int i=0;i<4;i++) for (int j=0;j<4;j++) - dupliMtx_list[string(obj->id.name)].push_back(obj->obmat[i][j]); + dupliMtx_list[obj->id.name].push_back(obj->obmat[i][j]); } @@ -184,7 +195,7 @@ bool yafrayRender_t::objectKnownData(Object* obj) // then save matrix of linked object in dupliMtx_list, using name of ORIGINAL object for (int i=0;i<4;i++) for (int j=0;j<4;j++) - dupliMtx_list[string(orgob->id.name)].push_back(obj->obmat[i][j]); + dupliMtx_list[orgob->id.name].push_back(obj->obmat[i][j]); return true; } // object not known yet diff --git a/source/blender/yafray/intern/yafray_Render.h b/source/blender/yafray/intern/yafray_Render.h index c65dab58615..e5c710c465d 100644 --- a/source/blender/yafray/intern/yafray_Render.h +++ b/source/blender/yafray/intern/yafray_Render.h @@ -88,20 +88,24 @@ class yafrayRender_t 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, MTex*> used_textures; std::map<std::string, std::vector<float> > dupliMtx_list; std::map<std::string, Object*> dup_srcob; std::map<void*, Object*> objectData; + std::map<Image*, Material*> imagetex; + std::map<Image*, std::string> imgtex_shader; Object* findObject(const char* name); bool getAllMatTexObs(); virtual void writeTextures()=0; + virtual void writeShader(const std::string &shader_name, Material* matr, const std::string &facetexname)=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 writeAreaLamp(LampRen* lamp, int num, float iview[4][4])=0; virtual void writeHemilight()=0; virtual void writePathlight()=0; virtual bool writeWorld()=0; |