Blender  V2.59
TEX_util.c
Go to the documentation of this file.
00001 /*
00002  *
00003  * ***** BEGIN GPL LICENSE BLOCK *****
00004  *
00005  * This program is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU General Public License
00007  * as published by the Free Software Foundation; either version 2
00008  * of the License, or (at your option) any later version. 
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software Foundation,
00017  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00018  *
00019  * The Original Code is Copyright (C) 2005 Blender Foundation.
00020  * All rights reserved.
00021  *
00022  * The Original Code is: all of this file.
00023  *
00024  * Contributor(s): none yet.
00025  *
00026  * ***** END GPL LICENSE BLOCK *****
00027  */
00028 
00034 /*
00035         HOW TEXTURE NODES WORK
00036 
00037         In contrast to Shader nodes, which place a color into the output
00038         stack when executed, Texture nodes place a TexDelegate* there. To
00039         obtain a color value from this, a node further up the chain reads
00040         the TexDelegate* from its input stack, and uses tex_call_delegate to
00041         retrieve the color from the delegate.
00042  
00043         comments: (ton)
00044 
00045         This system needs recode, a node system should rely on the stack, and 
00046         callbacks for nodes only should evaluate own node, not recursively go
00047         over other previous ones.
00048 */
00049 
00050 #include <assert.h>
00051 #include "TEX_util.h"
00052 
00053 #define PREV_RES 128 /* default preview resolution */
00054 
00055 void tex_call_delegate(TexDelegate *dg, float *out, TexParams *params, short thread)
00056 {
00057         if(dg->node->need_exec) {
00058                 dg->fn(out, params, dg->node, dg->in, thread);
00059 
00060                 if(dg->cdata->do_preview)
00061                         tex_do_preview(dg->node, params->previewco, out);
00062         }
00063 }
00064 
00065 static void tex_input(float *out, int sz, bNodeStack *in, TexParams *params, short thread)
00066 {
00067         TexDelegate *dg = in->data;
00068         if(dg) {
00069                 tex_call_delegate(dg, in->vec, params, thread);
00070         
00071                 if(in->hasoutput && in->sockettype == SOCK_VALUE)
00072                         in->vec[1] = in->vec[2] = in->vec[0];
00073         }
00074         memcpy(out, in->vec, sz * sizeof(float));
00075 }
00076 
00077 void tex_input_vec(float *out, bNodeStack *in, TexParams *params, short thread)
00078 {
00079         tex_input(out, 3, in, params, thread);
00080 }
00081 
00082 void tex_input_rgba(float *out, bNodeStack *in, TexParams *params, short thread)
00083 {
00084         tex_input(out, 4, in, params, thread);
00085         
00086         if(in->hasoutput && in->sockettype == SOCK_VALUE)
00087         {
00088                 out[1] = out[2] = out[0];
00089                 out[3] = 1;
00090         }
00091         
00092         if(in->hasoutput && in->sockettype == SOCK_VECTOR) {
00093                 out[0] = out[0] * .5f + .5f;
00094                 out[1] = out[1] * .5f + .5f;
00095                 out[2] = out[2] * .5f + .5f;
00096                 out[3] = 1;
00097         }
00098 }
00099 
00100 float tex_input_value(bNodeStack *in, TexParams *params, short thread)
00101 {
00102         float out[4];
00103         tex_input_vec(out, in, params, thread);
00104         return out[0];
00105 }
00106 
00107 void params_from_cdata(TexParams *out, TexCallData *in)
00108 {
00109         out->co = in->co;
00110         out->dxt = in->dxt;
00111         out->dyt = in->dyt;
00112         out->previewco = in->co;
00113         out->osatex = in->osatex;
00114         out->cfra = in->cfra;
00115         out->shi = in->shi;
00116         out->mtex = in->mtex;
00117 }
00118 
00119 void tex_do_preview(bNode *node, float *co, float *col)
00120 {
00121         bNodePreview *preview= node->preview;
00122 
00123         if(preview) {
00124                 int xs= ((co[0] + 1.0f)*0.5f)*preview->xsize;
00125                 int ys= ((co[1] + 1.0f)*0.5f)*preview->ysize;
00126 
00127                 nodeAddToPreview(node, col, xs, ys, 0); /* 0 = no color management */
00128         }
00129 }
00130 
00131 void tex_output(bNode *node, bNodeStack **in, bNodeStack *out, TexFn texfn, TexCallData *cdata)
00132 {
00133         TexDelegate *dg;
00134         if(!out->data)
00135                 /* Freed in tex_end_exec (node.c) */
00136                 dg = out->data = MEM_mallocN(sizeof(TexDelegate), "tex delegate");
00137         else
00138                 dg = out->data;
00139         
00140         dg->cdata= cdata;
00141         dg->fn = texfn;
00142         dg->node = node;
00143         memcpy(dg->in, in, MAX_SOCKET * sizeof(bNodeStack*));
00144         dg->type = out->sockettype;
00145 }
00146 
00147 void ntreeTexCheckCyclics(struct bNodeTree *ntree)
00148 {
00149         bNode *node;
00150         for(node= ntree->nodes.first; node; node= node->next) {
00151                 
00152                 if(node->type == TEX_NODE_TEXTURE && node->id)
00153                 {
00154                         /* custom2 stops the node from rendering */
00155                         if(node->custom1) {
00156                                 node->custom2 = 1;
00157                                 node->custom1 = 0;
00158                         } else {
00159                                 Tex *tex = (Tex *)node->id;
00160                                 
00161                                 node->custom2 = 0;
00162                         
00163                                 node->custom1 = 1;
00164                                 if(tex->use_nodes && tex->nodetree) {
00165                                         ntreeTexCheckCyclics(tex->nodetree);
00166                                 }
00167                                 node->custom1 = 0;
00168                         }
00169                 }
00170 
00171         }
00172 }
00173 
00174 int ntreeTexExecTree(
00175         bNodeTree *nodes,
00176         TexResult *texres,
00177         float *co,
00178         float *dxt, float *dyt,
00179         int osatex,
00180         short thread, 
00181         Tex *UNUSED(tex), 
00182         short which_output, 
00183         int cfra,
00184         int preview,
00185         ShadeInput *shi,
00186         MTex *mtex
00187 ){
00188         TexCallData data;
00189         float *nor= texres->nor;
00190         int retval = TEX_INT;
00191 
00192         data.co = co;
00193         data.dxt = dxt;
00194         data.dyt = dyt;
00195         data.osatex = osatex;
00196         data.target = texres;
00197         data.do_preview = preview;
00198         data.thread = thread;
00199         data.which_output = which_output;
00200         data.cfra= cfra;
00201         data.mtex= mtex;
00202         data.shi= shi;
00203         
00204         ntreeExecTree(nodes, &data, thread);
00205 
00206         if(texres->nor) retval |= TEX_NOR;
00207         retval |= TEX_RGB;
00208         /* confusing stuff; the texture output node sets this to NULL to indicate no normal socket was set
00209            however, the texture code checks this for other reasons (namely, a normal is required for material) */
00210         texres->nor= nor;
00211 
00212         return retval;
00213 }
00214