~ubuntu-branches/ubuntu/gutsy/blender/gutsy-security

« back to all changes in this revision

Viewing changes to source/blender/blenkernel/intern/node_shaders.c

  • Committer: Bazaar Package Importer
  • Author(s): Florian Ernst
  • Date: 2007-05-17 11:47:59 UTC
  • mfrom: (1.2.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20070517114759-yp4ybrnhp2u7pk66
Tags: 2.44-1
* New upstream release.
* Drop debian/patches/01_64bits_stupidity, not needed anymore: as of this
  version blender is 64 bits safe again. Adjust README.Debian accordingly.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/**
2
 
 * $Id: node_shaders.c,v 1.21 2007/02/01 20:38:37 sirdude Exp $
3
 
 *
4
 
 * ***** BEGIN GPL LICENSE BLOCK *****
5
 
 *
6
 
 * This program is free software; you can redistribute it and/or
7
 
 * modify it under the terms of the GNU General Public License
8
 
 * as published by the Free Software Foundation; either version 2
9
 
 * of the License, or (at your option) any later version. 
10
 
 *
11
 
 * This program is distributed in the hope that it will be useful,
12
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 
 * GNU General Public License for more details.
15
 
 *
16
 
 * You should have received a copy of the GNU General Public License
17
 
 * along with this program; if not, write to the Free Software Foundation,
18
 
 * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19
 
 *
20
 
 * The Original Code is Copyright (C) 2005 Blender Foundation.
21
 
 * All rights reserved.
22
 
 *
23
 
 * The Original Code is: all of this file.
24
 
 *
25
 
 * Contributor(s): none yet.
26
 
 *
27
 
 * ***** END GPL LICENSE BLOCK *****
28
 
 */
29
 
 
30
 
#include <stdlib.h>
31
 
#include <string.h>
32
 
#include <math.h>
33
 
 
34
 
#include "DNA_ID.h"
35
 
#include "DNA_material_types.h"
36
 
#include "DNA_node_types.h"
37
 
#include "DNA_scene_types.h"
38
 
#include "DNA_texture_types.h"
39
 
 
40
 
#include "BKE_blender.h"
41
 
#include "BKE_colortools.h"
42
 
#include "BKE_node.h"
43
 
#include "BKE_material.h"
44
 
#include "BKE_texture.h"
45
 
#include "BKE_utildefines.h"
46
 
 
47
 
#include "BLI_arithb.h"
48
 
#include "BLI_blenlib.h"
49
 
 
50
 
#include "MEM_guardedalloc.h"
51
 
 
52
 
#include "RE_shader_ext.h"              /* <- ShadeInput Shaderesult TexResult */
53
 
 
54
 
 
55
 
/* ********* exec data struct, remains internal *********** */
56
 
 
57
 
typedef struct ShaderCallData {
58
 
        ShadeInput *shi;                /* from render pipe */
59
 
        ShadeResult *shr;               /* from render pipe */
60
 
} ShaderCallData;
61
 
 
62
 
 
63
 
/* **************** call to switch lamploop for material node ************ */
64
 
 
65
 
static void (*node_shader_lamp_loop)(ShadeInput *, ShadeResult *);
66
 
                                                                         
67
 
void set_node_shader_lamp_loop(void (*lamp_loop_func)(ShadeInput *, ShadeResult *))
68
 
{
69
 
        node_shader_lamp_loop= lamp_loop_func;
70
 
}
71
 
 
72
 
/* ****** */
73
 
 
74
 
static void nodestack_get_vec(float *in, short type_in, bNodeStack *ns)
75
 
{
76
 
        float *from= ns->vec;
77
 
                
78
 
        if(type_in==SOCK_VALUE) {
79
 
                if(ns->sockettype==SOCK_VALUE)
80
 
                        *in= *from;
81
 
                else 
82
 
                        *in= 0.333333f*(from[0]+from[1]+from[2]);
83
 
        }
84
 
        else if(type_in==SOCK_VECTOR) {
85
 
                if(ns->sockettype==SOCK_VALUE) {
86
 
                        in[0]= from[0];
87
 
                        in[1]= from[0];
88
 
                        in[2]= from[0];
89
 
                }
90
 
                else {
91
 
                        VECCOPY(in, from);
92
 
                }
93
 
        }
94
 
        else { /* type_in==SOCK_RGBA */
95
 
                if(ns->sockettype==SOCK_RGBA) {
96
 
                        QUATCOPY(in, from);
97
 
                }
98
 
                else if(ns->sockettype==SOCK_VALUE) {
99
 
                        in[0]= from[0];
100
 
                        in[1]= from[0];
101
 
                        in[2]= from[0];
102
 
                        in[3]= 1.0f;
103
 
                }
104
 
                else {
105
 
                        VECCOPY(in, from);
106
 
                        in[3]= 1.0f;
107
 
                }
108
 
        }
109
 
}
110
 
 
111
 
/* ******************************************************** */
112
 
/* ********* Shader Node type definitions ***************** */
113
 
/* ******************************************************** */
114
 
 
115
 
/* SocketType syntax: 
116
 
   socket type, max connections (0 is no limit), name, 4 values for default, 2 values for range */
117
 
 
118
 
/* Verification rule: If name changes, a saved socket and its links will be removed! Type changes are OK */
119
 
 
120
 
/* **************** OUTPUT ******************** */
121
 
static bNodeSocketType sh_node_output_in[]= {
122
 
        {       SOCK_RGBA, 1, "Color",          0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
123
 
        {       SOCK_VALUE, 1, "Alpha",         1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
124
 
        {       -1, 0, ""       }
125
 
};
126
 
 
127
 
static void node_shader_exec_output(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
128
 
{
129
 
        if(data) {
130
 
                ShadeInput *shi= ((ShaderCallData *)data)->shi;
131
 
                float col[4];
132
 
                
133
 
                /* stack order input sockets: col, alpha, normal */
134
 
                nodestack_get_vec(col, SOCK_VECTOR, in[0]);
135
 
                nodestack_get_vec(col+3, SOCK_VALUE, in[1]);
136
 
                
137
 
                if(shi->do_preview) {
138
 
                        nodeAddToPreview(node, col, shi->xs, shi->ys);
139
 
                        node->lasty= shi->ys;
140
 
                }
141
 
                
142
 
                if(node->flag & NODE_DO_OUTPUT) {
143
 
                        ShadeResult *shr= ((ShaderCallData *)data)->shr;
144
 
                        
145
 
                        QUATCOPY(shr->combined, col);
146
 
                        shr->alpha= col[3];
147
 
                        
148
 
                        //      VECCOPY(shr->nor, in[3]->vec);
149
 
                }
150
 
        }       
151
 
}
152
 
 
153
 
static bNodeType sh_node_output= {
154
 
        /* type code   */       SH_NODE_OUTPUT,
155
 
        /* name        */       "Output",
156
 
        /* width+range */       80, 60, 200,
157
 
        /* class+opts  */       NODE_CLASS_OUTPUT, NODE_PREVIEW,
158
 
        /* input sock  */       sh_node_output_in,
159
 
        /* output sock */       NULL,
160
 
        /* storage     */       "",
161
 
        /* execfunc    */       node_shader_exec_output
162
 
        
163
 
};
164
 
 
165
 
/* **************** GEOMETRY  ******************** */
166
 
 
167
 
/* output socket defines */
168
 
#define GEOM_OUT_GLOB   0
169
 
#define GEOM_OUT_LOCAL  1
170
 
#define GEOM_OUT_VIEW   2
171
 
#define GEOM_OUT_ORCO   3
172
 
#define GEOM_OUT_UV             4
173
 
#define GEOM_OUT_NORMAL 5
174
 
#define GEOM_OUT_VCOL   6
175
 
 
176
 
/* output socket type definition */
177
 
static bNodeSocketType sh_node_geom_out[]= {
178
 
        {       SOCK_VECTOR, 0, "Global",       0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},   /* btw; uses no limit */
179
 
        {       SOCK_VECTOR, 0, "Local",        0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
180
 
        {       SOCK_VECTOR, 0, "View", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
181
 
        {       SOCK_VECTOR, 0, "Orco", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
182
 
        {       SOCK_VECTOR, 0, "UV",   0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
183
 
        {       SOCK_VECTOR, 0, "Normal",       0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
184
 
        {       SOCK_RGBA,   0, "Vertex Color", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
185
 
        {       -1, 0, ""       }
186
 
};
187
 
 
188
 
/* node execute callback */
189
 
static void node_shader_exec_geom(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
190
 
{
191
 
        if(data) {
192
 
                ShadeInput *shi= ((ShaderCallData *)data)->shi;
193
 
                NodeGeometry *ngeo= (NodeGeometry*)node->storage;
194
 
                ShadeInputUV *suv= &shi->uv[0];
195
 
                static float defaultvcol[4] = {1.0f, 1.0f, 1.0f, 1.0f};
196
 
                int i;
197
 
 
198
 
                if(ngeo->uvname[0]) {
199
 
                        /* find uv layer by name */
200
 
                        for(i = 0; i < shi->totuv; i++) {
201
 
                                if(strcmp(shi->uv[i].name, ngeo->uvname)==0) {
202
 
                                        suv= &shi->uv[i];
203
 
                                        break;
204
 
                                }
205
 
                        }
206
 
                }
207
 
 
208
 
                /* out: global, local, view, orco, uv, normal, vertex color */
209
 
                VECCOPY(out[GEOM_OUT_GLOB]->vec, shi->gl);
210
 
                VECCOPY(out[GEOM_OUT_LOCAL]->vec, shi->co);
211
 
                VECCOPY(out[GEOM_OUT_VIEW]->vec, shi->view);
212
 
                VECCOPY(out[GEOM_OUT_ORCO]->vec, shi->lo);
213
 
                VECCOPY(out[GEOM_OUT_UV]->vec, suv->uv);
214
 
                VECCOPY(out[GEOM_OUT_NORMAL]->vec, shi->vno);
215
 
 
216
 
                if (shi->totcol) {
217
 
                        /* find vertex color layer by name */
218
 
                        ShadeInputCol *scol= &shi->col[0];
219
 
 
220
 
                        if(ngeo->colname[0]) {
221
 
                                for(i = 0; i < shi->totcol; i++) {
222
 
                                        if(strcmp(shi->col[i].name, ngeo->colname)==0) {
223
 
                                                scol= &shi->col[i];
224
 
                                                break;
225
 
                                        }
226
 
                                }
227
 
                        }
228
 
 
229
 
                        VECCOPY(out[GEOM_OUT_VCOL]->vec, scol->col);
230
 
                        out[GEOM_OUT_VCOL]->vec[3]= 1.0f;
231
 
                }
232
 
                else
233
 
                        memcpy(out[GEOM_OUT_VCOL]->vec, defaultvcol, sizeof(defaultvcol));
234
 
                
235
 
                if(shi->osatex) {
236
 
                        out[GEOM_OUT_GLOB]->data= shi->dxgl;
237
 
                        out[GEOM_OUT_GLOB]->datatype= NS_OSA_VECTORS;
238
 
                        out[GEOM_OUT_LOCAL]->data= shi->dxco;
239
 
                        out[GEOM_OUT_LOCAL]->datatype= NS_OSA_VECTORS;
240
 
                        out[GEOM_OUT_VIEW]->data= &shi->dxview;
241
 
                        out[GEOM_OUT_VIEW]->datatype= NS_OSA_VALUES;
242
 
                        out[GEOM_OUT_ORCO]->data= shi->dxlo;
243
 
                        out[GEOM_OUT_ORCO]->datatype= NS_OSA_VECTORS;
244
 
                        out[GEOM_OUT_UV]->data= suv->dxuv;
245
 
                        out[GEOM_OUT_UV]->datatype= NS_OSA_VECTORS;
246
 
                        out[GEOM_OUT_NORMAL]->data= shi->dxno;
247
 
                        out[GEOM_OUT_NORMAL]->datatype= NS_OSA_VECTORS;
248
 
                }
249
 
        }
250
 
}
251
 
 
252
 
/* node type definition */
253
 
static bNodeType sh_node_geom= {
254
 
        /* type code   */       SH_NODE_GEOMETRY,
255
 
        /* name        */       "Geometry",
256
 
        /* width+range */       120, 80, 160,
257
 
        /* class+opts  */       NODE_CLASS_INPUT, NODE_OPTIONS,
258
 
        /* input sock  */       NULL,
259
 
        /* output sock */       sh_node_geom_out,
260
 
        /* storage     */       "NodeGeometry",
261
 
        /* execfunc    */       node_shader_exec_geom
262
 
        
263
 
};
264
 
 
265
 
/* **************** MATERIAL ******************** */
266
 
 
267
 
/* input socket defines */
268
 
#define MAT_IN_COLOR    0
269
 
#define MAT_IN_SPEC             1
270
 
#define MAT_IN_REFL             2
271
 
#define MAT_IN_NORMAL   3
272
 
 
273
 
static bNodeSocketType sh_node_material_in[]= {
274
 
        {       SOCK_RGBA, 1, "Color",          0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
275
 
        {       SOCK_RGBA, 1, "Spec",           0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
276
 
        {       SOCK_VALUE, 1, "Refl",          0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
277
 
        {       SOCK_VECTOR, 1, "Normal",       0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
278
 
        {       -1, 0, ""       }
279
 
};
280
 
 
281
 
/* output socket defines */
282
 
#define MAT_OUT_COLOR   0
283
 
#define MAT_OUT_ALPHA   1
284
 
#define MAT_OUT_NORMAL  2
285
 
 
286
 
static bNodeSocketType sh_node_material_out[]= {
287
 
        {       SOCK_RGBA, 0, "Color",          0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
288
 
        {       SOCK_VALUE, 0, "Alpha",         1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
289
 
        {       SOCK_VECTOR, 0, "Normal",       0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
290
 
        {       -1, 0, ""       }
291
 
};
292
 
 
293
 
static void node_shader_exec_material(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
294
 
{
295
 
        if(data && node->id) {
296
 
                ShadeResult shrnode;
297
 
                ShadeInput *shi;
298
 
                ShaderCallData *shcd= data;
299
 
                float col[4];
300
 
                
301
 
                shi= shcd->shi;
302
 
                shi->mat= (Material *)node->id;
303
 
                
304
 
                /* copy all relevant material vars, note, keep this synced with render_types.h */
305
 
                memcpy(&shi->r, &shi->mat->r, 23*sizeof(float));
306
 
                shi->har= shi->mat->har;
307
 
                
308
 
                /* write values */
309
 
                if(in[MAT_IN_COLOR]->hasinput)
310
 
                        nodestack_get_vec(&shi->r, SOCK_VECTOR, in[MAT_IN_COLOR]);
311
 
                
312
 
                if(in[MAT_IN_SPEC]->hasinput)
313
 
                        nodestack_get_vec(&shi->specr, SOCK_VECTOR, in[MAT_IN_SPEC]);
314
 
                
315
 
                if(in[MAT_IN_REFL]->hasinput)
316
 
                        nodestack_get_vec(&shi->refl, SOCK_VALUE, in[MAT_IN_REFL]);
317
 
                
318
 
                /* retrieve normal */
319
 
                if(in[MAT_IN_NORMAL]->hasinput) {
320
 
                        nodestack_get_vec(shi->vn, SOCK_VECTOR, in[MAT_IN_NORMAL]);
321
 
                        Normalise(shi->vn);
322
 
                }
323
 
                else
324
 
                        VECCOPY(shi->vn, shi->vno);
325
 
                
326
 
                /* custom option to flip normal */
327
 
                if(node->custom1 & SH_NODE_MAT_NEG) {
328
 
                        shi->vn[0]= -shi->vn[0];
329
 
                        shi->vn[1]= -shi->vn[1];
330
 
                        shi->vn[2]= -shi->vn[2];
331
 
                }
332
 
                
333
 
                node_shader_lamp_loop(shi, &shrnode);   /* clears shrnode */
334
 
                
335
 
                /* write to outputs */
336
 
                if(node->custom1 & SH_NODE_MAT_DIFF) {
337
 
                        VECCOPY(col, shrnode.combined);
338
 
                        if(!(node->custom1 & SH_NODE_MAT_SPEC)) {
339
 
                                VecSubf(col, col, shrnode.spec);
340
 
                        }
341
 
                }
342
 
                else if(node->custom1 & SH_NODE_MAT_SPEC) {
343
 
                        VECCOPY(col, shrnode.spec);
344
 
                }
345
 
                else
346
 
                        col[0]= col[1]= col[2]= 0.0f;
347
 
                
348
 
                col[3]= shrnode.alpha;
349
 
                
350
 
                if(shi->do_preview)
351
 
                        nodeAddToPreview(node, col, shi->xs, shi->ys);
352
 
                
353
 
                VECCOPY(out[MAT_OUT_COLOR]->vec, col);
354
 
                out[MAT_OUT_ALPHA]->vec[0]= shrnode.alpha;
355
 
                
356
 
                if(node->custom1 & SH_NODE_MAT_NEG) {
357
 
                        shi->vn[0]= -shi->vn[0];
358
 
                        shi->vn[1]= -shi->vn[1];
359
 
                        shi->vn[2]= -shi->vn[2];
360
 
                }
361
 
                
362
 
                VECCOPY(out[MAT_OUT_NORMAL]->vec, shi->vn);
363
 
                
364
 
                /* copy passes, now just active node */
365
 
                if(node->flag & NODE_ACTIVE_ID)
366
 
                        *(shcd->shr)= shrnode;
367
 
        }
368
 
}
369
 
 
370
 
static bNodeType sh_node_material= {
371
 
        /* type code   */       SH_NODE_MATERIAL,
372
 
        /* name        */       "Material",
373
 
        /* width+range */       120, 80, 240,
374
 
        /* class+opts  */       NODE_CLASS_INPUT, NODE_OPTIONS|NODE_PREVIEW,
375
 
        /* input sock  */       sh_node_material_in,
376
 
        /* output sock */       sh_node_material_out,
377
 
        /* storage     */       "",
378
 
        /* execfunc    */       node_shader_exec_material
379
 
        
380
 
};
381
 
 
382
 
/* **************** TEXTURE ******************** */
383
 
static bNodeSocketType sh_node_texture_in[]= {
384
 
        {       SOCK_VECTOR, 1, "Vector",       0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},   /* no limit */
385
 
        {       -1, 0, ""       }
386
 
};
387
 
static bNodeSocketType sh_node_texture_out[]= {
388
 
        {       SOCK_VALUE, 0, "Value",         1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
389
 
        {       SOCK_RGBA , 0, "Color",         1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f},
390
 
        {       SOCK_VECTOR, 0, "Normal",       0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
391
 
        {       -1, 0, ""       }
392
 
};
393
 
 
394
 
static void node_shader_exec_texture(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
395
 
{
396
 
        if(data && node->id) {
397
 
                ShadeInput *shi= ((ShaderCallData *)data)->shi;
398
 
                TexResult texres;
399
 
                float vec[3], nor[3]={0.0f, 0.0f, 0.0f};
400
 
                int retval;
401
 
                
402
 
                /* out: value, color, normal */
403
 
                
404
 
                /* we should find out if a normal as output is needed, for now we do all */
405
 
                texres.nor= nor;
406
 
                
407
 
                if(in[0]->hasinput) {
408
 
                        nodestack_get_vec(vec, SOCK_VECTOR, in[0]);
409
 
                        
410
 
                        if(in[0]->datatype==NS_OSA_VECTORS) {
411
 
                                float *fp= in[0]->data;
412
 
                                retval= multitex_ext((Tex *)node->id, vec, fp, fp+3, shi->osatex, &texres);
413
 
                        }
414
 
                        else if(in[0]->datatype==NS_OSA_VALUES) {
415
 
                                float *fp= in[0]->data;
416
 
                                float dxt[3], dyt[3];
417
 
                                
418
 
                                dxt[0]= fp[0]; dxt[1]= dxt[2]= 0.0f;
419
 
                                dyt[0]= fp[1]; dyt[1]= dyt[2]= 0.0f;
420
 
                                retval= multitex_ext((Tex *)node->id, vec, dxt, dyt, shi->osatex, &texres);
421
 
                        }
422
 
                        else
423
 
                                retval= multitex_ext((Tex *)node->id, vec, NULL, NULL, 0, &texres);
424
 
                }
425
 
                else {  /* only for previewrender, so we see stuff */
426
 
                        VECCOPY(vec, shi->lo);
427
 
                        retval= multitex_ext((Tex *)node->id, vec, NULL, NULL, 0, &texres);
428
 
                }
429
 
                
430
 
                /* stupid exception */
431
 
                if( ((Tex *)node->id)->type==TEX_STUCCI) {
432
 
                        texres.tin= 0.5f + 0.7f*texres.nor[0];
433
 
                        CLAMP(texres.tin, 0.0f, 1.0f);
434
 
                }
435
 
                
436
 
                /* intensity and color need some handling */
437
 
                if(texres.talpha)
438
 
                        out[0]->vec[0]= texres.ta;
439
 
                else
440
 
                        out[0]->vec[0]= texres.tin;
441
 
                
442
 
                if((retval & TEX_RGB)==0) {
443
 
                        out[1]->vec[0]= out[0]->vec[0];
444
 
                        out[1]->vec[1]= out[0]->vec[0];
445
 
                        out[1]->vec[2]= out[0]->vec[0];
446
 
                        out[1]->vec[3]= 1.0f;
447
 
                }
448
 
                else {
449
 
                        out[1]->vec[0]= texres.tr;
450
 
                        out[1]->vec[1]= texres.tg;
451
 
                        out[1]->vec[2]= texres.tb;
452
 
                        out[1]->vec[3]= 1.0f;
453
 
                }
454
 
                
455
 
                VECCOPY(out[2]->vec, nor);
456
 
                
457
 
                if(shi->do_preview)
458
 
                        nodeAddToPreview(node, out[1]->vec, shi->xs, shi->ys);
459
 
                
460
 
        }
461
 
}
462
 
 
463
 
static bNodeType sh_node_texture= {
464
 
        /* type code   */       SH_NODE_TEXTURE,
465
 
        /* name        */       "Texture",
466
 
        /* width+range */       120, 80, 240,
467
 
        /* class+opts  */       NODE_CLASS_INPUT, NODE_OPTIONS|NODE_PREVIEW,
468
 
        /* input sock  */       sh_node_texture_in,
469
 
        /* output sock */       sh_node_texture_out,
470
 
        /* storage     */       "",
471
 
        /* execfunc    */       node_shader_exec_texture
472
 
        
473
 
};
474
 
 
475
 
/* **************** MAPPING  ******************** */
476
 
static bNodeSocketType sh_node_mapping_in[]= {
477
 
        {       SOCK_VECTOR, 1, "Vector",       0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
478
 
        {       -1, 0, ""       }
479
 
};
480
 
 
481
 
static bNodeSocketType sh_node_mapping_out[]= {
482
 
        {       SOCK_VECTOR, 0, "Vector",       0.0f, 0.0f, 1.0f, 1.0f, -1.0f, 1.0f},
483
 
        {       -1, 0, ""       }
484
 
};
485
 
 
486
 
/* do the regular mapping options for blender textures */
487
 
static void node_shader_exec_mapping(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
488
 
{
489
 
        TexMapping *texmap= node->storage;
490
 
        float *vec= out[0]->vec;
491
 
        
492
 
        /* stack order input:  vector */
493
 
        /* stack order output: vector */
494
 
        nodestack_get_vec(vec, SOCK_VECTOR, in[0]);
495
 
        Mat4MulVecfl(texmap->mat, vec);
496
 
        
497
 
        if(texmap->flag & TEXMAP_CLIP_MIN) {
498
 
                if(vec[0]<texmap->min[0]) vec[0]= texmap->min[0];
499
 
                if(vec[1]<texmap->min[1]) vec[1]= texmap->min[1];
500
 
                if(vec[2]<texmap->min[2]) vec[2]= texmap->min[2];
501
 
        }
502
 
        if(texmap->flag & TEXMAP_CLIP_MAX) {
503
 
                if(vec[0]>texmap->max[0]) vec[0]= texmap->max[0];
504
 
                if(vec[1]>texmap->max[1]) vec[1]= texmap->max[1];
505
 
                if(vec[2]>texmap->max[2]) vec[2]= texmap->max[2];
506
 
        }
507
 
}
508
 
 
509
 
static bNodeType sh_node_mapping= {
510
 
        /* type code   */       SH_NODE_MAPPING,
511
 
        /* name        */       "Mapping",
512
 
        /* width+range */       240, 160, 320,
513
 
        /* class+opts  */       NODE_CLASS_OP_VECTOR, NODE_OPTIONS,
514
 
        /* input sock  */       sh_node_mapping_in,
515
 
        /* output sock */       sh_node_mapping_out,
516
 
        /* storage     */       "TexMapping",
517
 
        /* execfunc    */       node_shader_exec_mapping
518
 
        
519
 
};
520
 
 
521
 
/* **************** CAMERA INFO  ******************** */
522
 
static bNodeSocketType sh_node_camera_out[]= {
523
 
        {       SOCK_VECTOR, 0, "View Vector",                  1.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f},           /* None of these actually */
524
 
        {       SOCK_VALUE, 0, "View Z Depth",                  0.f, 0.0f, 0.0f, 0.0f, 0.0f, 99999999999.0f},   /* have any limits on their */
525
 
        {       SOCK_VALUE, 0, "View Distance",                 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 99999999999.0f},  /* values. */
526
 
        {       -1, 0, ""       }
527
 
};
528
 
 
529
 
 
530
 
static void node_shader_exec_camera(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
531
 
{
532
 
        if(data) {
533
 
                ShadeInput *shi= ((ShaderCallData *)data)->shi;  /* Data we need for shading. */
534
 
                
535
 
                VECCOPY(out[0]->vec, shi->co);          /* get view vector */
536
 
                out[1]->vec[0]= fabs(shi->co[2]);               /* get view z-depth */
537
 
                out[2]->vec[0]= Normalise(out[0]->vec); /* get view distance */
538
 
                }
539
 
        }
540
 
 
541
 
static bNodeType sh_node_camera= {
542
 
        /* type code   */       SH_NODE_CAMERA,
543
 
        /* name        */       "Camera Data",
544
 
        /* width+range */       95, 95, 120,
545
 
        /* class+opts  */       NODE_CLASS_INPUT, 0,
546
 
        /* input sock  */       NULL,
547
 
        /* output sock */       sh_node_camera_out,
548
 
        /* storage     */       "node_camera",
549
 
        /* execfunc    */       node_shader_exec_camera 
550
 
};
551
 
 
552
 
/* **************** SCALAR MATH ******************** */ 
553
 
static bNodeSocketType sh_node_math_in[]= { 
554
 
        { SOCK_VALUE, 1, "Value", 0.5f, 0.5f, 0.5f, 1.0f, -100.0f, 100.0f}, 
555
 
        { SOCK_VALUE, 1, "Value", 0.5f, 0.5f, 0.5f, 1.0f, -100.0f, 100.0f}, 
556
 
        { -1, 0, "" } 
557
 
};
558
 
 
559
 
static bNodeSocketType sh_node_math_out[]= { 
560
 
        { SOCK_VALUE, 0, "Value", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, 
561
 
        { -1, 0, "" } 
562
 
};
563
 
 
564
 
static void node_shader_exec_math(void *data, bNode *node, bNodeStack **in, 
565
 
bNodeStack **out) 
566
 
{
567
 
        switch(node->custom1){ 
568
 
        
569
 
        case 0: /* Add */
570
 
                out[0]->vec[0]= in[0]->vec[0] + in[1]->vec[0]; 
571
 
                break; 
572
 
        case 1: /* Subtract */
573
 
                out[0]->vec[0]= in[0]->vec[0] - in[1]->vec[0];
574
 
                break; 
575
 
        case 2: /* Multiply */
576
 
                out[0]->vec[0]= in[0]->vec[0] * in[1]->vec[0]; 
577
 
                break; 
578
 
        case 3: /* Divide */
579
 
                {
580
 
                        if(in[1]->vec[0]==0)    /* We don't want to divide by zero. */
581
 
                                out[0]->vec[0]= 0.0;
582
 
                        else
583
 
                                out[0]->vec[0]= in[0]->vec[0] / in[1]->vec[0];
584
 
                        }
585
 
                break;
586
 
        case 4: /* Sine */
587
 
                {
588
 
                        if(in[0]->hasinput || !in[1]->hasinput)  /* This one only takes one input, so we've got to choose. */
589
 
                                out[0]->vec[0]= sin(in[0]->vec[0]);
590
 
                        else
591
 
                                out[0]->vec[0]= sin(in[1]->vec[0]);
592
 
                }
593
 
                break;
594
 
        case 5: /* Cosine */
595
 
                {
596
 
                        if(in[0]->hasinput || !in[1]->hasinput)  /* This one only takes one input, so we've got to choose. */   
597
 
                                out[0]->vec[0]= cos(in[0]->vec[0]);
598
 
                        else
599
 
                                out[0]->vec[0]= cos(in[1]->vec[0]);
600
 
                }
601
 
                break;
602
 
        case 6: /* Tangent */
603
 
                {
604
 
                        if(in[0]->hasinput || !in[1]->hasinput)  /* This one only takes one input, so we've got to choose. */   
605
 
                                out[0]->vec[0]= tan(in[0]->vec[0]);
606
 
                        else
607
 
                                out[0]->vec[0]= tan(in[1]->vec[0]);
608
 
                }
609
 
                break;
610
 
        case 7: /* Arc-Sine */
611
 
                {
612
 
                        if(in[0]->hasinput || !in[1]->hasinput) { /* This one only takes one input, so we've got to choose. */
613
 
                                /* Can't do the impossible... */
614
 
                                if( in[0]->vec[0] <= 1 && in[0]->vec[0] >= -1 )
615
 
                                        out[0]->vec[0]= asin(in[0]->vec[0]);
616
 
                                else
617
 
                                        out[0]->vec[0]= 0.0;
618
 
                        }
619
 
                        else {
620
 
                                /* Can't do the impossible... */
621
 
                                if( in[1]->vec[0] <= 1 && in[1]->vec[0] >= -1 )
622
 
                                        out[0]->vec[0]= asin(in[1]->vec[0]);
623
 
                                else
624
 
                                        out[0]->vec[0]= 0.0;
625
 
                        }
626
 
                }
627
 
                break;
628
 
        case 8: /* Arc-Cosine */
629
 
                {
630
 
                        if(in[0]->hasinput || !in[1]->hasinput) { /* This one only takes one input, so we've got to choose. */
631
 
                                /* Can't do the impossible... */
632
 
                                if( in[0]->vec[0] <= 1 && in[0]->vec[0] >= -1 )
633
 
                                        out[0]->vec[0]= acos(in[0]->vec[0]);
634
 
                                else
635
 
                                        out[0]->vec[0]= 0.0;
636
 
                        }
637
 
                        else {
638
 
                                /* Can't do the impossible... */
639
 
                                if( in[1]->vec[0] <= 1 && in[1]->vec[0] >= -1 )
640
 
                                        out[0]->vec[0]= acos(in[1]->vec[0]);
641
 
                                else
642
 
                                        out[0]->vec[0]= 0.0;
643
 
                        }
644
 
                }
645
 
                break;
646
 
        case 9: /* Arc-Tangent */
647
 
                {
648
 
                        if(in[0]->hasinput || !in[1]->hasinput) /* This one only takes one input, so we've got to choose. */
649
 
                                out[0]->vec[0]= atan(in[0]->vec[0]);
650
 
                        else
651
 
                                out[0]->vec[0]= atan(in[1]->vec[0]);
652
 
                }
653
 
                break;
654
 
        case 10: /* Power */
655
 
                {
656
 
                        /* Don't want any imaginary numbers... */
657
 
                        if( in[0]->vec[0] >= 0 )
658
 
                                out[0]->vec[0]= pow(in[0]->vec[0], in[1]->vec[0]);
659
 
                        else
660
 
                                out[0]->vec[0]= 0.0;
661
 
                }
662
 
                break;
663
 
        case 11: /* Logarithm */
664
 
                {
665
 
                        /* Don't want any imaginary numbers... */
666
 
                        if( in[0]->vec[0] > 0  && in[1]->vec[0] > 0 )
667
 
                                out[0]->vec[0]= log(in[0]->vec[0]) / log(in[1]->vec[0]);
668
 
                        else
669
 
                                out[0]->vec[0]= 0.0;
670
 
                }
671
 
                break;
672
 
        case 12: /* Minimum */
673
 
                {
674
 
                        if( in[0]->vec[0] < in[1]->vec[0] )
675
 
                                out[0]->vec[0]= in[0]->vec[0];
676
 
                        else
677
 
                                out[0]->vec[0]= in[1]->vec[0];
678
 
                }
679
 
                break;
680
 
        case 13: /* Maximum */
681
 
                {
682
 
                        if( in[0]->vec[0] > in[1]->vec[0] )
683
 
                                out[0]->vec[0]= in[0]->vec[0];
684
 
                        else
685
 
                                out[0]->vec[0]= in[1]->vec[0];
686
 
                }
687
 
                break;
688
 
        case 14: /* Round */
689
 
                {
690
 
                        if(in[0]->hasinput || !in[1]->hasinput) /* This one only takes one input, so we've got to choose. */
691
 
                                out[0]->vec[0]= (int)(in[0]->vec[0] + 0.5f);
692
 
                        else
693
 
                                out[0]->vec[0]= (int)(in[1]->vec[0] + 0.5f);
694
 
                }
695
 
                break; 
696
 
        } 
697
 
}
698
 
 
699
 
static bNodeType sh_node_math= { 
700
 
        /* type code   */ SH_NODE_MATH, 
701
 
        /* name        */ "Math", 
702
 
        /* width+range */ 120, 110, 160, 
703
 
        /* class+opts  */ NODE_CLASS_CONVERTOR, NODE_OPTIONS, 
704
 
        /* input sock  */ sh_node_math_in, 
705
 
        /* output sock */ sh_node_math_out, 
706
 
        /* storage     */ "node_math", 
707
 
        /* execfunc    */ node_shader_exec_math 
708
 
};
709
 
 
710
 
/* **************** VALUE SQUEEZE ******************** */ 
711
 
static bNodeSocketType sh_node_squeeze_in[]= { 
712
 
        { SOCK_VALUE, 1, "Value", 0.0f, 0.0f, 0.0f, 0.0f, -100.0f, 100.0f}, 
713
 
        { SOCK_VALUE, 1, "Width", 1.0f, 0.0f, 0.0f, 0.0f, -100.0f, 100.0f}, 
714
 
        { SOCK_VALUE, 1, "Center", 0.0f, 0.0f, 0.0f, 0.0f, -100.0f, 100.0f}, 
715
 
        { -1, 0, "" } 
716
 
};
717
 
 
718
 
static bNodeSocketType sh_node_squeeze_out[]= { 
719
 
        { SOCK_VALUE, 0, "Value", 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, 
720
 
        { -1, 0, "" } 
721
 
};
722
 
 
723
 
static void node_shader_exec_squeeze(void *data, bNode *node, bNodeStack **in, 
724
 
bNodeStack **out) 
725
 
{
726
 
        float vec[3];
727
 
        
728
 
        nodestack_get_vec(vec, SOCK_VALUE, in[0]);
729
 
        nodestack_get_vec(vec+1, SOCK_VALUE, in[1]);
730
 
        nodestack_get_vec(vec+2, SOCK_VALUE, in[2]);
731
 
 
732
 
    out[0]->vec[0] = 1.0f / (1.0f + pow(2.71828183,-((vec[0]-vec[2])*vec[1]))) ;
733
 
}
734
 
 
735
 
static bNodeType sh_node_squeeze= { 
736
 
        /* type code   */ SH_NODE_SQUEEZE, 
737
 
        /* name        */ "Squeeze Value", 
738
 
        /* width+range */ 120, 110, 160, 
739
 
        /* class+opts  */ NODE_CLASS_CONVERTOR, NODE_OPTIONS, 
740
 
        /* input sock  */ sh_node_squeeze_in, 
741
 
        /* output sock */ sh_node_squeeze_out, 
742
 
        /* storage     */ "node_squeeze", 
743
 
        /* execfunc    */ node_shader_exec_squeeze 
744
 
};
745
 
 
746
 
 
747
 
 
748
 
/* **************** VECTOR MATH ******************** */ 
749
 
static bNodeSocketType sh_node_vect_math_in[]= { 
750
 
        { SOCK_VECTOR, 1, "Vector", 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f}, 
751
 
        { SOCK_VECTOR, 1, "Vector", 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f}, 
752
 
        { -1, 0, "" } 
753
 
};
754
 
 
755
 
static bNodeSocketType sh_node_vect_math_out[]= {
756
 
        { SOCK_VECTOR, 0, "Vector", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, 
757
 
        { SOCK_VALUE, 0, "Value", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
758
 
        { -1, 0, "" } 
759
 
};
760
 
 
761
 
static void node_shader_exec_vect_math(void *data, bNode *node, bNodeStack **in, bNodeStack **out) 
762
 
763
 
        float vec1[3], vec2[3];
764
 
        
765
 
        nodestack_get_vec(vec1, SOCK_VECTOR, in[0]);
766
 
        nodestack_get_vec(vec2, SOCK_VECTOR, in[1]);
767
 
        
768
 
        if(node->custom1 == 0) {        /* Add */
769
 
                out[0]->vec[0]= vec1[0] + vec2[0];
770
 
                out[0]->vec[1]= vec1[1] + vec2[1];
771
 
                out[0]->vec[2]= vec1[2] + vec2[2];
772
 
                
773
 
                out[1]->vec[0]= (fabs(out[0]->vec[0]) + fabs(out[0]->vec[0]) + fabs(out[0]->vec[0])) / 3;
774
 
        }
775
 
        else if(node->custom1 == 1) {   /* Subtract */
776
 
                out[0]->vec[0]= vec1[0] - vec2[0];
777
 
                out[0]->vec[1]= vec1[1] - vec2[1];
778
 
                out[0]->vec[2]= vec1[2] - vec2[2];
779
 
                
780
 
                out[1]->vec[0]= (fabs(out[0]->vec[0]) + fabs(out[0]->vec[0]) + fabs(out[0]->vec[0])) / 3;
781
 
        }
782
 
        else if(node->custom1 == 2) {   /* Average */
783
 
                out[0]->vec[0]= vec1[0] + vec2[0];
784
 
                out[0]->vec[1]= vec1[1] + vec2[1];
785
 
                out[0]->vec[2]= vec1[2] + vec2[2];
786
 
                
787
 
                out[1]->vec[0] = Normalise( out[0]->vec );
788
 
        }
789
 
        else if(node->custom1 == 3) {   /* Dot product */
790
 
                out[1]->vec[0]= (vec1[0] * vec2[0]) + (vec1[1] * vec2[1]) + (vec1[2] * vec2[2]);
791
 
        }
792
 
        else if(node->custom1 == 4) {   /* Cross product */
793
 
                out[0]->vec[0]= (vec1[1] * vec2[2]) - (vec1[2] * vec2[1]);
794
 
                out[0]->vec[1]= (vec1[2] * vec2[0]) - (vec1[0] * vec2[2]);
795
 
                out[0]->vec[2]= (vec1[0] * vec2[1]) - (vec1[1] * vec2[0]);
796
 
                
797
 
                out[1]->vec[0] = Normalise( out[0]->vec );
798
 
        }
799
 
        else if(node->custom1 == 5) {   /* Normalize */
800
 
                if(in[0]->hasinput || !in[1]->hasinput) {       /* This one only takes one input, so we've got to choose. */
801
 
                        out[0]->vec[0]= vec1[0];
802
 
                        out[0]->vec[1]= vec1[1];
803
 
                        out[0]->vec[2]= vec1[2];
804
 
                }
805
 
                else {
806
 
                        out[0]->vec[0]= vec2[0];
807
 
                        out[0]->vec[1]= vec2[1];
808
 
                        out[0]->vec[2]= vec2[2];
809
 
                }
810
 
                
811
 
                out[1]->vec[0] = Normalise( out[0]->vec );
812
 
        }
813
 
        
814
 
}
815
 
 
816
 
static bNodeType sh_node_vect_math= { 
817
 
        /* type code   */ SH_NODE_VECT_MATH, 
818
 
        /* name        */ "Vector Math", 
819
 
        /* width+range */ 80, 75, 140, 
820
 
        /* class+opts  */ NODE_CLASS_CONVERTOR, NODE_OPTIONS, 
821
 
        /* input sock  */ sh_node_vect_math_in, 
822
 
        /* output sock */ sh_node_vect_math_out, 
823
 
        /* storage     */ "node_vect_math", 
824
 
        /* execfunc    */ node_shader_exec_vect_math 
825
 
};
826
 
 
827
 
/* **************** NORMAL  ******************** */
828
 
static bNodeSocketType sh_node_normal_in[]= {
829
 
        {       SOCK_VECTOR, 1, "Normal",       0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
830
 
        {       -1, 0, ""       }
831
 
};
832
 
 
833
 
static bNodeSocketType sh_node_normal_out[]= {
834
 
        {       SOCK_VECTOR, 0, "Normal",       0.0f, 0.0f, 1.0f, 1.0f, -1.0f, 1.0f},
835
 
        {       SOCK_VALUE, 0, "Dot",           1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
836
 
        {       -1, 0, ""       }
837
 
};
838
 
 
839
 
/* generates normal, does dot product */
840
 
static void node_shader_exec_normal(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
841
 
{
842
 
        bNodeSocket *sock= node->outputs.first;
843
 
        float vec[3];
844
 
        
845
 
        /* stack order input:  normal */
846
 
        /* stack order output: normal, value */
847
 
        
848
 
        nodestack_get_vec(vec, SOCK_VECTOR, in[0]);
849
 
        
850
 
        VECCOPY(out[0]->vec, sock->ns.vec);
851
 
        /* render normals point inside... the widget points outside */
852
 
        out[1]->vec[0]= -INPR(out[0]->vec, vec);
853
 
}
854
 
 
855
 
static bNodeType sh_node_normal= {
856
 
        /* type code   */       SH_NODE_NORMAL,
857
 
        /* name        */       "Normal",
858
 
        /* width+range */       100, 60, 200,
859
 
        /* class+opts  */       NODE_CLASS_OP_VECTOR, NODE_OPTIONS,
860
 
        /* input sock  */       sh_node_normal_in,
861
 
        /* output sock */       sh_node_normal_out,
862
 
        /* storage     */       "",
863
 
        /* execfunc    */       node_shader_exec_normal
864
 
        
865
 
};
866
 
 
867
 
/* **************** CURVE VEC  ******************** */
868
 
static bNodeSocketType sh_node_curve_vec_in[]= {
869
 
        {       SOCK_VECTOR, 1, "Vector",       0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
870
 
        {       -1, 0, ""       }
871
 
};
872
 
 
873
 
static bNodeSocketType sh_node_curve_vec_out[]= {
874
 
        {       SOCK_VECTOR, 0, "Vector",       0.0f, 0.0f, 1.0f, 1.0f, -1.0f, 1.0f},
875
 
        {       -1, 0, ""       }
876
 
};
877
 
 
878
 
static void node_shader_exec_curve_vec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
879
 
{
880
 
        float vec[3];
881
 
        
882
 
        /* stack order input:  vec */
883
 
        /* stack order output: vec */
884
 
        nodestack_get_vec(vec, SOCK_VECTOR, in[0]);
885
 
        curvemapping_evaluate3F(node->storage, out[0]->vec, vec);
886
 
}
887
 
 
888
 
static bNodeType sh_node_curve_vec= {
889
 
        /* type code   */       SH_NODE_CURVE_VEC,
890
 
        /* name        */       "Vector Curves",
891
 
        /* width+range */       200, 140, 320,
892
 
        /* class+opts  */       NODE_CLASS_OP_VECTOR, NODE_OPTIONS,
893
 
        /* input sock  */       sh_node_curve_vec_in,
894
 
        /* output sock */       sh_node_curve_vec_out,
895
 
        /* storage     */       "CurveMapping",
896
 
        /* execfunc    */       node_shader_exec_curve_vec
897
 
        
898
 
};
899
 
 
900
 
/* **************** CURVE RGB  ******************** */
901
 
static bNodeSocketType sh_node_curve_rgb_in[]= {
902
 
        {       SOCK_RGBA, 1, "Color",  0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
903
 
        {       -1, 0, ""       }
904
 
};
905
 
 
906
 
static bNodeSocketType sh_node_curve_rgb_out[]= {
907
 
        {       SOCK_RGBA, 0, "Color",  0.0f, 0.0f, 1.0f, 1.0f, -1.0f, 1.0f},
908
 
        {       -1, 0, ""       }
909
 
};
910
 
 
911
 
static void node_shader_exec_curve_rgb(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
912
 
{
913
 
        float vec[3];
914
 
        
915
 
        /* stack order input:  vec */
916
 
        /* stack order output: vec */
917
 
        nodestack_get_vec(vec, SOCK_VECTOR, in[0]);
918
 
        curvemapping_evaluateRGBF(node->storage, out[0]->vec, vec);
919
 
}
920
 
 
921
 
static bNodeType sh_node_curve_rgb= {
922
 
        /* type code   */       SH_NODE_CURVE_RGB,
923
 
        /* name        */       "RGB Curves",
924
 
        /* width+range */       200, 140, 320,
925
 
        /* class+opts  */       NODE_CLASS_OP_COLOR, NODE_OPTIONS,
926
 
        /* input sock  */       sh_node_curve_rgb_in,
927
 
        /* output sock */       sh_node_curve_rgb_out,
928
 
        /* storage     */       "CurveMapping",
929
 
        /* execfunc    */       node_shader_exec_curve_rgb
930
 
        
931
 
};
932
 
 
933
 
/* **************** VALUE ******************** */
934
 
static bNodeSocketType sh_node_value_out[]= {
935
 
        {       SOCK_VALUE, 0, "Value",         0.5f, 0.0f, 0.0f, 0.0f, -100.0f, 100.0f},
936
 
        {       -1, 0, ""       }
937
 
};
938
 
 
939
 
static void node_shader_exec_value(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
940
 
{
941
 
        bNodeSocket *sock= node->outputs.first;
942
 
        
943
 
        out[0]->vec[0]= sock->ns.vec[0];
944
 
}
945
 
 
946
 
static bNodeType sh_node_value= {
947
 
        /* type code   */       SH_NODE_VALUE,
948
 
        /* name        */       "Value",
949
 
        /* width+range */       80, 50, 120,
950
 
        /* class+opts  */       NODE_CLASS_INPUT, NODE_OPTIONS,
951
 
        /* input sock  */       NULL,
952
 
        /* output sock */       sh_node_value_out,
953
 
        /* storage     */       "", 
954
 
        /* execfunc    */       node_shader_exec_value
955
 
        
956
 
};
957
 
 
958
 
/* **************** RGB ******************** */
959
 
static bNodeSocketType sh_node_rgb_out[]= {
960
 
        {       SOCK_RGBA, 0, "Color",                  0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f},
961
 
        {       -1, 0, ""       }
962
 
};
963
 
 
964
 
static void node_shader_exec_rgb(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
965
 
{
966
 
        bNodeSocket *sock= node->outputs.first;
967
 
        
968
 
        VECCOPY(out[0]->vec, sock->ns.vec);
969
 
}
970
 
 
971
 
static bNodeType sh_node_rgb= {
972
 
        /* type code   */       SH_NODE_RGB,
973
 
        /* name        */       "RGB",
974
 
        /* width+range */       100, 60, 140,
975
 
        /* class+opts  */       NODE_CLASS_INPUT, NODE_OPTIONS,
976
 
        /* input sock  */       NULL,
977
 
        /* output sock */       sh_node_rgb_out,
978
 
        /* storage     */       "",
979
 
        /* execfunc    */       node_shader_exec_rgb
980
 
        
981
 
};
982
 
 
983
 
/* **************** MIX RGB ******************** */
984
 
static bNodeSocketType sh_node_mix_rgb_in[]= {
985
 
        {       SOCK_VALUE, 1, "Fac",                   0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
986
 
        {       SOCK_RGBA, 1, "Color1",                 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f},
987
 
        {       SOCK_RGBA, 1, "Color2",                 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f},
988
 
        {       -1, 0, ""       }
989
 
};
990
 
static bNodeSocketType sh_node_mix_rgb_out[]= {
991
 
        {       SOCK_RGBA, 0, "Color",                  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
992
 
        {       -1, 0, ""       }
993
 
};
994
 
 
995
 
static void node_shader_exec_mix_rgb(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
996
 
{
997
 
        /* stack order in: fac, col1, col2 */
998
 
        /* stack order out: col */
999
 
        float col[3];
1000
 
        float fac;
1001
 
        float vec[3];
1002
 
 
1003
 
        nodestack_get_vec(&fac, SOCK_VALUE, in[0]);
1004
 
        CLAMP(fac, 0.0f, 1.0f);
1005
 
        
1006
 
        nodestack_get_vec(col, SOCK_VECTOR, in[1]);
1007
 
        nodestack_get_vec(vec, SOCK_VECTOR, in[2]);
1008
 
 
1009
 
        ramp_blend(node->custom1, col, col+1, col+2, fac, vec);
1010
 
        VECCOPY(out[0]->vec, col);
1011
 
}
1012
 
 
1013
 
static bNodeType sh_node_mix_rgb= {
1014
 
        /* type code   */       SH_NODE_MIX_RGB,
1015
 
        /* name        */       "Mix",
1016
 
        /* width+range */       100, 60, 150,
1017
 
        /* class+opts  */       NODE_CLASS_OP_COLOR, NODE_OPTIONS,
1018
 
        /* input sock  */       sh_node_mix_rgb_in,
1019
 
        /* output sock */       sh_node_mix_rgb_out,
1020
 
        /* storage     */       "", 
1021
 
        /* execfunc    */       node_shader_exec_mix_rgb
1022
 
        
1023
 
};
1024
 
 
1025
 
 
1026
 
/* **************** VALTORGB ******************** */
1027
 
static bNodeSocketType sh_node_valtorgb_in[]= {
1028
 
        {       SOCK_VALUE, 1, "Fac",                   0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
1029
 
        {       -1, 0, ""       }
1030
 
};
1031
 
static bNodeSocketType sh_node_valtorgb_out[]= {
1032
 
        {       SOCK_RGBA, 0, "Color",                  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
1033
 
        {       SOCK_VALUE, 0, "Alpha",                 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
1034
 
        {       -1, 0, ""       }
1035
 
};
1036
 
 
1037
 
static void node_shader_exec_valtorgb(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
1038
 
{
1039
 
        /* stack order in: fac */
1040
 
        /* stack order out: col, alpha */
1041
 
        
1042
 
        if(node->storage) {
1043
 
                float fac;
1044
 
                nodestack_get_vec(&fac, SOCK_VALUE, in[0]);
1045
 
 
1046
 
                do_colorband(node->storage, fac, out[0]->vec);
1047
 
                out[1]->vec[0]= out[0]->vec[3];
1048
 
        }
1049
 
}
1050
 
 
1051
 
static bNodeType sh_node_valtorgb= {
1052
 
        /* type code   */       SH_NODE_VALTORGB,
1053
 
        /* name        */       "ColorRamp",
1054
 
        /* width+range */       240, 200, 300,
1055
 
        /* class+opts  */       NODE_CLASS_CONVERTOR, NODE_OPTIONS,
1056
 
        /* input sock  */       sh_node_valtorgb_in,
1057
 
        /* output sock */       sh_node_valtorgb_out,
1058
 
        /* storage     */       "ColorBand",
1059
 
        /* execfunc    */       node_shader_exec_valtorgb
1060
 
        
1061
 
};
1062
 
 
1063
 
 
1064
 
/* **************** RGBTOBW ******************** */
1065
 
static bNodeSocketType sh_node_rgbtobw_in[]= {
1066
 
        {       SOCK_RGBA, 1, "Color",                  0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f},
1067
 
        {       -1, 0, ""       }
1068
 
};
1069
 
static bNodeSocketType sh_node_rgbtobw_out[]= {
1070
 
        {       SOCK_VALUE, 0, "Val",                   0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
1071
 
        {       -1, 0, ""       }
1072
 
};
1073
 
 
1074
 
 
1075
 
static void node_shader_exec_rgbtobw(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
1076
 
{
1077
 
        /* stack order out: bw */
1078
 
        /* stack order in: col */
1079
 
        
1080
 
        out[0]->vec[0]= in[0]->vec[0]*0.35f + in[0]->vec[1]*0.45f + in[0]->vec[2]*0.2f;
1081
 
}
1082
 
 
1083
 
static bNodeType sh_node_rgbtobw= {
1084
 
        /* type code   */       SH_NODE_RGBTOBW,
1085
 
        /* name        */       "RGB to BW",
1086
 
        /* width+range */       80, 40, 120,
1087
 
        /* class+opts  */       NODE_CLASS_CONVERTOR, 0,
1088
 
        /* input sock  */       sh_node_rgbtobw_in,
1089
 
        /* output sock */       sh_node_rgbtobw_out,
1090
 
        /* storage     */       "",
1091
 
        /* execfunc    */       node_shader_exec_rgbtobw
1092
 
        
1093
 
};
1094
 
 
1095
 
/* ****************** types array for all shaders ****************** */
1096
 
 
1097
 
bNodeType *node_all_shaders[]= {
1098
 
        &node_group_typeinfo,
1099
 
        &sh_node_output,
1100
 
        &sh_node_material,
1101
 
        &sh_node_camera,
1102
 
        &sh_node_value,
1103
 
        &sh_node_rgb,
1104
 
        &sh_node_mix_rgb,
1105
 
        &sh_node_valtorgb,
1106
 
        &sh_node_rgbtobw,
1107
 
        &sh_node_texture,
1108
 
        &sh_node_normal,
1109
 
        &sh_node_geom,
1110
 
        &sh_node_mapping,
1111
 
        &sh_node_curve_vec,
1112
 
        &sh_node_curve_rgb,
1113
 
        &sh_node_math,
1114
 
        &sh_node_vect_math,
1115
 
        &sh_node_squeeze,
1116
 
        NULL
1117
 
};
1118
 
 
1119
 
/* ******************* execute and parse ************ */
1120
 
 
1121
 
void ntreeShaderExecTree(bNodeTree *ntree, ShadeInput *shi, ShadeResult *shr)
1122
 
{
1123
 
        ShaderCallData scd;
1124
 
        
1125
 
        /* convert caller data to struct */
1126
 
        scd.shi= shi;
1127
 
        scd.shr= shr;
1128
 
        /* each material node has own local shaderesult, with optional copying */
1129
 
        memset(shr, 0, sizeof(ShadeResult));
1130
 
                   
1131
 
        ntreeExecTree(ntree, &scd, shi->thread);        /* threads */
1132
 
        
1133
 
        /* better not allow negative for now */
1134
 
        if(shr->combined[0]<0.0f) shr->combined[0]= 0.0f;
1135
 
        if(shr->combined[1]<0.0f) shr->combined[1]= 0.0f;
1136
 
        if(shr->combined[2]<0.0f) shr->combined[2]= 0.0f;
1137
 
        
1138
 
}
1139
 
 
1140
 
/* go over all used Geometry and Texture nodes, and return a texco flag */
1141
 
/* no group inside needed, this function is called for groups too */
1142
 
void ntreeShaderGetTexcoMode(bNodeTree *ntree, int r_mode, short *texco, int *mode)
1143
 
{
1144
 
        bNode *node;
1145
 
        bNodeSocket *sock;
1146
 
        int a;
1147
 
        
1148
 
        ntreeSocketUseFlags(ntree);
1149
 
 
1150
 
        for(node= ntree->nodes.first; node; node= node->next) {
1151
 
                if(node->type==SH_NODE_TEXTURE) {
1152
 
                        if((r_mode & R_OSA) && node->id) {
1153
 
                                Tex *tex= (Tex *)node->id;
1154
 
                                if ELEM3(tex->type, TEX_IMAGE, TEX_PLUGIN, TEX_ENVMAP) 
1155
 
                                        *texco |= TEXCO_OSA|NEED_UV;
1156
 
                        }
1157
 
                        /* usability exception... without input we still give the node orcos */
1158
 
                        sock= node->inputs.first;
1159
 
                        if(sock==NULL || sock->link==NULL)
1160
 
                                *texco |= TEXCO_ORCO|NEED_UV;
1161
 
                }
1162
 
                else if(node->type==SH_NODE_GEOMETRY) {
1163
 
                        /* note; sockets always exist for the given type! */
1164
 
                        for(a=0, sock= node->outputs.first; sock; sock= sock->next, a++) {
1165
 
                                if(sock->flag & SOCK_IN_USE) {
1166
 
                                        switch(a) {
1167
 
                                                case GEOM_OUT_GLOB: 
1168
 
                                                        *texco |= TEXCO_GLOB|NEED_UV; break;
1169
 
                                                case GEOM_OUT_VIEW: 
1170
 
                                                        *texco |= TEXCO_VIEW|NEED_UV; break;
1171
 
                                                case GEOM_OUT_ORCO: 
1172
 
                                                        *texco |= TEXCO_ORCO|NEED_UV; break;
1173
 
                                                case GEOM_OUT_UV: 
1174
 
                                                        *texco |= TEXCO_UV|NEED_UV; break;
1175
 
                                                case GEOM_OUT_NORMAL: 
1176
 
                                                        *texco |= TEXCO_NORM|NEED_UV; break;
1177
 
                                                case GEOM_OUT_VCOL:
1178
 
                                                        *texco |= NEED_UV; *mode |= MA_VERTEXCOL; break;
1179
 
                                        }
1180
 
                                }
1181
 
                        }
1182
 
                }
1183
 
        }
1184
 
}
1185
 
 
1186
 
/* nodes that use ID data get synced with local data */
1187
 
void nodeShaderSynchronizeID(bNode *node, int copyto)
1188
 
{
1189
 
        if(node->id==NULL) return;
1190
 
        
1191
 
        if(node->type==SH_NODE_MATERIAL) {
1192
 
                bNodeSocket *sock;
1193
 
                Material *ma= (Material *)node->id;
1194
 
                int a;
1195
 
                
1196
 
                /* hrmf, case in loop isnt super fast, but we dont edit 100s of material at same time either! */
1197
 
                for(a=0, sock= node->inputs.first; sock; sock= sock->next, a++) {
1198
 
                        if(!(sock->flag & SOCK_HIDDEN)) {
1199
 
                                if(copyto) {
1200
 
                                        switch(a) {
1201
 
                                                case MAT_IN_COLOR:
1202
 
                                                        VECCOPY(&ma->r, sock->ns.vec); break;
1203
 
                                                case MAT_IN_SPEC:
1204
 
                                                        VECCOPY(&ma->specr, sock->ns.vec); break;
1205
 
                                                case MAT_IN_REFL:
1206
 
                                                        ma->ref= sock->ns.vec[0]; break;
1207
 
                                        }
1208
 
                                }
1209
 
                                else {
1210
 
                                        switch(a) {
1211
 
                                                case MAT_IN_COLOR:
1212
 
                                                        VECCOPY(sock->ns.vec, &ma->r); break;
1213
 
                                                case MAT_IN_SPEC:
1214
 
                                                        VECCOPY(sock->ns.vec, &ma->specr); break;
1215
 
                                                case MAT_IN_REFL:
1216
 
                                                        sock->ns.vec[0]= ma->ref; break;
1217
 
                                        }
1218
 
                                }
1219
 
                        }
1220
 
                }
1221
 
        }
1222
 
        
1223
 
}