Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * The Original Code is Copyright (C) 2006 Blender Foundation. 00019 * All rights reserved. 00020 * 00021 * The Original Code is: all of this file. 00022 * 00023 * Contributor(s): Campbell Barton, Alfredo de Greef, David Millan Escriva, 00024 * Juho Vepsäläinen 00025 * 00026 * ***** END GPL LICENSE BLOCK ***** 00027 */ 00028 00034 #include "DNA_node_types.h" 00035 00036 #include "BKE_node.h" 00037 00038 #include "node_shader_util.h" 00039 #include "node_common.h" 00040 #include "node_exec.h" 00041 00042 static void copy_stack(bNodeStack *to, bNodeStack *from) 00043 { 00044 if (to != from) { 00045 copy_v4_v4(to->vec, from->vec); 00046 to->data = from->data; 00047 to->datatype = from->datatype; 00048 00049 /* tag as copy to prevent freeing */ 00050 to->is_copy = 1; 00051 } 00052 } 00053 00054 static void move_stack(bNodeStack *to, bNodeStack *from) 00055 { 00056 if (to != from) { 00057 copy_v4_v4(to->vec, from->vec); 00058 to->data = from->data; 00059 to->datatype = from->datatype; 00060 to->is_copy = from->is_copy; 00061 00062 zero_v4(from->vec); 00063 from->data = NULL; 00064 from->datatype = 0; 00065 from->is_copy = 0; 00066 } 00067 } 00068 00069 /**** GROUP ****/ 00070 00071 static void *group_initexec(bNode *node) 00072 { 00073 bNodeTree *ngroup= (bNodeTree*)node->id; 00074 bNodeTreeExec *exec; 00075 00076 /* initialize the internal node tree execution */ 00077 exec = ntreeShaderBeginExecTree(ngroup, 0); 00078 00079 return exec; 00080 } 00081 00082 static void group_freeexec(bNode *UNUSED(node), void *nodedata) 00083 { 00084 bNodeTreeExec*gexec= (bNodeTreeExec*)nodedata; 00085 00086 ntreeShaderEndExecTree(gexec, 0); 00087 } 00088 00089 /* Copy inputs to the internal stack. 00090 */ 00091 static void group_copy_inputs(bNode *node, bNodeStack **in, bNodeStack *gstack) 00092 { 00093 bNodeSocket *sock; 00094 bNodeStack *ns; 00095 int a; 00096 for (sock=node->inputs.first, a=0; sock; sock=sock->next, ++a) { 00097 if (sock->groupsock) { 00098 ns = node_get_socket_stack(gstack, sock->groupsock); 00099 copy_stack(ns, in[a]); 00100 } 00101 } 00102 } 00103 00104 /* Copy internal results to the external outputs. 00105 */ 00106 static void group_move_outputs(bNode *node, bNodeStack **out, bNodeStack *gstack) 00107 { 00108 bNodeSocket *sock; 00109 bNodeStack *ns; 00110 int a; 00111 for (sock=node->outputs.first, a=0; sock; sock=sock->next, ++a) { 00112 if (sock->groupsock) { 00113 ns = node_get_socket_stack(gstack, sock->groupsock); 00114 move_stack(out[a], ns); 00115 } 00116 } 00117 } 00118 00119 static void group_execute(void *data, int thread, struct bNode *node, void *nodedata, struct bNodeStack **in, struct bNodeStack **out) 00120 { 00121 bNodeTreeExec *exec= (bNodeTreeExec*)nodedata; 00122 bNodeThreadStack *nts; 00123 00124 /* XXX same behavior as trunk: all nodes inside group are executed. 00125 * it's stupid, but just makes it work. compo redesign will do this better. 00126 */ 00127 { 00128 bNode *inode; 00129 for (inode=exec->nodetree->nodes.first; inode; inode=inode->next) 00130 inode->need_exec = 1; 00131 } 00132 00133 nts = ntreeGetThreadStack(exec, thread); 00134 00135 group_copy_inputs(node, in, nts->stack); 00136 ntreeExecThreadNodes(exec, nts, data, thread); 00137 group_move_outputs(node, out, nts->stack); 00138 00139 ntreeReleaseThreadStack(nts); 00140 } 00141 00142 static void group_gpu_copy_inputs(bNode *node, GPUNodeStack *in, bNodeStack *gstack) 00143 { 00144 bNodeSocket *sock; 00145 bNodeStack *ns; 00146 int a; 00147 for (sock=node->inputs.first, a=0; sock; sock=sock->next, ++a) { 00148 if (sock->groupsock) { 00149 ns = node_get_socket_stack(gstack, sock->groupsock); 00150 /* convert the external gpu stack back to internal node stack data */ 00151 node_data_from_gpu_stack(ns, &in[a]); 00152 } 00153 } 00154 } 00155 00156 /* Copy internal results to the external outputs. 00157 */ 00158 static void group_gpu_move_outputs(bNode *node, GPUNodeStack *out, bNodeStack *gstack) 00159 { 00160 bNodeSocket *sock; 00161 bNodeStack *ns; 00162 int a; 00163 for (sock=node->outputs.first, a=0; sock; sock=sock->next, ++a) { 00164 if (sock->groupsock) { 00165 ns = node_get_socket_stack(gstack, sock->groupsock); 00166 /* convert the node stack data result back to gpu stack */ 00167 node_gpu_stack_from_data(&out[a], sock->type, ns); 00168 } 00169 } 00170 } 00171 00172 static int gpu_group_execute(GPUMaterial *mat, bNode *node, void *nodedata, GPUNodeStack *in, GPUNodeStack *out) 00173 { 00174 bNodeTreeExec *exec= (bNodeTreeExec*)nodedata; 00175 00176 group_gpu_copy_inputs(node, in, exec->stack); 00177 ntreeExecGPUNodes(exec, mat, (node->flag & NODE_GROUP_EDIT)); 00178 group_gpu_move_outputs(node, out, exec->stack); 00179 00180 return 1; 00181 } 00182 00183 void register_node_type_sh_group(bNodeTreeType *ttype) 00184 { 00185 static bNodeType ntype; 00186 00187 node_type_base(ttype, &ntype, NODE_GROUP, "Group", NODE_CLASS_GROUP, NODE_OPTIONS|NODE_CONST_OUTPUT); 00188 node_type_socket_templates(&ntype, NULL, NULL); 00189 node_type_size(&ntype, 120, 60, 200); 00190 node_type_label(&ntype, node_group_label); 00191 node_type_init(&ntype, node_group_init); 00192 node_type_valid(&ntype, node_group_valid); 00193 node_type_template(&ntype, node_group_template); 00194 node_type_update(&ntype, NULL, node_group_verify); 00195 node_type_group_edit(&ntype, node_group_edit_get, node_group_edit_set, node_group_edit_clear); 00196 node_type_exec_new(&ntype, group_initexec, group_freeexec, group_execute); 00197 node_type_gpu_ext(&ntype, gpu_group_execute); 00198 00199 nodeRegisterType(ttype, &ntype); 00200 } 00201 00202 00203 /**** FOR LOOP ****/ 00204 00205 #if 0 /* XXX loop nodes don't work nicely with current trees */ 00206 static void forloop_execute(void *data, int thread, struct bNode *node, void *nodedata, struct bNodeStack **in, struct bNodeStack **out) 00207 { 00208 bNodeTreeExec *exec= (bNodeTreeExec*)nodedata; 00209 bNodeThreadStack *nts; 00210 int iterations= (int)in[0]->vec[0]; 00211 bNodeSocket *sock; 00212 bNodeStack *ns; 00213 int iteration; 00214 00215 /* XXX same behavior as trunk: all nodes inside group are executed. 00216 * it's stupid, but just makes it work. compo redesign will do this better. 00217 */ 00218 { 00219 bNode *inode; 00220 for (inode=exec->nodetree->nodes.first; inode; inode=inode->next) 00221 inode->need_exec = 1; 00222 } 00223 00224 nts = ntreeGetThreadStack(exec, thread); 00225 00226 /* "Iteration" socket */ 00227 sock = exec->nodetree->inputs.first; 00228 ns = node_get_socket_stack(nts->stack, sock); 00229 00230 // group_copy_inputs(node, in, nts->stack); 00231 for (iteration=0; iteration < iterations; ++iteration) { 00232 /* first input contains current iteration counter */ 00233 ns->vec[0] = (float)iteration; 00234 ns->vec[1]=ns->vec[2]=ns->vec[3] = 0.0f; 00235 00236 // if (iteration > 0) 00237 // loop_init_iteration(exec->nodetree, nts->stack); 00238 // ntreeExecThreadNodes(exec, nts, data, thread); 00239 } 00240 // loop_copy_outputs(node, in, out, exec->stack); 00241 00242 ntreeReleaseThreadStack(nts); 00243 } 00244 00245 void register_node_type_sh_forloop(bNodeTreeType *ttype) 00246 { 00247 static bNodeType ntype; 00248 00249 node_type_base(ttype, &ntype, NODE_FORLOOP, "For", NODE_CLASS_GROUP, NODE_OPTIONS); 00250 node_type_socket_templates(&ntype, NULL, NULL); 00251 node_type_size(&ntype, 120, 60, 200); 00252 node_type_label(&ntype, node_group_label); 00253 node_type_init(&ntype, node_forloop_init); 00254 node_type_valid(&ntype, node_group_valid); 00255 node_type_template(&ntype, node_forloop_template); 00256 node_type_update(&ntype, NULL, node_group_verify); 00257 node_type_tree(&ntype, node_forloop_init_tree, node_loop_update_tree); 00258 node_type_group_edit(&ntype, node_group_edit_get, node_group_edit_set, node_group_edit_clear); 00259 node_type_exec_new(&ntype, group_initexec, group_freeexec, forloop_execute); 00260 00261 nodeRegisterType(ttype, &ntype); 00262 } 00263 #endif 00264 00265 /**** WHILE LOOP ****/ 00266 00267 #if 0 /* XXX loop nodes don't work nicely with current trees */ 00268 static void whileloop_execute(void *data, int thread, struct bNode *node, void *nodedata, struct bNodeStack **in, struct bNodeStack **out) 00269 { 00270 bNodeTreeExec *exec= (bNodeTreeExec*)nodedata; 00271 bNodeThreadStack *nts; 00272 int condition= (in[0]->vec[0] > 0.0f); 00273 bNodeSocket *sock; 00274 bNodeStack *ns; 00275 int iteration; 00276 00277 /* XXX same behavior as trunk: all nodes inside group are executed. 00278 * it's stupid, but just makes it work. compo redesign will do this better. 00279 */ 00280 { 00281 bNode *inode; 00282 for (inode=exec->nodetree->nodes.first; inode; inode=inode->next) 00283 inode->need_exec = 1; 00284 } 00285 00286 nts = ntreeGetThreadStack(exec, thread); 00287 00288 /* "Condition" socket */ 00289 sock = exec->nodetree->outputs.first; 00290 ns = node_get_socket_stack(nts->stack, sock); 00291 00292 iteration = 0; 00293 // group_copy_inputs(node, in, nts->stack); 00294 while (condition && iteration < node->custom1) { 00295 // if (iteration > 0) 00296 // loop_init_iteration(exec->nodetree, nts->stack); 00297 // ntreeExecThreadNodes(exec, nts, data, thread); 00298 00299 condition = (ns->vec[0] > 0.0f); 00300 ++iteration; 00301 } 00302 // loop_copy_outputs(node, in, out, exec->stack); 00303 00304 ntreeReleaseThreadStack(nts); 00305 } 00306 00307 void register_node_type_sh_whileloop(bNodeTreeType *ttype) 00308 { 00309 static bNodeType ntype; 00310 00311 node_type_base(ttype, &ntype, NODE_WHILELOOP, "While", NODE_CLASS_GROUP, NODE_OPTIONS); 00312 node_type_socket_templates(&ntype, NULL, NULL); 00313 node_type_size(&ntype, 120, 60, 200); 00314 node_type_label(&ntype, node_group_label); 00315 node_type_init(&ntype, node_whileloop_init); 00316 node_type_valid(&ntype, node_group_valid); 00317 node_type_template(&ntype, node_whileloop_template); 00318 node_type_update(&ntype, NULL, node_group_verify); 00319 node_type_tree(&ntype, node_whileloop_init_tree, node_loop_update_tree); 00320 node_type_group_edit(&ntype, node_group_edit_get, node_group_edit_set, node_group_edit_clear); 00321 node_type_exec_new(&ntype, group_initexec, group_freeexec, whileloop_execute); 00322 00323 nodeRegisterType(ttype, &ntype); 00324 } 00325 #endif