|
Blender
V2.59
|
00001 00002 /* material.c 00003 * 00004 * 00005 * $Id: material.c 38881 2011-07-31 12:43:41Z campbellbarton $ 00006 * 00007 * ***** BEGIN GPL LICENSE BLOCK ***** 00008 * 00009 * This program is free software; you can redistribute it and/or 00010 * modify it under the terms of the GNU General Public License 00011 * as published by the Free Software Foundation; either version 2 00012 * of the License, or (at your option) any later version. 00013 * 00014 * This program is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 * GNU General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU General Public License 00020 * along with this program; if not, write to the Free Software Foundation, 00021 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00022 * 00023 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00024 * All rights reserved. 00025 * 00026 * The Original Code is: all of this file. 00027 * 00028 * Contributor(s): none yet. 00029 * 00030 * ***** END GPL LICENSE BLOCK ***** 00031 */ 00032 00038 #include <string.h> 00039 #include <math.h> 00040 00041 #include "MEM_guardedalloc.h" 00042 00043 #include "DNA_curve_types.h" 00044 #include "DNA_material_types.h" 00045 #include "DNA_mesh_types.h" 00046 #include "DNA_meta_types.h" 00047 #include "DNA_node_types.h" 00048 #include "DNA_object_types.h" 00049 #include "DNA_scene_types.h" 00050 00051 #include "BLI_math.h" 00052 #include "BLI_listbase.h" 00053 #include "BLI_utildefines.h" 00054 00055 #include "BKE_animsys.h" 00056 #include "BKE_displist.h" 00057 #include "BKE_global.h" 00058 #include "BKE_icons.h" 00059 #include "BKE_library.h" 00060 #include "BKE_main.h" 00061 #include "BKE_material.h" 00062 #include "BKE_mesh.h" 00063 #include "BKE_node.h" 00064 #include "BKE_curve.h" 00065 00066 #include "GPU_material.h" 00067 00068 /* used in UI and render */ 00069 Material defmaterial; 00070 00071 /* called on startup, creator.c */ 00072 void init_def_material(void) 00073 { 00074 init_material(&defmaterial); 00075 } 00076 00077 /* not material itself */ 00078 void free_material(Material *ma) 00079 { 00080 MTex *mtex; 00081 int a; 00082 00083 for(a=0; a<MAX_MTEX; a++) { 00084 mtex= ma->mtex[a]; 00085 if(mtex && mtex->tex) mtex->tex->id.us--; 00086 if(mtex) MEM_freeN(mtex); 00087 } 00088 00089 if(ma->ramp_col) MEM_freeN(ma->ramp_col); 00090 if(ma->ramp_spec) MEM_freeN(ma->ramp_spec); 00091 00092 BKE_free_animdata((ID *)ma); 00093 00094 if(ma->preview) 00095 BKE_previewimg_free(&ma->preview); 00096 BKE_icon_delete((struct ID*)ma); 00097 ma->id.icon_id = 0; 00098 00099 /* is no lib link block, but material extension */ 00100 if(ma->nodetree) { 00101 ntreeFreeTree(ma->nodetree); 00102 MEM_freeN(ma->nodetree); 00103 } 00104 00105 if(ma->gpumaterial.first) 00106 GPU_material_free(ma); 00107 } 00108 00109 void init_material(Material *ma) 00110 { 00111 ma->r= ma->g= ma->b= ma->ref= 0.8; 00112 ma->specr= ma->specg= ma->specb= 1.0; 00113 ma->mirr= ma->mirg= ma->mirb= 1.0; 00114 ma->spectra= 1.0; 00115 ma->amb= 1.0; 00116 ma->alpha= 1.0; 00117 ma->spec= ma->hasize= 0.5; 00118 ma->har= 50; 00119 ma->starc= ma->ringc= 4; 00120 ma->linec= 12; 00121 ma->flarec= 1; 00122 ma->flaresize= ma->subsize= 1.0; 00123 ma->flareboost= 1; 00124 ma->seed2= 6; 00125 ma->friction= 0.5; 00126 ma->refrac= 4.0; 00127 ma->roughness= 0.5; 00128 ma->param[0]= 0.5; 00129 ma->param[1]= 0.1; 00130 ma->param[2]= 0.5; 00131 ma->param[3]= 0.1; 00132 ma->rms= 0.1; 00133 ma->darkness= 1.0; 00134 00135 ma->strand_sta= ma->strand_end= 1.0f; 00136 00137 ma->ang= 1.0; 00138 ma->ray_depth= 2; 00139 ma->ray_depth_tra= 2; 00140 ma->fresnel_mir= 0.0; 00141 ma->fresnel_tra= 0.0; 00142 ma->fresnel_tra_i= 1.25; 00143 ma->fresnel_mir_i= 1.25; 00144 ma->tx_limit= 0.0; 00145 ma->tx_falloff= 1.0; 00146 ma->shad_alpha= 1.0f; 00147 00148 ma->gloss_mir = ma->gloss_tra= 1.0; 00149 ma->samp_gloss_mir = ma->samp_gloss_tra= 18; 00150 ma->adapt_thresh_mir = ma->adapt_thresh_tra = 0.005; 00151 ma->dist_mir = 0.0; 00152 ma->fadeto_mir = MA_RAYMIR_FADETOSKY; 00153 00154 ma->rampfac_col= 1.0; 00155 ma->rampfac_spec= 1.0; 00156 ma->pr_lamp= 3; /* two lamps, is bits */ 00157 ma->pr_type= MA_SPHERE; 00158 00159 ma->sss_radius[0]= 1.0f; 00160 ma->sss_radius[1]= 1.0f; 00161 ma->sss_radius[2]= 1.0f; 00162 ma->sss_col[0]= 1.0f; 00163 ma->sss_col[1]= 1.0f; 00164 ma->sss_col[2]= 1.0f; 00165 ma->sss_error= 0.05f; 00166 ma->sss_scale= 0.1f; 00167 ma->sss_ior= 1.3f; 00168 ma->sss_colfac= 1.0f; 00169 ma->sss_texfac= 0.0f; 00170 ma->sss_front= 1.0f; 00171 ma->sss_back= 1.0f; 00172 00173 ma->vol.density = 1.0f; 00174 ma->vol.emission = 0.0f; 00175 ma->vol.scattering = 1.0f; 00176 ma->vol.reflection = 1.0f; 00177 ma->vol.transmission_col[0] = ma->vol.transmission_col[1] = ma->vol.transmission_col[2] = 1.0f; 00178 ma->vol.reflection_col[0] = ma->vol.reflection_col[1] = ma->vol.reflection_col[2] = 1.0f; 00179 ma->vol.emission_col[0] = ma->vol.emission_col[1] = ma->vol.emission_col[2] = 1.0f; 00180 ma->vol.density_scale = 1.0f; 00181 ma->vol.depth_cutoff = 0.01f; 00182 ma->vol.stepsize_type = MA_VOL_STEP_RANDOMIZED; 00183 ma->vol.stepsize = 0.2f; 00184 ma->vol.shade_type = MA_VOL_SHADE_SHADED; 00185 ma->vol.shadeflag |= MA_VOL_PRECACHESHADING; 00186 ma->vol.precache_resolution = 50; 00187 ma->vol.ms_spread = 0.2f; 00188 ma->vol.ms_diff = 1.f; 00189 ma->vol.ms_intensity = 1.f; 00190 00191 ma->mode= MA_TRACEBLE|MA_SHADBUF|MA_SHADOW|MA_RAYBIAS|MA_TANGENT_STR|MA_ZTRANSP; 00192 ma->shade_flag= MA_APPROX_OCCLUSION; 00193 ma->preview = NULL; 00194 } 00195 00196 Material *add_material(const char *name) 00197 { 00198 Material *ma; 00199 00200 ma= alloc_libblock(&G.main->mat, ID_MA, name); 00201 00202 init_material(ma); 00203 00204 return ma; 00205 } 00206 00207 /* XXX keep synced with next function */ 00208 Material *copy_material(Material *ma) 00209 { 00210 Material *man; 00211 int a; 00212 00213 man= copy_libblock(ma); 00214 00215 id_lib_extern((ID *)man->group); 00216 00217 for(a=0; a<MAX_MTEX; a++) { 00218 if(ma->mtex[a]) { 00219 man->mtex[a]= MEM_mallocN(sizeof(MTex), "copymaterial"); 00220 memcpy(man->mtex[a], ma->mtex[a], sizeof(MTex)); 00221 id_us_plus((ID *)man->mtex[a]->tex); 00222 } 00223 } 00224 00225 if(ma->ramp_col) man->ramp_col= MEM_dupallocN(ma->ramp_col); 00226 if(ma->ramp_spec) man->ramp_spec= MEM_dupallocN(ma->ramp_spec); 00227 00228 if (ma->preview) man->preview = BKE_previewimg_copy(ma->preview); 00229 00230 if(ma->nodetree) { 00231 man->nodetree= ntreeCopyTree(ma->nodetree); /* 0 == full new tree */ 00232 } 00233 00234 man->gpumaterial.first= man->gpumaterial.last= NULL; 00235 00236 return man; 00237 } 00238 00239 /* XXX (see above) material copy without adding to main dbase */ 00240 Material *localize_material(Material *ma) 00241 { 00242 Material *man; 00243 int a; 00244 00245 man= copy_libblock(ma); 00246 BLI_remlink(&G.main->mat, man); 00247 00248 /* no increment for texture ID users, in previewrender.c it prevents decrement */ 00249 for(a=0; a<MAX_MTEX; a++) { 00250 if(ma->mtex[a]) { 00251 man->mtex[a]= MEM_mallocN(sizeof(MTex), "copymaterial"); 00252 memcpy(man->mtex[a], ma->mtex[a], sizeof(MTex)); 00253 } 00254 } 00255 00256 if(ma->ramp_col) man->ramp_col= MEM_dupallocN(ma->ramp_col); 00257 if(ma->ramp_spec) man->ramp_spec= MEM_dupallocN(ma->ramp_spec); 00258 00259 man->preview = NULL; 00260 00261 if(ma->nodetree) 00262 man->nodetree= ntreeLocalize(ma->nodetree); 00263 00264 man->gpumaterial.first= man->gpumaterial.last= NULL; 00265 00266 return man; 00267 } 00268 00269 static void extern_local_material(Material *ma) 00270 { 00271 int i; 00272 for(i=0; i < MAX_MTEX; i++) { 00273 if(ma->mtex[i]) id_lib_extern((ID *)ma->mtex[i]->tex); 00274 } 00275 } 00276 00277 void make_local_material(Material *ma) 00278 { 00279 Main *bmain= G.main; 00280 Object *ob; 00281 Mesh *me; 00282 Curve *cu; 00283 MetaBall *mb; 00284 Material *man; 00285 int a, local=0, lib=0; 00286 00287 /* - only lib users: do nothing 00288 * - only local users: set flag 00289 * - mixed: make copy 00290 */ 00291 00292 if(ma->id.lib==NULL) return; 00293 if(ma->id.us==1) { 00294 ma->id.lib= NULL; 00295 ma->id.flag= LIB_LOCAL; 00296 00297 new_id(&bmain->mat, (ID *)ma, NULL); 00298 extern_local_material(ma); 00299 return; 00300 } 00301 00302 /* test objects */ 00303 ob= bmain->object.first; 00304 while(ob) { 00305 if(ob->mat) { 00306 for(a=0; a<ob->totcol; a++) { 00307 if(ob->mat[a]==ma) { 00308 if(ob->id.lib) lib= 1; 00309 else local= 1; 00310 } 00311 } 00312 } 00313 ob= ob->id.next; 00314 } 00315 /* test meshes */ 00316 me= bmain->mesh.first; 00317 while(me) { 00318 if(me->mat) { 00319 for(a=0; a<me->totcol; a++) { 00320 if(me->mat[a]==ma) { 00321 if(me->id.lib) lib= 1; 00322 else local= 1; 00323 } 00324 } 00325 } 00326 me= me->id.next; 00327 } 00328 /* test curves */ 00329 cu= bmain->curve.first; 00330 while(cu) { 00331 if(cu->mat) { 00332 for(a=0; a<cu->totcol; a++) { 00333 if(cu->mat[a]==ma) { 00334 if(cu->id.lib) lib= 1; 00335 else local= 1; 00336 } 00337 } 00338 } 00339 cu= cu->id.next; 00340 } 00341 /* test mballs */ 00342 mb= bmain->mball.first; 00343 while(mb) { 00344 if(mb->mat) { 00345 for(a=0; a<mb->totcol; a++) { 00346 if(mb->mat[a]==ma) { 00347 if(mb->id.lib) lib= 1; 00348 else local= 1; 00349 } 00350 } 00351 } 00352 mb= mb->id.next; 00353 } 00354 00355 if(local && lib==0) { 00356 ma->id.lib= NULL; 00357 ma->id.flag= LIB_LOCAL; 00358 00359 new_id(&bmain->mat, (ID *)ma, NULL); 00360 extern_local_material(ma); 00361 } 00362 else if(local && lib) { 00363 00364 man= copy_material(ma); 00365 man->id.us= 0; 00366 00367 /* do objects */ 00368 ob= bmain->object.first; 00369 while(ob) { 00370 if(ob->mat) { 00371 for(a=0; a<ob->totcol; a++) { 00372 if(ob->mat[a]==ma) { 00373 if(ob->id.lib==NULL) { 00374 ob->mat[a]= man; 00375 man->id.us++; 00376 ma->id.us--; 00377 } 00378 } 00379 } 00380 } 00381 ob= ob->id.next; 00382 } 00383 /* do meshes */ 00384 me= bmain->mesh.first; 00385 while(me) { 00386 if(me->mat) { 00387 for(a=0; a<me->totcol; a++) { 00388 if(me->mat[a]==ma) { 00389 if(me->id.lib==NULL) { 00390 me->mat[a]= man; 00391 man->id.us++; 00392 ma->id.us--; 00393 } 00394 } 00395 } 00396 } 00397 me= me->id.next; 00398 } 00399 /* do curves */ 00400 cu= bmain->curve.first; 00401 while(cu) { 00402 if(cu->mat) { 00403 for(a=0; a<cu->totcol; a++) { 00404 if(cu->mat[a]==ma) { 00405 if(cu->id.lib==NULL) { 00406 cu->mat[a]= man; 00407 man->id.us++; 00408 ma->id.us--; 00409 } 00410 } 00411 } 00412 } 00413 cu= cu->id.next; 00414 } 00415 /* do mballs */ 00416 mb= bmain->mball.first; 00417 while(mb) { 00418 if(mb->mat) { 00419 for(a=0; a<mb->totcol; a++) { 00420 if(mb->mat[a]==ma) { 00421 if(mb->id.lib==NULL) { 00422 mb->mat[a]= man; 00423 man->id.us++; 00424 ma->id.us--; 00425 } 00426 } 00427 } 00428 } 00429 mb= mb->id.next; 00430 } 00431 } 00432 } 00433 00434 /* for curve, mball, mesh types */ 00435 void extern_local_matarar(struct Material **matar, short totcol) 00436 { 00437 short i; 00438 for(i= 0; i < totcol; i++) { 00439 id_lib_extern((ID *)matar[i]); 00440 } 00441 } 00442 00443 Material ***give_matarar(Object *ob) 00444 { 00445 Mesh *me; 00446 Curve *cu; 00447 MetaBall *mb; 00448 00449 if(ob->type==OB_MESH) { 00450 me= ob->data; 00451 return &(me->mat); 00452 } 00453 else if ELEM3(ob->type, OB_CURVE, OB_FONT, OB_SURF) { 00454 cu= ob->data; 00455 return &(cu->mat); 00456 } 00457 else if(ob->type==OB_MBALL) { 00458 mb= ob->data; 00459 return &(mb->mat); 00460 } 00461 return NULL; 00462 } 00463 00464 short *give_totcolp(Object *ob) 00465 { 00466 Mesh *me; 00467 Curve *cu; 00468 MetaBall *mb; 00469 00470 if(ob->type==OB_MESH) { 00471 me= ob->data; 00472 return &(me->totcol); 00473 } 00474 else if ELEM3(ob->type, OB_CURVE, OB_FONT, OB_SURF) { 00475 cu= ob->data; 00476 return &(cu->totcol); 00477 } 00478 else if(ob->type==OB_MBALL) { 00479 mb= ob->data; 00480 return &(mb->totcol); 00481 } 00482 return NULL; 00483 } 00484 00485 /* same as above but for ID's */ 00486 Material ***give_matarar_id(ID *id) 00487 { 00488 switch(GS(id->name)) { 00489 case ID_ME: 00490 return &(((Mesh *)id)->mat); 00491 break; 00492 case ID_CU: 00493 return &(((Curve *)id)->mat); 00494 break; 00495 case ID_MB: 00496 return &(((MetaBall *)id)->mat); 00497 break; 00498 } 00499 return NULL; 00500 } 00501 00502 short *give_totcolp_id(ID *id) 00503 { 00504 switch(GS(id->name)) { 00505 case ID_ME: 00506 return &(((Mesh *)id)->totcol); 00507 break; 00508 case ID_CU: 00509 return &(((Curve *)id)->totcol); 00510 break; 00511 case ID_MB: 00512 return &(((MetaBall *)id)->totcol); 00513 break; 00514 } 00515 return NULL; 00516 } 00517 00518 void data_delete_material_index_id(ID *id, int index) 00519 { 00520 switch(GS(id->name)) { 00521 case ID_ME: 00522 mesh_delete_material_index((Mesh *)id, index); 00523 break; 00524 case ID_CU: 00525 curve_delete_material_index((Curve *)id, index); 00526 break; 00527 case ID_MB: 00528 /* meta-elems dont have materials atm */ 00529 break; 00530 } 00531 } 00532 00533 void material_append_id(ID *id, Material *ma) 00534 { 00535 Material ***matar; 00536 if((matar= give_matarar_id(id))) { 00537 short *totcol= give_totcolp_id(id); 00538 Material **mat= MEM_callocN(sizeof(void *) * ((*totcol) + 1), "newmatar"); 00539 if(*totcol) memcpy(mat, *matar, sizeof(void *) * (*totcol)); 00540 if(*matar) MEM_freeN(*matar); 00541 00542 *matar= mat; 00543 (*matar)[(*totcol)++]= ma; 00544 00545 id_us_plus((ID *)ma); 00546 test_object_materials(id); 00547 } 00548 } 00549 00550 Material *material_pop_id(ID *id, int index, int remove_material_slot) 00551 { 00552 Material *ret= NULL; 00553 Material ***matar; 00554 if((matar= give_matarar_id(id))) { 00555 short *totcol= give_totcolp_id(id); 00556 if(index >= 0 && index < (*totcol)) { 00557 ret= (*matar)[index]; 00558 id_us_min((ID *)ret); 00559 00560 if (remove_material_slot) { 00561 if(*totcol <= 1) { 00562 *totcol= 0; 00563 MEM_freeN(*matar); 00564 *matar= NULL; 00565 } 00566 else { 00567 Material **mat; 00568 if(index + 1 != (*totcol)) 00569 memmove((*matar)+index, (*matar)+(index+1), sizeof(void *) * ((*totcol) - (index + 1))); 00570 00571 (*totcol)--; 00572 00573 mat= MEM_callocN(sizeof(void *) * (*totcol), "newmatar"); 00574 memcpy(mat, *matar, sizeof(void *) * (*totcol)); 00575 MEM_freeN(*matar); 00576 00577 *matar= mat; 00578 test_object_materials(id); 00579 } 00580 00581 /* decrease mat_nr index */ 00582 data_delete_material_index_id(id, index); 00583 } 00584 00585 /* don't remove material slot, only clear it*/ 00586 else 00587 (*matar)[index]= NULL; 00588 } 00589 } 00590 00591 return ret; 00592 } 00593 00594 Material *give_current_material(Object *ob, int act) 00595 { 00596 Material ***matarar, *ma; 00597 short *totcolp; 00598 00599 if(ob==NULL) return NULL; 00600 00601 /* if object cannot have material, totcolp==NULL */ 00602 totcolp= give_totcolp(ob); 00603 if(totcolp==NULL || ob->totcol==0) return NULL; 00604 00605 if(act<0) { 00606 printf("no!\n"); 00607 } 00608 00609 if(act>ob->totcol) act= ob->totcol; 00610 else if(act<=0) act= 1; 00611 00612 if(ob->matbits && ob->matbits[act-1]) { /* in object */ 00613 ma= ob->mat[act-1]; 00614 } 00615 else { /* in data */ 00616 00617 /* check for inconsistency */ 00618 if(*totcolp < ob->totcol) 00619 ob->totcol= *totcolp; 00620 if(act>ob->totcol) act= ob->totcol; 00621 00622 matarar= give_matarar(ob); 00623 00624 if(matarar && *matarar) ma= (*matarar)[act-1]; 00625 else ma= NULL; 00626 00627 } 00628 00629 return ma; 00630 } 00631 00632 ID *material_from(Object *ob, int act) 00633 { 00634 00635 if(ob==NULL) return NULL; 00636 00637 if(ob->totcol==0) return ob->data; 00638 if(act==0) act= 1; 00639 00640 if(ob->matbits[act-1]) return (ID *)ob; 00641 else return ob->data; 00642 } 00643 00644 Material *give_node_material(Material *ma) 00645 { 00646 if(ma && ma->use_nodes && ma->nodetree) { 00647 bNode *node= nodeGetActiveID(ma->nodetree, ID_MA); 00648 00649 if(node) 00650 return (Material *)node->id; 00651 } 00652 00653 return NULL; 00654 } 00655 00656 /* GS reads the memory pointed at in a specific ordering. There are, 00657 * however two definitions for it. I have jotted them down here, both, 00658 * but I think the first one is actually used. The thing is that 00659 * big-endian systems might read this the wrong way round. OTOH, we 00660 * constructed the IDs that are read out with this macro explicitly as 00661 * well. I expect we'll sort it out soon... */ 00662 00663 /* from blendef: */ 00664 #define GS(a) (*((short *)(a))) 00665 00666 /* from misc_util: flip the bytes from x */ 00667 /* #define GS(x) (((unsigned char *)(x))[0] << 8 | ((unsigned char *)(x))[1]) */ 00668 00669 void resize_object_material(Object *ob, const short totcol) 00670 { 00671 Material **newmatar; 00672 char *newmatbits; 00673 00674 if(totcol==0) { 00675 if(ob->totcol) { 00676 MEM_freeN(ob->mat); 00677 MEM_freeN(ob->matbits); 00678 ob->mat= NULL; 00679 ob->matbits= NULL; 00680 } 00681 } 00682 else if(ob->totcol<totcol) { 00683 newmatar= MEM_callocN(sizeof(void *)*totcol, "newmatar"); 00684 newmatbits= MEM_callocN(sizeof(char)*totcol, "newmatbits"); 00685 if(ob->totcol) { 00686 memcpy(newmatar, ob->mat, sizeof(void *)*ob->totcol); 00687 memcpy(newmatbits, ob->matbits, sizeof(char)*ob->totcol); 00688 MEM_freeN(ob->mat); 00689 MEM_freeN(ob->matbits); 00690 } 00691 ob->mat= newmatar; 00692 ob->matbits= newmatbits; 00693 } 00694 ob->totcol= totcol; 00695 if(ob->totcol && ob->actcol==0) ob->actcol= 1; 00696 if(ob->actcol>ob->totcol) ob->actcol= ob->totcol; 00697 } 00698 00699 void test_object_materials(ID *id) 00700 { 00701 /* make the ob mat-array same size as 'ob->data' mat-array */ 00702 Object *ob; 00703 short *totcol; 00704 00705 if(id==NULL || (totcol=give_totcolp_id(id))==NULL) { 00706 return; 00707 } 00708 00709 for(ob= G.main->object.first; ob; ob= ob->id.next) { 00710 if(ob->data==id) { 00711 resize_object_material(ob, *totcol); 00712 } 00713 } 00714 } 00715 00716 void assign_material(Object *ob, Material *ma, int act) 00717 { 00718 Material *mao, **matar, ***matarar; 00719 char *matbits; 00720 short *totcolp; 00721 00722 if(act>MAXMAT) return; 00723 if(act<1) act= 1; 00724 00725 /* prevent crashing when using accidentally */ 00726 BLI_assert(ob->id.lib == NULL); 00727 if(ob->id.lib) return; 00728 00729 /* test arraylens */ 00730 00731 totcolp= give_totcolp(ob); 00732 matarar= give_matarar(ob); 00733 00734 if(totcolp==NULL || matarar==NULL) return; 00735 00736 if(act > *totcolp) { 00737 matar= MEM_callocN(sizeof(void *)*act, "matarray1"); 00738 00739 if(*totcolp) { 00740 memcpy(matar, *matarar, sizeof(void *)*(*totcolp)); 00741 MEM_freeN(*matarar); 00742 } 00743 00744 *matarar= matar; 00745 *totcolp= act; 00746 } 00747 00748 if(act > ob->totcol) { 00749 matar= MEM_callocN(sizeof(void *)*act, "matarray2"); 00750 matbits= MEM_callocN(sizeof(char)*act, "matbits1"); 00751 if( ob->totcol) { 00752 memcpy(matar, ob->mat, sizeof(void *)*( ob->totcol )); 00753 memcpy(matbits, ob->matbits, sizeof(char)*(*totcolp)); 00754 MEM_freeN(ob->mat); 00755 MEM_freeN(ob->matbits); 00756 } 00757 ob->mat= matar; 00758 ob->matbits= matbits; 00759 ob->totcol= act; 00760 00761 /* copy object/mesh linking, or assign based on userpref */ 00762 if(ob->actcol) 00763 ob->matbits[act-1]= ob->matbits[ob->actcol-1]; 00764 else 00765 ob->matbits[act-1]= (U.flag & USER_MAT_ON_OB)? 1: 0; 00766 } 00767 00768 /* do it */ 00769 00770 if(ob->matbits[act-1]) { /* in object */ 00771 mao= ob->mat[act-1]; 00772 if(mao) mao->id.us--; 00773 ob->mat[act-1]= ma; 00774 } 00775 else { /* in data */ 00776 mao= (*matarar)[act-1]; 00777 if(mao) mao->id.us--; 00778 (*matarar)[act-1]= ma; 00779 } 00780 00781 if(ma) 00782 id_us_plus((ID *)ma); 00783 test_object_materials(ob->data); 00784 } 00785 00786 /* XXX - this calls many more update calls per object then are needed, could be optimized */ 00787 void assign_matarar(struct Object *ob, struct Material ***matar, int totcol) 00788 { 00789 int i, actcol_orig= ob->actcol; 00790 00791 while(object_remove_material_slot(ob)) {}; 00792 00793 /* now we have the right number of slots */ 00794 for(i=0; i<totcol; i++) 00795 assign_material(ob, (*matar)[i], i+1); 00796 00797 if(actcol_orig > ob->totcol) 00798 actcol_orig= ob->totcol; 00799 00800 ob->actcol= actcol_orig; 00801 } 00802 00803 00804 int find_material_index(Object *ob, Material *ma) 00805 { 00806 Material ***matarar; 00807 short a, *totcolp; 00808 00809 if(ma==NULL) return 0; 00810 00811 totcolp= give_totcolp(ob); 00812 matarar= give_matarar(ob); 00813 00814 if(totcolp==NULL || matarar==NULL) return 0; 00815 00816 for(a=0; a<*totcolp; a++) 00817 if((*matarar)[a]==ma) 00818 break; 00819 if(a<*totcolp) 00820 return a+1; 00821 return 0; 00822 } 00823 00824 int object_add_material_slot(Object *ob) 00825 { 00826 if(ob==NULL) return FALSE; 00827 if(ob->totcol>=MAXMAT) return FALSE; 00828 00829 assign_material(ob, NULL, ob->totcol+1); 00830 ob->actcol= ob->totcol; 00831 return TRUE; 00832 } 00833 00834 static void do_init_render_material(Material *ma, int r_mode, float *amb) 00835 { 00836 MTex *mtex; 00837 int a, needuv=0, needtang=0; 00838 00839 if(ma->flarec==0) ma->flarec= 1; 00840 00841 /* add all texcoflags from mtex, texco and mapto were cleared in advance */ 00842 for(a=0; a<MAX_MTEX; a++) { 00843 00844 /* separate tex switching */ 00845 if(ma->septex & (1<<a)) continue; 00846 00847 mtex= ma->mtex[a]; 00848 if(mtex && mtex->tex && (mtex->tex->type | (mtex->tex->use_nodes && mtex->tex->nodetree) )) { 00849 00850 ma->texco |= mtex->texco; 00851 ma->mapto |= mtex->mapto; 00852 00853 /* always get derivatives for these textures */ 00854 if ELEM3(mtex->tex->type, TEX_IMAGE, TEX_PLUGIN, TEX_ENVMAP) ma->texco |= TEXCO_OSA; 00855 else if(mtex->texflag & (MTEX_COMPAT_BUMP|MTEX_3TAP_BUMP|MTEX_5TAP_BUMP)) ma->texco |= TEXCO_OSA; 00856 00857 if(ma->texco & (TEXCO_ORCO|TEXCO_REFL|TEXCO_NORM|TEXCO_STRAND|TEXCO_STRESS)) needuv= 1; 00858 else if(ma->texco & (TEXCO_GLOB|TEXCO_UV|TEXCO_OBJECT|TEXCO_SPEED)) needuv= 1; 00859 else if(ma->texco & (TEXCO_LAVECTOR|TEXCO_VIEW|TEXCO_STICKY)) needuv= 1; 00860 00861 if((ma->mapto & MAP_NORM) && (mtex->normapspace == MTEX_NSPACE_TANGENT)) 00862 needtang= 1; 00863 } 00864 } 00865 00866 if(needtang) ma->mode |= MA_NORMAP_TANG; 00867 else ma->mode &= ~MA_NORMAP_TANG; 00868 00869 if(ma->mode & (MA_VERTEXCOL|MA_VERTEXCOLP|MA_FACETEXTURE)) { 00870 needuv= 1; 00871 if(r_mode & R_OSA) ma->texco |= TEXCO_OSA; /* for texfaces */ 00872 } 00873 if(needuv) ma->texco |= NEED_UV; 00874 00875 /* since the raytracer doesnt recalc O structs for each ray, we have to preset them all */ 00876 if(r_mode & R_RAYTRACE) { 00877 if((ma->mode & (MA_RAYMIRROR|MA_SHADOW_TRA)) || ((ma->mode & MA_TRANSP) && (ma->mode & MA_RAYTRANSP))) { 00878 ma->texco |= NEED_UV|TEXCO_ORCO|TEXCO_REFL|TEXCO_NORM; 00879 if(r_mode & R_OSA) ma->texco |= TEXCO_OSA; 00880 } 00881 } 00882 00883 if(amb) { 00884 ma->ambr= ma->amb*amb[0]; 00885 ma->ambg= ma->amb*amb[1]; 00886 ma->ambb= ma->amb*amb[2]; 00887 } 00888 /* will become or-ed result of all node modes */ 00889 ma->mode_l= ma->mode; 00890 ma->mode_l &= ~MA_SHLESS; 00891 00892 if(ma->strand_surfnor > 0.0f) 00893 ma->mode_l |= MA_STR_SURFDIFF; 00894 00895 /* parses the geom+tex nodes */ 00896 if(ma->nodetree && ma->use_nodes) 00897 ntreeShaderGetTexcoMode(ma->nodetree, r_mode, &ma->texco, &ma->mode_l); 00898 } 00899 00900 static void init_render_nodetree(bNodeTree *ntree, Material *basemat, int r_mode, float *amb) 00901 { 00902 bNode *node; 00903 00904 for(node=ntree->nodes.first; node; node= node->next) { 00905 if(node->id) { 00906 if(GS(node->id->name)==ID_MA) { 00907 Material *ma= (Material *)node->id; 00908 if(ma!=basemat) { 00909 do_init_render_material(ma, r_mode, amb); 00910 basemat->texco |= ma->texco; 00911 basemat->mode_l |= ma->mode_l & ~(MA_TRANSP|MA_ZTRANSP|MA_RAYTRANSP); 00912 } 00913 } 00914 else if(node->type==NODE_GROUP) 00915 init_render_nodetree((bNodeTree *)node->id, basemat, r_mode, amb); 00916 } 00917 } 00918 } 00919 00920 void init_render_material(Material *mat, int r_mode, float *amb) 00921 { 00922 00923 do_init_render_material(mat, r_mode, amb); 00924 00925 if(mat->nodetree && mat->use_nodes) { 00926 init_render_nodetree(mat->nodetree, mat, r_mode, amb); 00927 00928 ntreeBeginExecTree(mat->nodetree); /* has internal flag to detect it only does it once */ 00929 } 00930 } 00931 00932 void init_render_materials(Main *bmain, int r_mode, float *amb) 00933 { 00934 Material *ma; 00935 00936 /* clear these flags before going over materials, to make sure they 00937 * are cleared only once, otherwise node materials contained in other 00938 * node materials can go wrong */ 00939 for(ma= bmain->mat.first; ma; ma= ma->id.next) { 00940 if(ma->id.us) { 00941 ma->texco= 0; 00942 ma->mapto= 0; 00943 } 00944 } 00945 00946 /* two steps, first initialize, then or the flags for layers */ 00947 for(ma= bmain->mat.first; ma; ma= ma->id.next) { 00948 /* is_used flag comes back in convertblender.c */ 00949 ma->flag &= ~MA_IS_USED; 00950 if(ma->id.us) 00951 init_render_material(ma, r_mode, amb); 00952 } 00953 00954 do_init_render_material(&defmaterial, r_mode, amb); 00955 } 00956 00957 /* only needed for nodes now */ 00958 void end_render_material(Material *mat) 00959 { 00960 if(mat && mat->nodetree && mat->use_nodes) 00961 ntreeEndExecTree(mat->nodetree); /* has internal flag to detect it only does it once */ 00962 } 00963 00964 void end_render_materials(Main *bmain) 00965 { 00966 Material *ma; 00967 for(ma= bmain->mat.first; ma; ma= ma->id.next) 00968 if(ma->id.us) 00969 end_render_material(ma); 00970 } 00971 00972 static int material_in_nodetree(bNodeTree *ntree, Material *mat) 00973 { 00974 bNode *node; 00975 00976 for(node=ntree->nodes.first; node; node= node->next) { 00977 if(node->id && GS(node->id->name)==ID_MA) { 00978 if(node->id==(ID*)mat) 00979 return 1; 00980 } 00981 else if(node->type==NODE_GROUP) 00982 if(material_in_nodetree((bNodeTree*)node->id, mat)) 00983 return 1; 00984 } 00985 00986 return 0; 00987 } 00988 00989 int material_in_material(Material *parmat, Material *mat) 00990 { 00991 if(parmat==mat) 00992 return 1; 00993 else if(parmat->nodetree && parmat->use_nodes) 00994 return material_in_nodetree(parmat->nodetree, mat); 00995 else 00996 return 0; 00997 } 00998 00999 /* ****************** */ 01000 01001 static char colname_array[125][20]= { 01002 "Black","DarkRed","HalfRed","Red","Red", 01003 "DarkGreen","DarkOlive","Brown","Chocolate","OrangeRed", 01004 "HalfGreen","GreenOlive","DryOlive","Goldenrod","DarkOrange", 01005 "LightGreen","Chartreuse","YellowGreen","Yellow","Gold", 01006 "Green","LawnGreen","GreenYellow","LightOlive","Yellow", 01007 "DarkBlue","DarkPurple","HotPink","VioletPink","RedPink", 01008 "SlateGray","DarkGrey","PalePurple","IndianRed","Tomato", 01009 "SeaGreen","PaleGreen","GreenKhaki","LightBrown","LightSalmon", 01010 "SpringGreen","PaleGreen","MediumOlive","YellowBrown","LightGold", 01011 "LightGreen","LightGreen","LightGreen","GreenYellow","PaleYellow", 01012 "HalfBlue","DarkSky","HalfMagenta","VioletRed","DeepPink", 01013 "SteelBlue","SkyBlue","Orchid","LightHotPink","HotPink", 01014 "SeaGreen","SlateGray","MediumGrey","Burlywood","LightPink", 01015 "SpringGreen","Aquamarine","PaleGreen","Khaki","PaleOrange", 01016 "SpringGreen","SeaGreen","PaleGreen","PaleWhite","YellowWhite", 01017 "LightBlue","Purple","MediumOrchid","Magenta","Magenta", 01018 "RoyalBlue","SlateBlue","MediumOrchid","Orchid","Magenta", 01019 "DeepSkyBlue","LightSteelBlue","LightSkyBlue","Violet","LightPink", 01020 "Cyan","DarkTurquoise","SkyBlue","Grey","Snow", 01021 "Mint","Mint","Aquamarine","MintCream","Ivory", 01022 "Blue","Blue","DarkMagenta","DarkOrchid","Magenta", 01023 "SkyBlue","RoyalBlue","LightSlateBlue","MediumOrchid","Magenta", 01024 "DodgerBlue","SteelBlue","MediumPurple","PalePurple","Plum", 01025 "DeepSkyBlue","PaleBlue","LightSkyBlue","PalePurple","Thistle", 01026 "Cyan","ColdBlue","PaleTurquoise","GhostWhite","White" 01027 }; 01028 01029 void automatname(Material *ma) 01030 { 01031 int nr, r, g, b; 01032 float ref; 01033 01034 if(ma==NULL) return; 01035 if(ma->mode & MA_SHLESS) ref= 1.0; 01036 else ref= ma->ref; 01037 01038 r= (int)(4.99f*(ref*ma->r)); 01039 g= (int)(4.99f*(ref*ma->g)); 01040 b= (int)(4.99f*(ref*ma->b)); 01041 nr= r + 5*g + 25*b; 01042 if(nr>124) nr= 124; 01043 new_id(&G.main->mat, (ID *)ma, colname_array[nr]); 01044 01045 } 01046 01047 01048 int object_remove_material_slot(Object *ob) 01049 { 01050 Material *mao, ***matarar; 01051 Object *obt; 01052 short *totcolp; 01053 int a, actcol; 01054 01055 if(ob==NULL || ob->totcol==0) return FALSE; 01056 01057 /* take a mesh/curve/mball as starting point, remove 1 index, 01058 * AND with all objects that share the ob->data 01059 * 01060 * after that check indices in mesh/curve/mball!!! 01061 */ 01062 01063 totcolp= give_totcolp(ob); 01064 matarar= give_matarar(ob); 01065 01066 if(*matarar==NULL) return FALSE; 01067 01068 /* we delete the actcol */ 01069 if(ob->totcol) { 01070 mao= (*matarar)[ob->actcol-1]; 01071 if(mao) mao->id.us--; 01072 } 01073 01074 for(a=ob->actcol; a<ob->totcol; a++) 01075 (*matarar)[a-1]= (*matarar)[a]; 01076 (*totcolp)--; 01077 01078 if(*totcolp==0) { 01079 MEM_freeN(*matarar); 01080 *matarar= NULL; 01081 } 01082 01083 actcol= ob->actcol; 01084 obt= G.main->object.first; 01085 while(obt) { 01086 01087 if(obt->data==ob->data) { 01088 01089 /* WATCH IT: do not use actcol from ob or from obt (can become zero) */ 01090 mao= obt->mat[actcol-1]; 01091 if(mao) mao->id.us--; 01092 01093 for(a=actcol; a<obt->totcol; a++) { 01094 obt->mat[a-1]= obt->mat[a]; 01095 obt->matbits[a-1]= obt->matbits[a]; 01096 } 01097 obt->totcol--; 01098 if(obt->actcol > obt->totcol) obt->actcol= obt->totcol; 01099 01100 if(obt->totcol==0) { 01101 MEM_freeN(obt->mat); 01102 MEM_freeN(obt->matbits); 01103 obt->mat= NULL; 01104 obt->matbits= NULL; 01105 } 01106 } 01107 obt= obt->id.next; 01108 } 01109 01110 /* check indices from mesh */ 01111 if (ELEM4(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT)) { 01112 data_delete_material_index_id((ID *)ob->data, actcol-1); 01113 freedisplist(&ob->disp); 01114 } 01115 01116 return TRUE; 01117 } 01118 01119 01120 /* r g b = current value, col = new value, fac==0 is no change */ 01121 /* if g==NULL, it only does r channel */ 01122 void ramp_blend(int type, float *r, float *g, float *b, float fac, float *col) 01123 { 01124 float tmp, facm= 1.0f-fac; 01125 01126 switch (type) { 01127 case MA_RAMP_BLEND: 01128 *r = facm*(*r) + fac*col[0]; 01129 if(g) { 01130 *g = facm*(*g) + fac*col[1]; 01131 *b = facm*(*b) + fac*col[2]; 01132 } 01133 break; 01134 case MA_RAMP_ADD: 01135 *r += fac*col[0]; 01136 if(g) { 01137 *g += fac*col[1]; 01138 *b += fac*col[2]; 01139 } 01140 break; 01141 case MA_RAMP_MULT: 01142 *r *= (facm + fac*col[0]); 01143 if(g) { 01144 *g *= (facm + fac*col[1]); 01145 *b *= (facm + fac*col[2]); 01146 } 01147 break; 01148 case MA_RAMP_SCREEN: 01149 *r = 1.0f - (facm + fac*(1.0f - col[0])) * (1.0f - *r); 01150 if(g) { 01151 *g = 1.0f - (facm + fac*(1.0f - col[1])) * (1.0f - *g); 01152 *b = 1.0f - (facm + fac*(1.0f - col[2])) * (1.0f - *b); 01153 } 01154 break; 01155 case MA_RAMP_OVERLAY: 01156 if(*r < 0.5f) 01157 *r *= (facm + 2.0f*fac*col[0]); 01158 else 01159 *r = 1.0f - (facm + 2.0f*fac*(1.0f - col[0])) * (1.0f - *r); 01160 if(g) { 01161 if(*g < 0.5f) 01162 *g *= (facm + 2.0f*fac*col[1]); 01163 else 01164 *g = 1.0f - (facm + 2.0f*fac*(1.0f - col[1])) * (1.0f - *g); 01165 if(*b < 0.5f) 01166 *b *= (facm + 2.0f*fac*col[2]); 01167 else 01168 *b = 1.0f - (facm + 2.0f*fac*(1.0f - col[2])) * (1.0f - *b); 01169 } 01170 break; 01171 case MA_RAMP_SUB: 01172 *r -= fac*col[0]; 01173 if(g) { 01174 *g -= fac*col[1]; 01175 *b -= fac*col[2]; 01176 } 01177 break; 01178 case MA_RAMP_DIV: 01179 if(col[0]!=0.0f) 01180 *r = facm*(*r) + fac*(*r)/col[0]; 01181 if(g) { 01182 if(col[1]!=0.0f) 01183 *g = facm*(*g) + fac*(*g)/col[1]; 01184 if(col[2]!=0.0f) 01185 *b = facm*(*b) + fac*(*b)/col[2]; 01186 } 01187 break; 01188 case MA_RAMP_DIFF: 01189 *r = facm*(*r) + fac*fabsf(*r-col[0]); 01190 if(g) { 01191 *g = facm*(*g) + fac*fabsf(*g-col[1]); 01192 *b = facm*(*b) + fac*fabsf(*b-col[2]); 01193 } 01194 break; 01195 case MA_RAMP_DARK: 01196 tmp=col[0]+((1-col[0])*facm); 01197 if(tmp < *r) *r= tmp; 01198 if(g) { 01199 tmp=col[1]+((1-col[1])*facm); 01200 if(tmp < *g) *g= tmp; 01201 tmp=col[2]+((1-col[2])*facm); 01202 if(tmp < *b) *b= tmp; 01203 } 01204 break; 01205 case MA_RAMP_LIGHT: 01206 tmp= fac*col[0]; 01207 if(tmp > *r) *r= tmp; 01208 if(g) { 01209 tmp= fac*col[1]; 01210 if(tmp > *g) *g= tmp; 01211 tmp= fac*col[2]; 01212 if(tmp > *b) *b= tmp; 01213 } 01214 break; 01215 case MA_RAMP_DODGE: 01216 01217 01218 if(*r !=0.0f){ 01219 tmp = 1.0f - fac*col[0]; 01220 if(tmp <= 0.0f) 01221 *r = 1.0f; 01222 else if ((tmp = (*r) / tmp)> 1.0f) 01223 *r = 1.0f; 01224 else 01225 *r = tmp; 01226 } 01227 if(g) { 01228 if(*g !=0.0f){ 01229 tmp = 1.0f - fac*col[1]; 01230 if(tmp <= 0.0f ) 01231 *g = 1.0f; 01232 else if ((tmp = (*g) / tmp) > 1.0f ) 01233 *g = 1.0f; 01234 else 01235 *g = tmp; 01236 } 01237 if(*b !=0.0f){ 01238 tmp = 1.0f - fac*col[2]; 01239 if(tmp <= 0.0f) 01240 *b = 1.0f; 01241 else if ((tmp = (*b) / tmp) > 1.0f ) 01242 *b = 1.0f; 01243 else 01244 *b = tmp; 01245 } 01246 01247 } 01248 break; 01249 case MA_RAMP_BURN: 01250 01251 tmp = facm + fac*col[0]; 01252 01253 if(tmp <= 0.0f) 01254 *r = 0.0f; 01255 else if (( tmp = (1.0f - (1.0f - (*r)) / tmp )) < 0.0f) 01256 *r = 0.0f; 01257 else if (tmp > 1.0f) 01258 *r=1.0f; 01259 else 01260 *r = tmp; 01261 01262 if(g) { 01263 tmp = facm + fac*col[1]; 01264 if(tmp <= 0.0f) 01265 *g = 0.0f; 01266 else if (( tmp = (1.0f - (1.0f - (*g)) / tmp )) < 0.0f ) 01267 *g = 0.0f; 01268 else if(tmp >1.0f) 01269 *g=1.0f; 01270 else 01271 *g = tmp; 01272 01273 tmp = facm + fac*col[2]; 01274 if(tmp <= 0.0f) 01275 *b = 0.0f; 01276 else if (( tmp = (1.0f - (1.0f - (*b)) / tmp )) < 0.0f ) 01277 *b = 0.0f; 01278 else if(tmp >1.0f) 01279 *b= 1.0f; 01280 else 01281 *b = tmp; 01282 } 01283 break; 01284 case MA_RAMP_HUE: 01285 if(g){ 01286 float rH,rS,rV; 01287 float colH,colS,colV; 01288 float tmpr,tmpg,tmpb; 01289 rgb_to_hsv(col[0],col[1],col[2],&colH,&colS,&colV); 01290 if(colS!=0 ){ 01291 rgb_to_hsv(*r,*g,*b,&rH,&rS,&rV); 01292 hsv_to_rgb( colH , rS, rV, &tmpr, &tmpg, &tmpb); 01293 *r = facm*(*r) + fac*tmpr; 01294 *g = facm*(*g) + fac*tmpg; 01295 *b = facm*(*b) + fac*tmpb; 01296 } 01297 } 01298 break; 01299 case MA_RAMP_SAT: 01300 if(g){ 01301 float rH,rS,rV; 01302 float colH,colS,colV; 01303 rgb_to_hsv(*r,*g,*b,&rH,&rS,&rV); 01304 if(rS!=0){ 01305 rgb_to_hsv(col[0],col[1],col[2],&colH,&colS,&colV); 01306 hsv_to_rgb( rH, (facm*rS +fac*colS), rV, r, g, b); 01307 } 01308 } 01309 break; 01310 case MA_RAMP_VAL: 01311 if(g){ 01312 float rH,rS,rV; 01313 float colH,colS,colV; 01314 rgb_to_hsv(*r,*g,*b,&rH,&rS,&rV); 01315 rgb_to_hsv(col[0],col[1],col[2],&colH,&colS,&colV); 01316 hsv_to_rgb( rH, rS, (facm*rV +fac*colV), r, g, b); 01317 } 01318 break; 01319 case MA_RAMP_COLOR: 01320 if(g){ 01321 float rH,rS,rV; 01322 float colH,colS,colV; 01323 float tmpr,tmpg,tmpb; 01324 rgb_to_hsv(col[0],col[1],col[2],&colH,&colS,&colV); 01325 if(colS!=0){ 01326 rgb_to_hsv(*r,*g,*b,&rH,&rS,&rV); 01327 hsv_to_rgb( colH, colS, rV, &tmpr, &tmpg, &tmpb); 01328 *r = facm*(*r) + fac*tmpr; 01329 *g = facm*(*g) + fac*tmpg; 01330 *b = facm*(*b) + fac*tmpb; 01331 } 01332 } 01333 break; 01334 case MA_RAMP_SOFT: 01335 if (g){ 01336 float scr, scg, scb; 01337 01338 /* first calculate non-fac based Screen mix */ 01339 scr = 1.0f - (1.0f - col[0]) * (1.0f - *r); 01340 scg = 1.0f - (1.0f - col[1]) * (1.0f - *g); 01341 scb = 1.0f - (1.0f - col[2]) * (1.0f - *b); 01342 01343 *r = facm*(*r) + fac*(((1.0f - *r) * col[0] * (*r)) + (*r * scr)); 01344 *g = facm*(*g) + fac*(((1.0f - *g) * col[1] * (*g)) + (*g * scg)); 01345 *b = facm*(*b) + fac*(((1.0f - *b) * col[2] * (*b)) + (*b * scb)); 01346 } 01347 break; 01348 case MA_RAMP_LINEAR: 01349 if (col[0] > 0.5f) 01350 *r = *r + fac*(2.0f*(col[0]-0.5f)); 01351 else 01352 *r = *r + fac*(2.0f*(col[0]) - 1.0f); 01353 if (g){ 01354 if (col[1] > 0.5f) 01355 *g = *g + fac*(2.0f*(col[1]-0.5f)); 01356 else 01357 *g = *g + fac*(2.0f*(col[1]) -1.0f); 01358 if (col[2] > 0.5f) 01359 *b = *b + fac*(2.0f*(col[2]-0.5f)); 01360 else 01361 *b = *b + fac*(2.0f*(col[2]) - 1.0f); 01362 } 01363 break; 01364 } 01365 } 01366 01367 /* copy/paste buffer, if we had a propper py api that would be better */ 01368 Material matcopybuf; 01369 static short matcopied= 0; 01370 01371 void clear_matcopybuf(void) 01372 { 01373 memset(&matcopybuf, 0, sizeof(Material)); 01374 matcopied= 0; 01375 } 01376 01377 void free_matcopybuf(void) 01378 { 01379 int a; 01380 01381 for(a=0; a<MAX_MTEX; a++) { 01382 if(matcopybuf.mtex[a]) { 01383 MEM_freeN(matcopybuf.mtex[a]); 01384 matcopybuf.mtex[a]= NULL; 01385 } 01386 } 01387 01388 if(matcopybuf.ramp_col) MEM_freeN(matcopybuf.ramp_col); 01389 if(matcopybuf.ramp_spec) MEM_freeN(matcopybuf.ramp_spec); 01390 01391 matcopybuf.ramp_col= NULL; 01392 matcopybuf.ramp_spec= NULL; 01393 01394 if(matcopybuf.nodetree) { 01395 ntreeFreeTree(matcopybuf.nodetree); 01396 MEM_freeN(matcopybuf.nodetree); 01397 matcopybuf.nodetree= NULL; 01398 } 01399 01400 matcopied= 0; 01401 } 01402 01403 void copy_matcopybuf(Material *ma) 01404 { 01405 int a; 01406 MTex *mtex; 01407 01408 if(matcopied) 01409 free_matcopybuf(); 01410 01411 memcpy(&matcopybuf, ma, sizeof(Material)); 01412 if(matcopybuf.ramp_col) matcopybuf.ramp_col= MEM_dupallocN(matcopybuf.ramp_col); 01413 if(matcopybuf.ramp_spec) matcopybuf.ramp_spec= MEM_dupallocN(matcopybuf.ramp_spec); 01414 01415 for(a=0; a<MAX_MTEX; a++) { 01416 mtex= matcopybuf.mtex[a]; 01417 if(mtex) { 01418 matcopybuf.mtex[a]= MEM_dupallocN(mtex); 01419 } 01420 } 01421 matcopybuf.nodetree= ntreeCopyTree(ma->nodetree); 01422 matcopybuf.preview= NULL; 01423 matcopybuf.gpumaterial.first= matcopybuf.gpumaterial.last= NULL; 01424 matcopied= 1; 01425 } 01426 01427 void paste_matcopybuf(Material *ma) 01428 { 01429 int a; 01430 MTex *mtex; 01431 ID id; 01432 01433 if(matcopied==0) 01434 return; 01435 /* free current mat */ 01436 if(ma->ramp_col) MEM_freeN(ma->ramp_col); 01437 if(ma->ramp_spec) MEM_freeN(ma->ramp_spec); 01438 for(a=0; a<MAX_MTEX; a++) { 01439 mtex= ma->mtex[a]; 01440 if(mtex && mtex->tex) mtex->tex->id.us--; 01441 if(mtex) MEM_freeN(mtex); 01442 } 01443 01444 if(ma->nodetree) { 01445 ntreeFreeTree(ma->nodetree); 01446 MEM_freeN(ma->nodetree); 01447 } 01448 01449 GPU_material_free(ma); 01450 01451 id= (ma->id); 01452 memcpy(ma, &matcopybuf, sizeof(Material)); 01453 (ma->id)= id; 01454 01455 if(matcopybuf.ramp_col) ma->ramp_col= MEM_dupallocN(matcopybuf.ramp_col); 01456 if(matcopybuf.ramp_spec) ma->ramp_spec= MEM_dupallocN(matcopybuf.ramp_spec); 01457 01458 for(a=0; a<MAX_MTEX; a++) { 01459 mtex= ma->mtex[a]; 01460 if(mtex) { 01461 ma->mtex[a]= MEM_dupallocN(mtex); 01462 if(mtex->tex) id_us_plus((ID *)mtex->tex); 01463 } 01464 } 01465 01466 ma->nodetree= ntreeCopyTree(matcopybuf.nodetree); 01467 }