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) 2001-2002 by NaN Holding BV. 00019 * All rights reserved. 00020 * 00021 * The Original Code is: all of this file. 00022 * 00023 * Contributor(s): none yet. 00024 * 00025 * ***** END GPL LICENSE BLOCK ***** 00026 */ 00027 00033 #include <string.h> 00034 #include <math.h> 00035 #include <stddef.h> 00036 00037 #include "MEM_guardedalloc.h" 00038 00039 #include "DNA_curve_types.h" 00040 #include "DNA_material_types.h" 00041 #include "DNA_mesh_types.h" 00042 #include "DNA_meshdata_types.h" 00043 #include "DNA_customdata_types.h" 00044 #include "DNA_ID.h" 00045 #include "DNA_meta_types.h" 00046 #include "DNA_node_types.h" 00047 #include "DNA_object_types.h" 00048 #include "DNA_scene_types.h" 00049 00050 #include "BLI_math.h" 00051 #include "BLI_listbase.h" 00052 #include "BLI_utildefines.h" 00053 #include "BLI_bpath.h" 00054 #include "BLI_string.h" 00055 00056 #include "BKE_animsys.h" 00057 #include "BKE_displist.h" 00058 #include "BKE_global.h" 00059 #include "BKE_icons.h" 00060 #include "BKE_image.h" 00061 #include "BKE_library.h" 00062 #include "BKE_main.h" 00063 #include "BKE_material.h" 00064 #include "BKE_mesh.h" 00065 #include "BKE_node.h" 00066 #include "BKE_curve.h" 00067 00068 #include "GPU_material.h" 00069 00070 /* used in UI and render */ 00071 Material defmaterial; 00072 00073 /* called on startup, creator.c */ 00074 void init_def_material(void) 00075 { 00076 init_material(&defmaterial); 00077 } 00078 00079 /* not material itself */ 00080 void free_material(Material *ma) 00081 { 00082 MTex *mtex; 00083 int a; 00084 00085 for(a=0; a<MAX_MTEX; a++) { 00086 mtex= ma->mtex[a]; 00087 if(mtex && mtex->tex) mtex->tex->id.us--; 00088 if(mtex) MEM_freeN(mtex); 00089 } 00090 00091 if(ma->ramp_col) MEM_freeN(ma->ramp_col); 00092 if(ma->ramp_spec) MEM_freeN(ma->ramp_spec); 00093 00094 BKE_free_animdata((ID *)ma); 00095 00096 if(ma->preview) 00097 BKE_previewimg_free(&ma->preview); 00098 BKE_icon_delete((struct ID*)ma); 00099 ma->id.icon_id = 0; 00100 00101 /* is no lib link block, but material extension */ 00102 if(ma->nodetree) { 00103 ntreeFreeTree(ma->nodetree); 00104 MEM_freeN(ma->nodetree); 00105 } 00106 00107 if(ma->gpumaterial.first) 00108 GPU_material_free(ma); 00109 } 00110 00111 void init_material(Material *ma) 00112 { 00113 ma->r= ma->g= ma->b= ma->ref= 0.8; 00114 ma->specr= ma->specg= ma->specb= 1.0; 00115 ma->mirr= ma->mirg= ma->mirb= 1.0; 00116 ma->spectra= 1.0; 00117 ma->amb= 1.0; 00118 ma->alpha= 1.0; 00119 ma->spec= ma->hasize= 0.5; 00120 ma->har= 50; 00121 ma->starc= ma->ringc= 4; 00122 ma->linec= 12; 00123 ma->flarec= 1; 00124 ma->flaresize= ma->subsize= 1.0; 00125 ma->flareboost= 1; 00126 ma->seed2= 6; 00127 ma->friction= 0.5; 00128 ma->refrac= 4.0; 00129 ma->roughness= 0.5; 00130 ma->param[0]= 0.5; 00131 ma->param[1]= 0.1; 00132 ma->param[2]= 0.5; 00133 ma->param[3]= 0.1; 00134 ma->rms= 0.1; 00135 ma->darkness= 1.0; 00136 00137 ma->strand_sta= ma->strand_end= 1.0f; 00138 00139 ma->ang= 1.0; 00140 ma->ray_depth= 2; 00141 ma->ray_depth_tra= 2; 00142 ma->fresnel_mir= 0.0; 00143 ma->fresnel_tra= 0.0; 00144 ma->fresnel_tra_i= 1.25; 00145 ma->fresnel_mir_i= 1.25; 00146 ma->tx_limit= 0.0; 00147 ma->tx_falloff= 1.0; 00148 ma->shad_alpha= 1.0f; 00149 00150 ma->gloss_mir = ma->gloss_tra= 1.0; 00151 ma->samp_gloss_mir = ma->samp_gloss_tra= 18; 00152 ma->adapt_thresh_mir = ma->adapt_thresh_tra = 0.005; 00153 ma->dist_mir = 0.0; 00154 ma->fadeto_mir = MA_RAYMIR_FADETOSKY; 00155 00156 ma->rampfac_col= 1.0; 00157 ma->rampfac_spec= 1.0; 00158 ma->pr_lamp= 3; /* two lamps, is bits */ 00159 ma->pr_type= MA_SPHERE; 00160 00161 ma->sss_radius[0]= 1.0f; 00162 ma->sss_radius[1]= 1.0f; 00163 ma->sss_radius[2]= 1.0f; 00164 ma->sss_col[0]= 1.0f; 00165 ma->sss_col[1]= 1.0f; 00166 ma->sss_col[2]= 1.0f; 00167 ma->sss_error= 0.05f; 00168 ma->sss_scale= 0.1f; 00169 ma->sss_ior= 1.3f; 00170 ma->sss_colfac= 1.0f; 00171 ma->sss_texfac= 0.0f; 00172 ma->sss_front= 1.0f; 00173 ma->sss_back= 1.0f; 00174 00175 ma->vol.density = 1.0f; 00176 ma->vol.emission = 0.0f; 00177 ma->vol.scattering = 1.0f; 00178 ma->vol.reflection = 1.0f; 00179 ma->vol.transmission_col[0] = ma->vol.transmission_col[1] = ma->vol.transmission_col[2] = 1.0f; 00180 ma->vol.reflection_col[0] = ma->vol.reflection_col[1] = ma->vol.reflection_col[2] = 1.0f; 00181 ma->vol.emission_col[0] = ma->vol.emission_col[1] = ma->vol.emission_col[2] = 1.0f; 00182 ma->vol.density_scale = 1.0f; 00183 ma->vol.depth_cutoff = 0.01f; 00184 ma->vol.stepsize_type = MA_VOL_STEP_RANDOMIZED; 00185 ma->vol.stepsize = 0.2f; 00186 ma->vol.shade_type = MA_VOL_SHADE_SHADED; 00187 ma->vol.shadeflag |= MA_VOL_PRECACHESHADING; 00188 ma->vol.precache_resolution = 50; 00189 ma->vol.ms_spread = 0.2f; 00190 ma->vol.ms_diff = 1.f; 00191 ma->vol.ms_intensity = 1.f; 00192 00193 ma->game.flag = GEMAT_BACKCULL; 00194 ma->game.alpha_blend=0; 00195 ma->game.face_orientation=0; 00196 00197 ma->mode= MA_TRACEBLE|MA_SHADBUF|MA_SHADOW|MA_RAYBIAS|MA_TANGENT_STR|MA_ZTRANSP; 00198 ma->shade_flag= MA_APPROX_OCCLUSION; 00199 ma->preview = NULL; 00200 } 00201 00202 Material *add_material(const char *name) 00203 { 00204 Material *ma; 00205 00206 ma= alloc_libblock(&G.main->mat, ID_MA, name); 00207 00208 init_material(ma); 00209 00210 return ma; 00211 } 00212 00213 /* XXX keep synced with next function */ 00214 Material *copy_material(Material *ma) 00215 { 00216 Material *man; 00217 int a; 00218 00219 man= copy_libblock(&ma->id); 00220 00221 id_lib_extern((ID *)man->group); 00222 00223 for(a=0; a<MAX_MTEX; a++) { 00224 if(ma->mtex[a]) { 00225 man->mtex[a]= MEM_mallocN(sizeof(MTex), "copymaterial"); 00226 memcpy(man->mtex[a], ma->mtex[a], sizeof(MTex)); 00227 id_us_plus((ID *)man->mtex[a]->tex); 00228 } 00229 } 00230 00231 if(ma->ramp_col) man->ramp_col= MEM_dupallocN(ma->ramp_col); 00232 if(ma->ramp_spec) man->ramp_spec= MEM_dupallocN(ma->ramp_spec); 00233 00234 if (ma->preview) man->preview = BKE_previewimg_copy(ma->preview); 00235 00236 if(ma->nodetree) { 00237 man->nodetree= ntreeCopyTree(ma->nodetree); /* 0 == full new tree */ 00238 } 00239 00240 man->gpumaterial.first= man->gpumaterial.last= NULL; 00241 00242 return man; 00243 } 00244 00245 /* XXX (see above) material copy without adding to main dbase */ 00246 Material *localize_material(Material *ma) 00247 { 00248 Material *man; 00249 int a; 00250 00251 man= copy_libblock(&ma->id); 00252 BLI_remlink(&G.main->mat, man); 00253 00254 /* no increment for texture ID users, in previewrender.c it prevents decrement */ 00255 for(a=0; a<MAX_MTEX; a++) { 00256 if(ma->mtex[a]) { 00257 man->mtex[a]= MEM_mallocN(sizeof(MTex), "copymaterial"); 00258 memcpy(man->mtex[a], ma->mtex[a], sizeof(MTex)); 00259 } 00260 } 00261 00262 if(ma->ramp_col) man->ramp_col= MEM_dupallocN(ma->ramp_col); 00263 if(ma->ramp_spec) man->ramp_spec= MEM_dupallocN(ma->ramp_spec); 00264 00265 man->preview = NULL; 00266 00267 if(ma->nodetree) 00268 man->nodetree= ntreeLocalize(ma->nodetree); 00269 00270 man->gpumaterial.first= man->gpumaterial.last= NULL; 00271 00272 return man; 00273 } 00274 00275 static void extern_local_material(Material *ma) 00276 { 00277 int i; 00278 for(i=0; i < MAX_MTEX; i++) { 00279 if(ma->mtex[i]) id_lib_extern((ID *)ma->mtex[i]->tex); 00280 } 00281 } 00282 00283 void make_local_material(Material *ma) 00284 { 00285 Main *bmain= G.main; 00286 Object *ob; 00287 Mesh *me; 00288 Curve *cu; 00289 MetaBall *mb; 00290 int a, is_local= FALSE, is_lib= FALSE; 00291 00292 /* - only lib users: do nothing 00293 * - only local users: set flag 00294 * - mixed: make copy 00295 */ 00296 00297 if(ma->id.lib==NULL) return; 00298 00299 /* One local user; set flag and return. */ 00300 if(ma->id.us==1) { 00301 id_clear_lib_data(bmain, &ma->id); 00302 extern_local_material(ma); 00303 return; 00304 } 00305 00306 /* Check which other IDs reference this one to determine if it's used by 00307 lib or local */ 00308 /* test objects */ 00309 ob= bmain->object.first; 00310 while(ob) { 00311 if(ob->mat) { 00312 for(a=0; a<ob->totcol; a++) { 00313 if(ob->mat[a]==ma) { 00314 if(ob->id.lib) is_lib= TRUE; 00315 else is_local= TRUE; 00316 } 00317 } 00318 } 00319 ob= ob->id.next; 00320 } 00321 /* test meshes */ 00322 me= bmain->mesh.first; 00323 while(me) { 00324 if(me->mat) { 00325 for(a=0; a<me->totcol; a++) { 00326 if(me->mat[a]==ma) { 00327 if(me->id.lib) is_lib= TRUE; 00328 else is_local= TRUE; 00329 } 00330 } 00331 } 00332 me= me->id.next; 00333 } 00334 /* test curves */ 00335 cu= bmain->curve.first; 00336 while(cu) { 00337 if(cu->mat) { 00338 for(a=0; a<cu->totcol; a++) { 00339 if(cu->mat[a]==ma) { 00340 if(cu->id.lib) is_lib= TRUE; 00341 else is_local= TRUE; 00342 } 00343 } 00344 } 00345 cu= cu->id.next; 00346 } 00347 /* test mballs */ 00348 mb= bmain->mball.first; 00349 while(mb) { 00350 if(mb->mat) { 00351 for(a=0; a<mb->totcol; a++) { 00352 if(mb->mat[a]==ma) { 00353 if(mb->id.lib) is_lib= TRUE; 00354 else is_local= TRUE; 00355 } 00356 } 00357 } 00358 mb= mb->id.next; 00359 } 00360 00361 /* Only local users. */ 00362 if(is_local && is_lib == FALSE) { 00363 id_clear_lib_data(bmain, &ma->id); 00364 extern_local_material(ma); 00365 } 00366 /* Both user and local, so copy. */ 00367 else if(is_local && is_lib) { 00368 Material *ma_new= copy_material(ma); 00369 00370 ma_new->id.us= 0; 00371 00372 /* Remap paths of new ID using old library as base. */ 00373 BKE_id_lib_local_paths(bmain, ma->id.lib, &ma_new->id); 00374 00375 /* do objects */ 00376 ob= bmain->object.first; 00377 while(ob) { 00378 if(ob->mat) { 00379 for(a=0; a<ob->totcol; a++) { 00380 if(ob->mat[a]==ma) { 00381 if(ob->id.lib==NULL) { 00382 ob->mat[a]= ma_new; 00383 ma_new->id.us++; 00384 ma->id.us--; 00385 } 00386 } 00387 } 00388 } 00389 ob= ob->id.next; 00390 } 00391 /* do meshes */ 00392 me= bmain->mesh.first; 00393 while(me) { 00394 if(me->mat) { 00395 for(a=0; a<me->totcol; a++) { 00396 if(me->mat[a]==ma) { 00397 if(me->id.lib==NULL) { 00398 me->mat[a]= ma_new; 00399 ma_new->id.us++; 00400 ma->id.us--; 00401 } 00402 } 00403 } 00404 } 00405 me= me->id.next; 00406 } 00407 /* do curves */ 00408 cu= bmain->curve.first; 00409 while(cu) { 00410 if(cu->mat) { 00411 for(a=0; a<cu->totcol; a++) { 00412 if(cu->mat[a]==ma) { 00413 if(cu->id.lib==NULL) { 00414 cu->mat[a]= ma_new; 00415 ma_new->id.us++; 00416 ma->id.us--; 00417 } 00418 } 00419 } 00420 } 00421 cu= cu->id.next; 00422 } 00423 /* do mballs */ 00424 mb= bmain->mball.first; 00425 while(mb) { 00426 if(mb->mat) { 00427 for(a=0; a<mb->totcol; a++) { 00428 if(mb->mat[a]==ma) { 00429 if(mb->id.lib==NULL) { 00430 mb->mat[a]= ma_new; 00431 ma_new->id.us++; 00432 ma->id.us--; 00433 } 00434 } 00435 } 00436 } 00437 mb= mb->id.next; 00438 } 00439 } 00440 } 00441 00442 /* for curve, mball, mesh types */ 00443 void extern_local_matarar(struct Material **matar, short totcol) 00444 { 00445 short i; 00446 for(i= 0; i < totcol; i++) { 00447 id_lib_extern((ID *)matar[i]); 00448 } 00449 } 00450 00451 Material ***give_matarar(Object *ob) 00452 { 00453 Mesh *me; 00454 Curve *cu; 00455 MetaBall *mb; 00456 00457 if(ob->type==OB_MESH) { 00458 me= ob->data; 00459 return &(me->mat); 00460 } 00461 else if ELEM3(ob->type, OB_CURVE, OB_FONT, OB_SURF) { 00462 cu= ob->data; 00463 return &(cu->mat); 00464 } 00465 else if(ob->type==OB_MBALL) { 00466 mb= ob->data; 00467 return &(mb->mat); 00468 } 00469 return NULL; 00470 } 00471 00472 short *give_totcolp(Object *ob) 00473 { 00474 Mesh *me; 00475 Curve *cu; 00476 MetaBall *mb; 00477 00478 if(ob->type==OB_MESH) { 00479 me= ob->data; 00480 return &(me->totcol); 00481 } 00482 else if ELEM3(ob->type, OB_CURVE, OB_FONT, OB_SURF) { 00483 cu= ob->data; 00484 return &(cu->totcol); 00485 } 00486 else if(ob->type==OB_MBALL) { 00487 mb= ob->data; 00488 return &(mb->totcol); 00489 } 00490 return NULL; 00491 } 00492 00493 /* same as above but for ID's */ 00494 Material ***give_matarar_id(ID *id) 00495 { 00496 switch(GS(id->name)) { 00497 case ID_ME: 00498 return &(((Mesh *)id)->mat); 00499 break; 00500 case ID_CU: 00501 return &(((Curve *)id)->mat); 00502 break; 00503 case ID_MB: 00504 return &(((MetaBall *)id)->mat); 00505 break; 00506 } 00507 return NULL; 00508 } 00509 00510 short *give_totcolp_id(ID *id) 00511 { 00512 switch(GS(id->name)) { 00513 case ID_ME: 00514 return &(((Mesh *)id)->totcol); 00515 break; 00516 case ID_CU: 00517 return &(((Curve *)id)->totcol); 00518 break; 00519 case ID_MB: 00520 return &(((MetaBall *)id)->totcol); 00521 break; 00522 } 00523 return NULL; 00524 } 00525 00526 static void data_delete_material_index_id(ID *id, short index) 00527 { 00528 switch(GS(id->name)) { 00529 case ID_ME: 00530 mesh_delete_material_index((Mesh *)id, index); 00531 break; 00532 case ID_CU: 00533 curve_delete_material_index((Curve *)id, index); 00534 break; 00535 case ID_MB: 00536 /* meta-elems dont have materials atm */ 00537 break; 00538 } 00539 } 00540 00541 void material_append_id(ID *id, Material *ma) 00542 { 00543 Material ***matar; 00544 if((matar= give_matarar_id(id))) { 00545 short *totcol= give_totcolp_id(id); 00546 Material **mat= MEM_callocN(sizeof(void *) * ((*totcol) + 1), "newmatar"); 00547 if(*totcol) memcpy(mat, *matar, sizeof(void *) * (*totcol)); 00548 if(*matar) MEM_freeN(*matar); 00549 00550 *matar= mat; 00551 (*matar)[(*totcol)++]= ma; 00552 00553 id_us_plus((ID *)ma); 00554 test_object_materials(id); 00555 } 00556 } 00557 00558 Material *material_pop_id(ID *id, int index_i, int remove_material_slot) 00559 { 00560 short index= (short)index_i; 00561 Material *ret= NULL; 00562 Material ***matar; 00563 if((matar= give_matarar_id(id))) { 00564 short *totcol= give_totcolp_id(id); 00565 if(index >= 0 && index < (*totcol)) { 00566 ret= (*matar)[index]; 00567 id_us_min((ID *)ret); 00568 00569 if (remove_material_slot) { 00570 if(*totcol <= 1) { 00571 *totcol= 0; 00572 MEM_freeN(*matar); 00573 *matar= NULL; 00574 } 00575 else { 00576 Material **mat; 00577 if(index + 1 != (*totcol)) 00578 memmove((*matar)+index, (*matar)+(index+1), sizeof(void *) * ((*totcol) - (index + 1))); 00579 00580 (*totcol)--; 00581 00582 mat= MEM_callocN(sizeof(void *) * (*totcol), "newmatar"); 00583 memcpy(mat, *matar, sizeof(void *) * (*totcol)); 00584 MEM_freeN(*matar); 00585 00586 *matar= mat; 00587 test_object_materials(id); 00588 } 00589 00590 /* decrease mat_nr index */ 00591 data_delete_material_index_id(id, index); 00592 } 00593 00594 /* don't remove material slot, only clear it*/ 00595 else 00596 (*matar)[index]= NULL; 00597 } 00598 } 00599 00600 return ret; 00601 } 00602 00603 Material *give_current_material(Object *ob, short act) 00604 { 00605 Material ***matarar, *ma; 00606 short *totcolp; 00607 00608 if(ob==NULL) return NULL; 00609 00610 /* if object cannot have material, totcolp==NULL */ 00611 totcolp= give_totcolp(ob); 00612 if(totcolp==NULL || ob->totcol==0) return NULL; 00613 00614 if(act<0) { 00615 printf("no!\n"); 00616 } 00617 00618 if(act>ob->totcol) act= ob->totcol; 00619 else if(act<=0) act= 1; 00620 00621 if(ob->matbits && ob->matbits[act-1]) { /* in object */ 00622 ma= ob->mat[act-1]; 00623 } 00624 else { /* in data */ 00625 00626 /* check for inconsistency */ 00627 if(*totcolp < ob->totcol) 00628 ob->totcol= *totcolp; 00629 if(act>ob->totcol) act= ob->totcol; 00630 00631 matarar= give_matarar(ob); 00632 00633 if(matarar && *matarar) ma= (*matarar)[act-1]; 00634 else ma= NULL; 00635 00636 } 00637 00638 return ma; 00639 } 00640 00641 ID *material_from(Object *ob, short act) 00642 { 00643 00644 if(ob==NULL) return NULL; 00645 00646 if(ob->totcol==0) return ob->data; 00647 if(act==0) act= 1; 00648 00649 if(ob->matbits[act-1]) return (ID *)ob; 00650 else return ob->data; 00651 } 00652 00653 Material *give_node_material(Material *ma) 00654 { 00655 if(ma && ma->use_nodes && ma->nodetree) { 00656 bNode *node= nodeGetActiveID(ma->nodetree, ID_MA); 00657 00658 if(node) 00659 return (Material *)node->id; 00660 } 00661 00662 return NULL; 00663 } 00664 00665 /* GS reads the memory pointed at in a specific ordering. There are, 00666 * however two definitions for it. I have jotted them down here, both, 00667 * but I think the first one is actually used. The thing is that 00668 * big-endian systems might read this the wrong way round. OTOH, we 00669 * constructed the IDs that are read out with this macro explicitly as 00670 * well. I expect we'll sort it out soon... */ 00671 00672 /* from blendef: */ 00673 #define GS(a) (*((short *)(a))) 00674 00675 /* from misc_util: flip the bytes from x */ 00676 /* #define GS(x) (((unsigned char *)(x))[0] << 8 | ((unsigned char *)(x))[1]) */ 00677 00678 void resize_object_material(Object *ob, const short totcol) 00679 { 00680 Material **newmatar; 00681 char *newmatbits; 00682 00683 if(totcol==0) { 00684 if(ob->totcol) { 00685 MEM_freeN(ob->mat); 00686 MEM_freeN(ob->matbits); 00687 ob->mat= NULL; 00688 ob->matbits= NULL; 00689 } 00690 } 00691 else if(ob->totcol<totcol) { 00692 newmatar= MEM_callocN(sizeof(void *)*totcol, "newmatar"); 00693 newmatbits= MEM_callocN(sizeof(char)*totcol, "newmatbits"); 00694 if(ob->totcol) { 00695 memcpy(newmatar, ob->mat, sizeof(void *)*ob->totcol); 00696 memcpy(newmatbits, ob->matbits, sizeof(char)*ob->totcol); 00697 MEM_freeN(ob->mat); 00698 MEM_freeN(ob->matbits); 00699 } 00700 ob->mat= newmatar; 00701 ob->matbits= newmatbits; 00702 } 00703 ob->totcol= totcol; 00704 if(ob->totcol && ob->actcol==0) ob->actcol= 1; 00705 if(ob->actcol>ob->totcol) ob->actcol= ob->totcol; 00706 } 00707 00708 void test_object_materials(ID *id) 00709 { 00710 /* make the ob mat-array same size as 'ob->data' mat-array */ 00711 Object *ob; 00712 short *totcol; 00713 00714 if(id==NULL || (totcol=give_totcolp_id(id))==NULL) { 00715 return; 00716 } 00717 00718 for(ob= G.main->object.first; ob; ob= ob->id.next) { 00719 if(ob->data==id) { 00720 resize_object_material(ob, *totcol); 00721 } 00722 } 00723 } 00724 00725 void assign_material_id(ID *id, Material *ma, short act) 00726 { 00727 Material *mao, **matar, ***matarar; 00728 short *totcolp; 00729 00730 if(act>MAXMAT) return; 00731 if(act<1) act= 1; 00732 00733 /* prevent crashing when using accidentally */ 00734 BLI_assert(id->lib == NULL); 00735 if(id->lib) return; 00736 00737 /* test arraylens */ 00738 00739 totcolp= give_totcolp_id(id); 00740 matarar= give_matarar_id(id); 00741 00742 if(totcolp==NULL || matarar==NULL) return; 00743 00744 if(act > *totcolp) { 00745 matar= MEM_callocN(sizeof(void *)*act, "matarray1"); 00746 00747 if(*totcolp) { 00748 memcpy(matar, *matarar, sizeof(void *)*(*totcolp)); 00749 MEM_freeN(*matarar); 00750 } 00751 00752 *matarar= matar; 00753 *totcolp= act; 00754 } 00755 00756 /* in data */ 00757 mao= (*matarar)[act-1]; 00758 if(mao) mao->id.us--; 00759 (*matarar)[act-1]= ma; 00760 00761 if(ma) 00762 id_us_plus((ID *)ma); 00763 00764 test_object_materials(id); 00765 } 00766 00767 void assign_material(Object *ob, Material *ma, short act) 00768 { 00769 Material *mao, **matar, ***matarar; 00770 char *matbits; 00771 short *totcolp; 00772 00773 if(act>MAXMAT) return; 00774 if(act<1) act= 1; 00775 00776 /* prevent crashing when using accidentally */ 00777 BLI_assert(ob->id.lib == NULL); 00778 if(ob->id.lib) return; 00779 00780 /* test arraylens */ 00781 00782 totcolp= give_totcolp(ob); 00783 matarar= give_matarar(ob); 00784 00785 if(totcolp==NULL || matarar==NULL) return; 00786 00787 if(act > *totcolp) { 00788 matar= MEM_callocN(sizeof(void *)*act, "matarray1"); 00789 00790 if(*totcolp) { 00791 memcpy(matar, *matarar, sizeof(void *)*(*totcolp)); 00792 MEM_freeN(*matarar); 00793 } 00794 00795 *matarar= matar; 00796 *totcolp= act; 00797 } 00798 00799 if(act > ob->totcol) { 00800 matar= MEM_callocN(sizeof(void *)*act, "matarray2"); 00801 matbits= MEM_callocN(sizeof(char)*act, "matbits1"); 00802 if( ob->totcol) { 00803 memcpy(matar, ob->mat, sizeof(void *)*( ob->totcol )); 00804 memcpy(matbits, ob->matbits, sizeof(char)*(*totcolp)); 00805 MEM_freeN(ob->mat); 00806 MEM_freeN(ob->matbits); 00807 } 00808 ob->mat= matar; 00809 ob->matbits= matbits; 00810 ob->totcol= act; 00811 00812 /* copy object/mesh linking, or assign based on userpref */ 00813 if(ob->actcol) 00814 ob->matbits[act-1]= ob->matbits[ob->actcol-1]; 00815 else 00816 ob->matbits[act-1]= (U.flag & USER_MAT_ON_OB)? 1: 0; 00817 } 00818 00819 /* do it */ 00820 00821 if(ob->matbits[act-1]) { /* in object */ 00822 mao= ob->mat[act-1]; 00823 if(mao) mao->id.us--; 00824 ob->mat[act-1]= ma; 00825 } 00826 else { /* in data */ 00827 mao= (*matarar)[act-1]; 00828 if(mao) mao->id.us--; 00829 (*matarar)[act-1]= ma; 00830 } 00831 00832 if(ma) 00833 id_us_plus((ID *)ma); 00834 test_object_materials(ob->data); 00835 } 00836 00837 /* XXX - this calls many more update calls per object then are needed, could be optimized */ 00838 void assign_matarar(struct Object *ob, struct Material ***matar, short totcol) 00839 { 00840 int actcol_orig= ob->actcol; 00841 short i; 00842 00843 while(object_remove_material_slot(ob)) {}; 00844 00845 /* now we have the right number of slots */ 00846 for(i=0; i<totcol; i++) 00847 assign_material(ob, (*matar)[i], i+1); 00848 00849 if(actcol_orig > ob->totcol) 00850 actcol_orig= ob->totcol; 00851 00852 ob->actcol= actcol_orig; 00853 } 00854 00855 00856 short find_material_index(Object *ob, Material *ma) 00857 { 00858 Material ***matarar; 00859 short a, *totcolp; 00860 00861 if(ma==NULL) return 0; 00862 00863 totcolp= give_totcolp(ob); 00864 matarar= give_matarar(ob); 00865 00866 if(totcolp==NULL || matarar==NULL) return 0; 00867 00868 for(a=0; a<*totcolp; a++) 00869 if((*matarar)[a]==ma) 00870 break; 00871 if(a<*totcolp) 00872 return a+1; 00873 return 0; 00874 } 00875 00876 int object_add_material_slot(Object *ob) 00877 { 00878 if(ob==NULL) return FALSE; 00879 if(ob->totcol>=MAXMAT) return FALSE; 00880 00881 assign_material(ob, NULL, ob->totcol+1); 00882 ob->actcol= ob->totcol; 00883 return TRUE; 00884 } 00885 00886 static void do_init_render_material(Material *ma, int r_mode, float *amb) 00887 { 00888 MTex *mtex; 00889 int a, needuv=0, needtang=0; 00890 00891 if(ma->flarec==0) ma->flarec= 1; 00892 00893 /* add all texcoflags from mtex, texco and mapto were cleared in advance */ 00894 for(a=0; a<MAX_MTEX; a++) { 00895 00896 /* separate tex switching */ 00897 if(ma->septex & (1<<a)) continue; 00898 00899 mtex= ma->mtex[a]; 00900 if(mtex && mtex->tex && (mtex->tex->type | (mtex->tex->use_nodes && mtex->tex->nodetree) )) { 00901 00902 ma->texco |= mtex->texco; 00903 ma->mapto |= mtex->mapto; 00904 00905 /* always get derivatives for these textures */ 00906 if ELEM3(mtex->tex->type, TEX_IMAGE, TEX_PLUGIN, TEX_ENVMAP) ma->texco |= TEXCO_OSA; 00907 else if(mtex->texflag & (MTEX_COMPAT_BUMP|MTEX_3TAP_BUMP|MTEX_5TAP_BUMP|MTEX_BICUBIC_BUMP)) ma->texco |= TEXCO_OSA; 00908 00909 if(ma->texco & (TEXCO_ORCO|TEXCO_REFL|TEXCO_NORM|TEXCO_STRAND|TEXCO_STRESS)) needuv= 1; 00910 else if(ma->texco & (TEXCO_GLOB|TEXCO_UV|TEXCO_OBJECT|TEXCO_SPEED)) needuv= 1; 00911 else if(ma->texco & (TEXCO_LAVECTOR|TEXCO_VIEW|TEXCO_STICKY)) needuv= 1; 00912 00913 if((ma->mapto & MAP_NORM) && (mtex->normapspace == MTEX_NSPACE_TANGENT)) 00914 needtang= 1; 00915 } 00916 } 00917 00918 if(needtang) ma->mode |= MA_NORMAP_TANG; 00919 else ma->mode &= ~MA_NORMAP_TANG; 00920 00921 if(ma->mode & (MA_VERTEXCOL|MA_VERTEXCOLP|MA_FACETEXTURE)) { 00922 needuv= 1; 00923 if(r_mode & R_OSA) ma->texco |= TEXCO_OSA; /* for texfaces */ 00924 } 00925 if(needuv) ma->texco |= NEED_UV; 00926 00927 /* since the raytracer doesnt recalc O structs for each ray, we have to preset them all */ 00928 if(r_mode & R_RAYTRACE) { 00929 if((ma->mode & (MA_RAYMIRROR|MA_SHADOW_TRA)) || ((ma->mode & MA_TRANSP) && (ma->mode & MA_RAYTRANSP))) { 00930 ma->texco |= NEED_UV|TEXCO_ORCO|TEXCO_REFL|TEXCO_NORM; 00931 if(r_mode & R_OSA) ma->texco |= TEXCO_OSA; 00932 } 00933 } 00934 00935 if(amb) { 00936 ma->ambr= ma->amb*amb[0]; 00937 ma->ambg= ma->amb*amb[1]; 00938 ma->ambb= ma->amb*amb[2]; 00939 } 00940 /* will become or-ed result of all node modes */ 00941 ma->mode_l= ma->mode; 00942 ma->mode_l &= ~MA_SHLESS; 00943 00944 if(ma->strand_surfnor > 0.0f) 00945 ma->mode_l |= MA_STR_SURFDIFF; 00946 00947 /* parses the geom+tex nodes */ 00948 if(ma->nodetree && ma->use_nodes) 00949 ntreeShaderGetTexcoMode(ma->nodetree, r_mode, &ma->texco, &ma->mode_l); 00950 } 00951 00952 static void init_render_nodetree(bNodeTree *ntree, Material *basemat, int r_mode, float *amb) 00953 { 00954 bNode *node; 00955 00956 for(node=ntree->nodes.first; node; node= node->next) { 00957 if(node->id) { 00958 if(GS(node->id->name)==ID_MA) { 00959 Material *ma= (Material *)node->id; 00960 if(ma!=basemat) { 00961 do_init_render_material(ma, r_mode, amb); 00962 basemat->texco |= ma->texco; 00963 basemat->mode_l |= ma->mode_l & ~(MA_TRANSP|MA_ZTRANSP|MA_RAYTRANSP); 00964 } 00965 } 00966 else if(node->type==NODE_GROUP) 00967 init_render_nodetree((bNodeTree *)node->id, basemat, r_mode, amb); 00968 } 00969 } 00970 } 00971 00972 void init_render_material(Material *mat, int r_mode, float *amb) 00973 { 00974 00975 do_init_render_material(mat, r_mode, amb); 00976 00977 if(mat->nodetree && mat->use_nodes) { 00978 init_render_nodetree(mat->nodetree, mat, r_mode, amb); 00979 00980 if (!mat->nodetree->execdata) 00981 mat->nodetree->execdata = ntreeShaderBeginExecTree(mat->nodetree, 1); 00982 } 00983 } 00984 00985 void init_render_materials(Main *bmain, int r_mode, float *amb) 00986 { 00987 Material *ma; 00988 00989 /* clear these flags before going over materials, to make sure they 00990 * are cleared only once, otherwise node materials contained in other 00991 * node materials can go wrong */ 00992 for(ma= bmain->mat.first; ma; ma= ma->id.next) { 00993 if(ma->id.us) { 00994 ma->texco= 0; 00995 ma->mapto= 0; 00996 } 00997 } 00998 00999 /* two steps, first initialize, then or the flags for layers */ 01000 for(ma= bmain->mat.first; ma; ma= ma->id.next) { 01001 /* is_used flag comes back in convertblender.c */ 01002 ma->flag &= ~MA_IS_USED; 01003 if(ma->id.us) 01004 init_render_material(ma, r_mode, amb); 01005 } 01006 01007 do_init_render_material(&defmaterial, r_mode, amb); 01008 } 01009 01010 /* only needed for nodes now */ 01011 void end_render_material(Material *mat) 01012 { 01013 if(mat && mat->nodetree && mat->use_nodes) { 01014 if (mat->nodetree->execdata) 01015 ntreeShaderEndExecTree(mat->nodetree->execdata, 1); 01016 } 01017 } 01018 01019 void end_render_materials(Main *bmain) 01020 { 01021 Material *ma; 01022 for(ma= bmain->mat.first; ma; ma= ma->id.next) 01023 if(ma->id.us) 01024 end_render_material(ma); 01025 } 01026 01027 static int material_in_nodetree(bNodeTree *ntree, Material *mat) 01028 { 01029 bNode *node; 01030 01031 for(node=ntree->nodes.first; node; node= node->next) { 01032 if(node->id && GS(node->id->name)==ID_MA) { 01033 if(node->id==(ID*)mat) 01034 return 1; 01035 } 01036 else if(node->type==NODE_GROUP) 01037 if(material_in_nodetree((bNodeTree*)node->id, mat)) 01038 return 1; 01039 } 01040 01041 return 0; 01042 } 01043 01044 int material_in_material(Material *parmat, Material *mat) 01045 { 01046 if(parmat==mat) 01047 return 1; 01048 else if(parmat->nodetree && parmat->use_nodes) 01049 return material_in_nodetree(parmat->nodetree, mat); 01050 else 01051 return 0; 01052 } 01053 01054 /* ****************** */ 01055 01056 static char colname_array[125][20]= { 01057 "Black","DarkRed","HalfRed","Red","Red", 01058 "DarkGreen","DarkOlive","Brown","Chocolate","OrangeRed", 01059 "HalfGreen","GreenOlive","DryOlive","Goldenrod","DarkOrange", 01060 "LightGreen","Chartreuse","YellowGreen","Yellow","Gold", 01061 "Green","LawnGreen","GreenYellow","LightOlive","Yellow", 01062 "DarkBlue","DarkPurple","HotPink","VioletPink","RedPink", 01063 "SlateGray","DarkGrey","PalePurple","IndianRed","Tomato", 01064 "SeaGreen","PaleGreen","GreenKhaki","LightBrown","LightSalmon", 01065 "SpringGreen","PaleGreen","MediumOlive","YellowBrown","LightGold", 01066 "LightGreen","LightGreen","LightGreen","GreenYellow","PaleYellow", 01067 "HalfBlue","DarkSky","HalfMagenta","VioletRed","DeepPink", 01068 "SteelBlue","SkyBlue","Orchid","LightHotPink","HotPink", 01069 "SeaGreen","SlateGray","MediumGrey","Burlywood","LightPink", 01070 "SpringGreen","Aquamarine","PaleGreen","Khaki","PaleOrange", 01071 "SpringGreen","SeaGreen","PaleGreen","PaleWhite","YellowWhite", 01072 "LightBlue","Purple","MediumOrchid","Magenta","Magenta", 01073 "RoyalBlue","SlateBlue","MediumOrchid","Orchid","Magenta", 01074 "DeepSkyBlue","LightSteelBlue","LightSkyBlue","Violet","LightPink", 01075 "Cyan","DarkTurquoise","SkyBlue","Grey","Snow", 01076 "Mint","Mint","Aquamarine","MintCream","Ivory", 01077 "Blue","Blue","DarkMagenta","DarkOrchid","Magenta", 01078 "SkyBlue","RoyalBlue","LightSlateBlue","MediumOrchid","Magenta", 01079 "DodgerBlue","SteelBlue","MediumPurple","PalePurple","Plum", 01080 "DeepSkyBlue","PaleBlue","LightSkyBlue","PalePurple","Thistle", 01081 "Cyan","ColdBlue","PaleTurquoise","GhostWhite","White" 01082 }; 01083 01084 void automatname(Material *ma) 01085 { 01086 int nr, r, g, b; 01087 float ref; 01088 01089 if(ma==NULL) return; 01090 if(ma->mode & MA_SHLESS) ref= 1.0; 01091 else ref= ma->ref; 01092 01093 r= (int)(4.99f*(ref*ma->r)); 01094 g= (int)(4.99f*(ref*ma->g)); 01095 b= (int)(4.99f*(ref*ma->b)); 01096 nr= r + 5*g + 25*b; 01097 if(nr>124) nr= 124; 01098 new_id(&G.main->mat, (ID *)ma, colname_array[nr]); 01099 01100 } 01101 01102 01103 int object_remove_material_slot(Object *ob) 01104 { 01105 Material *mao, ***matarar; 01106 Object *obt; 01107 short *totcolp; 01108 short a, actcol; 01109 01110 if (ob==NULL || ob->totcol==0) { 01111 return FALSE; 01112 } 01113 01114 /* this should never happen and used to crash */ 01115 if (ob->actcol <= 0) { 01116 printf("%s: invalid material index %d, report a bug!\n", __func__, ob->actcol); 01117 BLI_assert(0); 01118 return FALSE; 01119 } 01120 01121 /* take a mesh/curve/mball as starting point, remove 1 index, 01122 * AND with all objects that share the ob->data 01123 * 01124 * after that check indices in mesh/curve/mball!!! 01125 */ 01126 01127 totcolp= give_totcolp(ob); 01128 matarar= give_matarar(ob); 01129 01130 if(*matarar==NULL) return FALSE; 01131 01132 /* we delete the actcol */ 01133 mao= (*matarar)[ob->actcol-1]; 01134 if(mao) mao->id.us--; 01135 01136 for(a=ob->actcol; a<ob->totcol; a++) 01137 (*matarar)[a-1]= (*matarar)[a]; 01138 (*totcolp)--; 01139 01140 if(*totcolp==0) { 01141 MEM_freeN(*matarar); 01142 *matarar= NULL; 01143 } 01144 01145 actcol= ob->actcol; 01146 obt= G.main->object.first; 01147 while(obt) { 01148 01149 if(obt->data==ob->data) { 01150 01151 /* WATCH IT: do not use actcol from ob or from obt (can become zero) */ 01152 mao= obt->mat[actcol-1]; 01153 if(mao) mao->id.us--; 01154 01155 for(a=actcol; a<obt->totcol; a++) { 01156 obt->mat[a-1]= obt->mat[a]; 01157 obt->matbits[a-1]= obt->matbits[a]; 01158 } 01159 obt->totcol--; 01160 if(obt->actcol > obt->totcol) obt->actcol= obt->totcol; 01161 01162 if(obt->totcol==0) { 01163 MEM_freeN(obt->mat); 01164 MEM_freeN(obt->matbits); 01165 obt->mat= NULL; 01166 obt->matbits= NULL; 01167 } 01168 } 01169 obt= obt->id.next; 01170 } 01171 01172 /* check indices from mesh */ 01173 if (ELEM4(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT)) { 01174 data_delete_material_index_id((ID *)ob->data, actcol-1); 01175 freedisplist(&ob->disp); 01176 } 01177 01178 return TRUE; 01179 } 01180 01181 01182 /* r_col = current value, col = new value, fac==0 is no change */ 01183 void ramp_blend(int type, float r_col[3], const float fac, const float col[3]) 01184 { 01185 float tmp, facm= 1.0f-fac; 01186 01187 switch (type) { 01188 case MA_RAMP_BLEND: 01189 r_col[0] = facm*(r_col[0]) + fac*col[0]; 01190 r_col[1] = facm*(r_col[1]) + fac*col[1]; 01191 r_col[2] = facm*(r_col[2]) + fac*col[2]; 01192 break; 01193 case MA_RAMP_ADD: 01194 r_col[0] += fac*col[0]; 01195 r_col[1] += fac*col[1]; 01196 r_col[2] += fac*col[2]; 01197 break; 01198 case MA_RAMP_MULT: 01199 r_col[0] *= (facm + fac*col[0]); 01200 r_col[1] *= (facm + fac*col[1]); 01201 r_col[2] *= (facm + fac*col[2]); 01202 break; 01203 case MA_RAMP_SCREEN: 01204 r_col[0] = 1.0f - (facm + fac*(1.0f - col[0])) * (1.0f - r_col[0]); 01205 r_col[1] = 1.0f - (facm + fac*(1.0f - col[1])) * (1.0f - r_col[1]); 01206 r_col[2] = 1.0f - (facm + fac*(1.0f - col[2])) * (1.0f - r_col[2]); 01207 break; 01208 case MA_RAMP_OVERLAY: 01209 if(r_col[0] < 0.5f) 01210 r_col[0] *= (facm + 2.0f*fac*col[0]); 01211 else 01212 r_col[0] = 1.0f - (facm + 2.0f*fac*(1.0f - col[0])) * (1.0f - r_col[0]); 01213 if(r_col[1] < 0.5f) 01214 r_col[1] *= (facm + 2.0f*fac*col[1]); 01215 else 01216 r_col[1] = 1.0f - (facm + 2.0f*fac*(1.0f - col[1])) * (1.0f - r_col[1]); 01217 if(r_col[2] < 0.5f) 01218 r_col[2] *= (facm + 2.0f*fac*col[2]); 01219 else 01220 r_col[2] = 1.0f - (facm + 2.0f*fac*(1.0f - col[2])) * (1.0f - r_col[2]); 01221 break; 01222 case MA_RAMP_SUB: 01223 r_col[0] -= fac*col[0]; 01224 r_col[1] -= fac*col[1]; 01225 r_col[2] -= fac*col[2]; 01226 break; 01227 case MA_RAMP_DIV: 01228 if(col[0]!=0.0f) 01229 r_col[0] = facm*(r_col[0]) + fac*(r_col[0])/col[0]; 01230 if(col[1]!=0.0f) 01231 r_col[1] = facm*(r_col[1]) + fac*(r_col[1])/col[1]; 01232 if(col[2]!=0.0f) 01233 r_col[2] = facm*(r_col[2]) + fac*(r_col[2])/col[2]; 01234 break; 01235 case MA_RAMP_DIFF: 01236 r_col[0] = facm*(r_col[0]) + fac*fabsf(r_col[0]-col[0]); 01237 r_col[1] = facm*(r_col[1]) + fac*fabsf(r_col[1]-col[1]); 01238 r_col[2] = facm*(r_col[2]) + fac*fabsf(r_col[2]-col[2]); 01239 break; 01240 case MA_RAMP_DARK: 01241 tmp=col[0]+((1-col[0])*facm); 01242 if(tmp < r_col[0]) r_col[0]= tmp; 01243 tmp=col[1]+((1-col[1])*facm); 01244 if(tmp < r_col[1]) r_col[1]= tmp; 01245 tmp=col[2]+((1-col[2])*facm); 01246 if(tmp < r_col[2]) r_col[2]= tmp; 01247 break; 01248 case MA_RAMP_LIGHT: 01249 tmp= fac*col[0]; 01250 if(tmp > r_col[0]) r_col[0]= tmp; 01251 tmp= fac*col[1]; 01252 if(tmp > r_col[1]) r_col[1]= tmp; 01253 tmp= fac*col[2]; 01254 if(tmp > r_col[2]) r_col[2]= tmp; 01255 break; 01256 case MA_RAMP_DODGE: 01257 if(r_col[0] !=0.0f){ 01258 tmp = 1.0f - fac*col[0]; 01259 if(tmp <= 0.0f) 01260 r_col[0] = 1.0f; 01261 else if ((tmp = (r_col[0]) / tmp)> 1.0f) 01262 r_col[0] = 1.0f; 01263 else 01264 r_col[0] = tmp; 01265 } 01266 if(r_col[1] !=0.0f){ 01267 tmp = 1.0f - fac*col[1]; 01268 if(tmp <= 0.0f ) 01269 r_col[1] = 1.0f; 01270 else if ((tmp = (r_col[1]) / tmp) > 1.0f ) 01271 r_col[1] = 1.0f; 01272 else 01273 r_col[1] = tmp; 01274 } 01275 if(r_col[2] !=0.0f){ 01276 tmp = 1.0f - fac*col[2]; 01277 if(tmp <= 0.0f) 01278 r_col[2] = 1.0f; 01279 else if ((tmp = (r_col[2]) / tmp) > 1.0f ) 01280 r_col[2] = 1.0f; 01281 else 01282 r_col[2] = tmp; 01283 } 01284 break; 01285 case MA_RAMP_BURN: 01286 tmp = facm + fac*col[0]; 01287 01288 if(tmp <= 0.0f) 01289 r_col[0] = 0.0f; 01290 else if (( tmp = (1.0f - (1.0f - (r_col[0])) / tmp )) < 0.0f) 01291 r_col[0] = 0.0f; 01292 else if (tmp > 1.0f) 01293 r_col[0]=1.0f; 01294 else 01295 r_col[0] = tmp; 01296 01297 tmp = facm + fac*col[1]; 01298 if(tmp <= 0.0f) 01299 r_col[1] = 0.0f; 01300 else if (( tmp = (1.0f - (1.0f - (r_col[1])) / tmp )) < 0.0f ) 01301 r_col[1] = 0.0f; 01302 else if(tmp >1.0f) 01303 r_col[1]=1.0f; 01304 else 01305 r_col[1] = tmp; 01306 01307 tmp = facm + fac*col[2]; 01308 if(tmp <= 0.0f) 01309 r_col[2] = 0.0f; 01310 else if (( tmp = (1.0f - (1.0f - (r_col[2])) / tmp )) < 0.0f ) 01311 r_col[2] = 0.0f; 01312 else if(tmp >1.0f) 01313 r_col[2]= 1.0f; 01314 else 01315 r_col[2] = tmp; 01316 break; 01317 case MA_RAMP_HUE: 01318 { 01319 float rH,rS,rV; 01320 float colH,colS,colV; 01321 float tmpr,tmpg,tmpb; 01322 rgb_to_hsv(col[0],col[1],col[2],&colH,&colS,&colV); 01323 if(colS!=0 ){ 01324 rgb_to_hsv(r_col[0],r_col[1],r_col[2],&rH,&rS,&rV); 01325 hsv_to_rgb( colH , rS, rV, &tmpr, &tmpg, &tmpb); 01326 r_col[0] = facm*(r_col[0]) + fac*tmpr; 01327 r_col[1] = facm*(r_col[1]) + fac*tmpg; 01328 r_col[2] = facm*(r_col[2]) + fac*tmpb; 01329 } 01330 } 01331 break; 01332 case MA_RAMP_SAT: 01333 { 01334 float rH,rS,rV; 01335 float colH,colS,colV; 01336 rgb_to_hsv(r_col[0],r_col[1],r_col[2],&rH,&rS,&rV); 01337 if(rS!=0){ 01338 rgb_to_hsv(col[0],col[1],col[2],&colH,&colS,&colV); 01339 hsv_to_rgb( rH, (facm*rS +fac*colS), rV, r_col+0, r_col+1, r_col+2); 01340 } 01341 } 01342 break; 01343 case MA_RAMP_VAL: 01344 { 01345 float rH,rS,rV; 01346 float colH,colS,colV; 01347 rgb_to_hsv(r_col[0],r_col[1],r_col[2],&rH,&rS,&rV); 01348 rgb_to_hsv(col[0],col[1],col[2],&colH,&colS,&colV); 01349 hsv_to_rgb( rH, rS, (facm*rV +fac*colV), r_col+0, r_col+1, r_col+2); 01350 } 01351 break; 01352 case MA_RAMP_COLOR: 01353 { 01354 float rH,rS,rV; 01355 float colH,colS,colV; 01356 float tmpr,tmpg,tmpb; 01357 rgb_to_hsv(col[0],col[1],col[2],&colH,&colS,&colV); 01358 if(colS!=0){ 01359 rgb_to_hsv(r_col[0],r_col[1],r_col[2],&rH,&rS,&rV); 01360 hsv_to_rgb( colH, colS, rV, &tmpr, &tmpg, &tmpb); 01361 r_col[0] = facm*(r_col[0]) + fac*tmpr; 01362 r_col[1] = facm*(r_col[1]) + fac*tmpg; 01363 r_col[2] = facm*(r_col[2]) + fac*tmpb; 01364 } 01365 } 01366 break; 01367 case MA_RAMP_SOFT: 01368 { 01369 float scr, scg, scb; 01370 01371 /* first calculate non-fac based Screen mix */ 01372 scr = 1.0f - (1.0f - col[0]) * (1.0f - r_col[0]); 01373 scg = 1.0f - (1.0f - col[1]) * (1.0f - r_col[1]); 01374 scb = 1.0f - (1.0f - col[2]) * (1.0f - r_col[2]); 01375 01376 r_col[0] = facm*(r_col[0]) + fac*(((1.0f - r_col[0]) * col[0] * (r_col[0])) + (r_col[0] * scr)); 01377 r_col[1] = facm*(r_col[1]) + fac*(((1.0f - r_col[1]) * col[1] * (r_col[1])) + (r_col[1] * scg)); 01378 r_col[2] = facm*(r_col[2]) + fac*(((1.0f - r_col[2]) * col[2] * (r_col[2])) + (r_col[2] * scb)); 01379 } 01380 break; 01381 case MA_RAMP_LINEAR: 01382 if (col[0] > 0.5f) 01383 r_col[0] = r_col[0] + fac*(2.0f*(col[0]-0.5f)); 01384 else 01385 r_col[0] = r_col[0] + fac*(2.0f*(col[0]) - 1.0f); 01386 if (col[1] > 0.5f) 01387 r_col[1] = r_col[1] + fac*(2.0f*(col[1]-0.5f)); 01388 else 01389 r_col[1] = r_col[1] + fac*(2.0f*(col[1]) -1.0f); 01390 if (col[2] > 0.5f) 01391 r_col[2] = r_col[2] + fac*(2.0f*(col[2]-0.5f)); 01392 else 01393 r_col[2] = r_col[2] + fac*(2.0f*(col[2]) - 1.0f); 01394 break; 01395 } 01396 } 01397 01398 /* copy/paste buffer, if we had a propper py api that would be better */ 01399 static Material matcopybuf; 01400 static short matcopied= 0; 01401 01402 void clear_matcopybuf(void) 01403 { 01404 memset(&matcopybuf, 0, sizeof(Material)); 01405 matcopied= 0; 01406 } 01407 01408 void free_matcopybuf(void) 01409 { 01410 int a; 01411 01412 for(a=0; a<MAX_MTEX; a++) { 01413 if(matcopybuf.mtex[a]) { 01414 MEM_freeN(matcopybuf.mtex[a]); 01415 matcopybuf.mtex[a]= NULL; 01416 } 01417 } 01418 01419 if(matcopybuf.ramp_col) MEM_freeN(matcopybuf.ramp_col); 01420 if(matcopybuf.ramp_spec) MEM_freeN(matcopybuf.ramp_spec); 01421 01422 matcopybuf.ramp_col= NULL; 01423 matcopybuf.ramp_spec= NULL; 01424 01425 if(matcopybuf.nodetree) { 01426 ntreeFreeTree(matcopybuf.nodetree); 01427 MEM_freeN(matcopybuf.nodetree); 01428 matcopybuf.nodetree= NULL; 01429 } 01430 01431 matcopied= 0; 01432 } 01433 01434 void copy_matcopybuf(Material *ma) 01435 { 01436 int a; 01437 MTex *mtex; 01438 01439 if(matcopied) 01440 free_matcopybuf(); 01441 01442 memcpy(&matcopybuf, ma, sizeof(Material)); 01443 if(matcopybuf.ramp_col) matcopybuf.ramp_col= MEM_dupallocN(matcopybuf.ramp_col); 01444 if(matcopybuf.ramp_spec) matcopybuf.ramp_spec= MEM_dupallocN(matcopybuf.ramp_spec); 01445 01446 for(a=0; a<MAX_MTEX; a++) { 01447 mtex= matcopybuf.mtex[a]; 01448 if(mtex) { 01449 matcopybuf.mtex[a]= MEM_dupallocN(mtex); 01450 } 01451 } 01452 matcopybuf.nodetree= ntreeCopyTree(ma->nodetree); 01453 matcopybuf.preview= NULL; 01454 matcopybuf.gpumaterial.first= matcopybuf.gpumaterial.last= NULL; 01455 matcopied= 1; 01456 } 01457 01458 void paste_matcopybuf(Material *ma) 01459 { 01460 int a; 01461 MTex *mtex; 01462 ID id; 01463 01464 if(matcopied==0) 01465 return; 01466 /* free current mat */ 01467 if(ma->ramp_col) MEM_freeN(ma->ramp_col); 01468 if(ma->ramp_spec) MEM_freeN(ma->ramp_spec); 01469 for(a=0; a<MAX_MTEX; a++) { 01470 mtex= ma->mtex[a]; 01471 if(mtex && mtex->tex) mtex->tex->id.us--; 01472 if(mtex) MEM_freeN(mtex); 01473 } 01474 01475 if(ma->nodetree) { 01476 ntreeFreeTree(ma->nodetree); 01477 MEM_freeN(ma->nodetree); 01478 } 01479 01480 GPU_material_free(ma); 01481 01482 id= (ma->id); 01483 memcpy(ma, &matcopybuf, sizeof(Material)); 01484 (ma->id)= id; 01485 01486 if(matcopybuf.ramp_col) ma->ramp_col= MEM_dupallocN(matcopybuf.ramp_col); 01487 if(matcopybuf.ramp_spec) ma->ramp_spec= MEM_dupallocN(matcopybuf.ramp_spec); 01488 01489 for(a=0; a<MAX_MTEX; a++) { 01490 mtex= ma->mtex[a]; 01491 if(mtex) { 01492 ma->mtex[a]= MEM_dupallocN(mtex); 01493 if(mtex->tex) id_us_plus((ID *)mtex->tex); 01494 } 01495 } 01496 01497 ma->nodetree= ntreeCopyTree(matcopybuf.nodetree); 01498 } 01499 01500 01501 /*********************** texface to material convert functions **********************/ 01502 /* encode all the TF information into a single int */ 01503 static int encode_tfaceflag(MTFace *tf, int convertall) 01504 { 01505 /* calculate the flag */ 01506 int flag = tf->mode; 01507 01508 /* options that change the material offline render */ 01509 if (!convertall) { 01510 flag &= ~TF_OBCOL; 01511 } 01512 01513 /* clean flags that are not being converted */ 01514 flag &= ~TF_TEX; 01515 flag &= ~TF_SHAREDVERT; 01516 flag &= ~TF_SHAREDCOL; 01517 flag &= ~TF_CONVERTED; 01518 01519 /* light tface flag is ignored in GLSL mode */ 01520 flag &= ~TF_LIGHT; 01521 01522 /* 15 is how big the flag can be - hardcoded here and in decode_tfaceflag() */ 01523 flag |= tf->transp << 15; 01524 01525 /* increase 1 so flag 0 is different than no flag yet */ 01526 return flag + 1; 01527 } 01528 01529 /* set the material options based in the tface flag */ 01530 static void decode_tfaceflag(Material *ma, int flag, int convertall) 01531 { 01532 int alphablend; 01533 GameSettings *game= &ma->game; 01534 01535 /* flag is shifted in 1 to make 0 != no flag yet (see encode_tfaceflag) */ 01536 flag -= 1; 01537 01538 alphablend = flag >> 15; //encoded in the encode_tfaceflag function 01539 (*game).flag = 0; 01540 01541 /* General Material Options */ 01542 if ((flag & TF_DYNAMIC)==0) (*game).flag |= GEMAT_NOPHYSICS; 01543 01544 /* Material Offline Rendering Properties */ 01545 if (convertall) { 01546 if (flag & TF_OBCOL) ma->shade_flag |= MA_OBCOLOR; 01547 } 01548 01549 /* Special Face Properties */ 01550 if ((flag & TF_TWOSIDE)==0) (*game).flag |= GEMAT_BACKCULL; 01551 if (flag & TF_INVISIBLE)(*game).flag |= GEMAT_INVISIBLE; 01552 if (flag & TF_BMFONT) (*game).flag |= GEMAT_TEXT; 01553 01554 /* Face Orientation */ 01555 if (flag & TF_BILLBOARD) (*game).face_orientation |= GEMAT_HALO; 01556 else if (flag & TF_BILLBOARD2) (*game).face_orientation |= GEMAT_BILLBOARD; 01557 else if (flag & TF_SHADOW) (*game).face_orientation |= GEMAT_SHADOW; 01558 01559 /* Alpha Blend */ 01560 if (flag & TF_ALPHASORT && ELEM(alphablend, TF_ALPHA, TF_ADD)) (*game).alpha_blend = GEMAT_ALPHA_SORT; 01561 else if (alphablend & TF_ALPHA) (*game).alpha_blend = GEMAT_ALPHA; 01562 else if (alphablend & TF_ADD) (*game).alpha_blend = GEMAT_ADD; 01563 else if (alphablend & TF_CLIP) (*game).alpha_blend = GEMAT_CLIP; 01564 } 01565 01566 /* boolean check to see if the mesh needs a material */ 01567 static int check_tfaceneedmaterial(int flag) 01568 { 01569 // check if the flags we have are not deprecated != than default material options 01570 // also if only flags are visible and collision see if all objects using this mesh have this option in physics 01571 01572 /* flag is shifted in 1 to make 0 != no flag yet (see encode_tfaceflag) */ 01573 flag -=1; 01574 01575 // deprecated flags 01576 flag &= ~TF_OBCOL; 01577 flag &= ~TF_SHAREDVERT; 01578 flag &= ~TF_SHAREDCOL; 01579 01580 /* light tface flag is ignored in GLSL mode */ 01581 flag &= ~TF_LIGHT; 01582 01583 // automatic detected if tex image has alpha 01584 flag &= ~(TF_ALPHA << 15); 01585 // automatic detected if using texture 01586 flag &= ~TF_TEX; 01587 01588 // settings for the default NoMaterial 01589 if (flag == TF_DYNAMIC) 01590 return 0; 01591 01592 else 01593 return 1; 01594 } 01595 01596 /* return number of digits of an integer */ 01597 // XXX to be optmized or replaced by an equivalent blender internal function 01598 static int integer_getdigits(int number) 01599 { 01600 int i=0; 01601 if (number == 0) return 1; 01602 01603 while (number != 0){ 01604 number = (int)(number/10); 01605 i++; 01606 } 01607 return i; 01608 } 01609 01610 static void calculate_tface_materialname(char *matname, char *newname, int flag) 01611 { 01612 // if flag has only light and collision and material matches those values 01613 // you can do strcpy(name, mat_name); 01614 // otherwise do: 01615 int digits = integer_getdigits(flag); 01616 /* clamp the old name, remove the MA prefix and add the .TF.flag suffix 01617 e.g. matname = "MALoooooooooooooongName"; newname = "Loooooooooooooon.TF.2" */ 01618 BLI_snprintf(newname, MAX_ID_NAME, "%.*s.TF.%0*d", MAX_ID_NAME-(digits+5), matname, digits, flag); 01619 } 01620 01621 /* returns -1 if no match */ 01622 static short mesh_getmaterialnumber(Mesh *me, Material *ma) 01623 { 01624 short a; 01625 01626 for (a=0; a<me->totcol; a++) { 01627 if (me->mat[a] == ma) { 01628 return a; 01629 } 01630 } 01631 01632 return -1; 01633 } 01634 01635 /* append material */ 01636 static short mesh_addmaterial(Mesh *me, Material *ma) 01637 { 01638 material_append_id(&me->id, NULL); 01639 me->mat[me->totcol-1]= ma; 01640 01641 id_us_plus(&ma->id); 01642 01643 return me->totcol-1; 01644 } 01645 01646 static void set_facetexture_flags(Material *ma, Image *image) 01647 { 01648 if(image) { 01649 ma->mode |= MA_FACETEXTURE; 01650 /* we could check if the texture has alpha, but then more meshes sharing the same 01651 * material may need it. Let's make it simple. */ 01652 if(BKE_image_has_alpha(image)) 01653 ma->mode |= MA_FACETEXTURE_ALPHA; 01654 } 01655 } 01656 01657 /* returns material number */ 01658 static short convert_tfacenomaterial(Main *main, Mesh *me, MTFace *tf, int flag) 01659 { 01660 Material *ma; 01661 char idname[MAX_ID_NAME]; 01662 short mat_nr= -1; 01663 01664 /* new material, the name uses the flag*/ 01665 BLI_snprintf(idname, sizeof(idname), "MAMaterial.TF.%0*d", integer_getdigits(flag), flag); 01666 01667 if ((ma= BLI_findstring(&main->mat, idname+2, offsetof(ID, name)+2))) { 01668 mat_nr= mesh_getmaterialnumber(me, ma); 01669 /* assign the material to the mesh */ 01670 if(mat_nr == -1) mat_nr= mesh_addmaterial(me, ma); 01671 01672 /* if needed set "Face Textures [Alpha]" Material options */ 01673 set_facetexture_flags(ma, tf->tpage); 01674 } 01675 /* create a new material */ 01676 else { 01677 ma= add_material(idname+2); 01678 01679 if(ma){ 01680 printf("TexFace Convert: Material \"%s\" created.\n", idname+2); 01681 mat_nr= mesh_addmaterial(me, ma); 01682 01683 /* if needed set "Face Textures [Alpha]" Material options */ 01684 set_facetexture_flags(ma, tf->tpage); 01685 01686 decode_tfaceflag(ma, flag, 1); 01687 // the final decoding will happen after, outside the main loop 01688 // for now store the flag into the material and change light/tex/collision 01689 // store the flag as a negative number 01690 ma->game.flag = -flag; 01691 id_us_min((ID *)ma); 01692 } 01693 else printf("Error: Unable to create Material \"%s\" for Mesh \"%s\".", idname+2, me->id.name+2); 01694 } 01695 01696 /* set as converted, no need to go bad to this face */ 01697 tf->mode |= TF_CONVERTED; 01698 return mat_nr; 01699 } 01700 01701 /* Function to fully convert materials */ 01702 static void convert_tfacematerial(Main *main, Material *ma) 01703 { 01704 Mesh *me; 01705 Material *mat_new; 01706 MFace *mf; 01707 MTFace *tf; 01708 int flag, index; 01709 int a; 01710 short mat_nr; 01711 CustomDataLayer *cdl; 01712 char idname[MAX_ID_NAME]; 01713 01714 for(me=main->mesh.first; me; me=me->id.next){ 01715 /* check if this mesh uses this material */ 01716 for(a=0;a<me->totcol;a++) 01717 if(me->mat[a] == ma) break; 01718 01719 /* no material found */ 01720 if (a == me->totcol) continue; 01721 01722 /* get the active tface layer */ 01723 index= CustomData_get_active_layer_index(&me->fdata, CD_MTFACE); 01724 cdl= (index == -1)? NULL: &me->fdata.layers[index]; 01725 if (!cdl) continue; 01726 01727 /* loop over all the faces and stop at the ones that use the material*/ 01728 for(a=0, mf=me->mface; a<me->totface; a++, mf++) { 01729 if(me->mat[mf->mat_nr] != ma) continue; 01730 01731 /* texface data for this face */ 01732 tf = ((MTFace*)cdl->data) + a; 01733 flag = encode_tfaceflag(tf, 1); 01734 01735 /* the name of the new material */ 01736 calculate_tface_materialname(ma->id.name, (char *)&idname, flag); 01737 01738 if ((mat_new= BLI_findstring(&main->mat, idname+2, offsetof(ID, name)+2))) { 01739 /* material already existent, see if the mesh has it */ 01740 mat_nr = mesh_getmaterialnumber(me, mat_new); 01741 /* material is not in the mesh, add it */ 01742 if(mat_nr == -1) mat_nr= mesh_addmaterial(me, mat_new); 01743 } 01744 /* create a new material */ 01745 else { 01746 mat_new=copy_material(ma); 01747 if(mat_new){ 01748 /* rename the material*/ 01749 strcpy(mat_new->id.name, idname); 01750 id_us_min((ID *)mat_new); 01751 01752 mat_nr= mesh_addmaterial(me, mat_new); 01753 decode_tfaceflag(mat_new, flag, 1); 01754 } 01755 else { 01756 printf("Error: Unable to create Material \"%s\" for Mesh \"%s.", idname+2, me->id.name+2); 01757 mat_nr = mf->mat_nr; 01758 continue; 01759 } 01760 } 01761 01762 /* if the material has a texture but no texture channel 01763 * set "Face Textures [Alpha]" Material options 01764 * actually we need to run it always, because of old behavior 01765 * of using face texture if any texture channel was present (multitex) */ 01766 //if((!mat_new->mtex[0]) && (!mat_new->mtex[0]->tex)) 01767 set_facetexture_flags(mat_new, tf->tpage); 01768 01769 /* set the material number to the face*/ 01770 mf->mat_nr = mat_nr; 01771 } 01772 /* remove material from mesh */ 01773 for(a=0;a<me->totcol;) 01774 if(me->mat[a] == ma) material_pop_id(&me->id, a, 1);else a++; 01775 } 01776 } 01777 01778 01779 #define MAT_BGE_DISPUTED -99999 01780 01781 int do_version_tface(Main *main, int fileload) 01782 { 01783 Mesh *me; 01784 Material *ma; 01785 MFace *mf; 01786 MTFace *tf; 01787 CustomDataLayer *cdl; 01788 int a; 01789 int flag; 01790 int index; 01791 01792 /* sometimes mesh has no materials but will need a new one. In those 01793 * cases we need to ignore the mf->mat_nr and only look at the face 01794 * mode because it can be zero as uninitialized or the 1st created material 01795 */ 01796 int nomaterialslots; 01797 01798 /* alert to user to check the console */ 01799 int nowarning = 1; 01800 01801 /* mark all the materials to conversion with a flag 01802 * if there is tface create a complete flag for that storing in flag 01803 * if there is tface and flag > 0: creates a new flag based on this face 01804 * if flags are different set flag to -1 01805 */ 01806 01807 /* 1st part: marking mesh materials to update */ 01808 for(me=main->mesh.first; me; me=me->id.next){ 01809 if (me->id.lib) continue; 01810 01811 /* get the active tface layer */ 01812 index= CustomData_get_active_layer_index(&me->fdata, CD_MTFACE); 01813 cdl= (index == -1)? NULL: &me->fdata.layers[index]; 01814 if (!cdl) continue; 01815 01816 nomaterialslots = (me->totcol==0?1:0); 01817 01818 /* loop over all the faces*/ 01819 for(a=0, mf=me->mface; a<me->totface; a++, mf++) { 01820 /* texface data for this face */ 01821 tf = ((MTFace*)cdl->data) + a; 01822 01823 /* conversion should happen only once */ 01824 if (fileload) 01825 tf->mode &= ~TF_CONVERTED; 01826 else { 01827 if((tf->mode & TF_CONVERTED)) continue; 01828 else tf->mode |= TF_CONVERTED; 01829 } 01830 01831 /* no material slots */ 01832 if(nomaterialslots) { 01833 flag = encode_tfaceflag(tf, 1); 01834 01835 /* create/find a new material and assign to the face */ 01836 if (check_tfaceneedmaterial(flag)) { 01837 mf->mat_nr= convert_tfacenomaterial(main, me, tf, flag); 01838 } 01839 /* else mark them as no-material to be reverted to 0 later */ 01840 else { 01841 mf->mat_nr = -1; 01842 } 01843 } 01844 else if(mf->mat_nr < me->totcol) { 01845 ma= me->mat[mf->mat_nr]; 01846 01847 /* no material create one if necessary */ 01848 if(!ma) { 01849 /* find a new material and assign to the face */ 01850 flag = encode_tfaceflag(tf, 1); 01851 01852 /* create/find a new material and assign to the face */ 01853 if (check_tfaceneedmaterial(flag)) 01854 mf->mat_nr= convert_tfacenomaterial(main, me, tf, flag); 01855 01856 continue; 01857 } 01858 01859 /* we can't read from this if it comes from a library, 01860 * at doversion time: direct_link might not have happened on it, 01861 * so ma->mtex is not pointing to valid memory yet. 01862 * later we could, but it's better not */ 01863 else if(ma->id.lib) 01864 continue; 01865 01866 /* material already marked as disputed */ 01867 else if(ma->game.flag == MAT_BGE_DISPUTED) 01868 continue; 01869 01870 /* found a material */ 01871 else { 01872 flag = encode_tfaceflag(tf, ((fileload)?0:1)); 01873 01874 /* first time changing this material */ 01875 if (ma->game.flag == 0) 01876 ma->game.flag= -flag; 01877 01878 /* mark material as disputed */ 01879 else if (ma->game.flag != -flag) { 01880 ma->game.flag = MAT_BGE_DISPUTED; 01881 continue; 01882 } 01883 01884 /* material ok so far */ 01885 else { 01886 ma->game.flag = -flag; 01887 01888 /* some people uses multitexture with TexFace by creating a texture 01889 * channel which not neccessarly the tf->tpage image. But the game engine 01890 * was enabling it. Now it's required to set "Face Texture [Alpha] in the 01891 * material settings. */ 01892 if(!fileload) 01893 set_facetexture_flags(ma, tf->tpage); 01894 } 01895 } 01896 } 01897 else 01898 continue; 01899 } 01900 01901 /* if we didn't have material slot and now we do, we need to 01902 * make sure the materials are correct */ 01903 if(nomaterialslots) { 01904 if (me->totcol>0) { 01905 for(a=0, mf=me->mface; a<me->totface; a++, mf++) { 01906 if (mf->mat_nr == -1) { 01907 /* texface data for this face */ 01908 tf = ((MTFace*)cdl->data) + a; 01909 mf->mat_nr= convert_tfacenomaterial(main, me, tf, encode_tfaceflag(tf, 1)); 01910 } 01911 } 01912 } 01913 else { 01914 for(a=0, mf=me->mface; a<me->totface; a++, mf++) { 01915 mf->mat_nr=0; 01916 } 01917 } 01918 } 01919 01920 } 01921 01922 /* 2nd part - conversion */ 01923 /* skip library files */ 01924 01925 /* we shouldn't loop through the materials created in the loop. make the loop stop at its original length) */ 01926 for (ma= main->mat.first, a=0; ma; ma= ma->id.next, a++) { 01927 if (ma->id.lib) continue; 01928 01929 /* disputed material */ 01930 if (ma->game.flag == MAT_BGE_DISPUTED) { 01931 ma->game.flag = 0; 01932 if (fileload) { 01933 printf("Warning: material \"%s\" skipped - to convert old game texface to material go to the Help menu.\n", ma->id.name+2); 01934 nowarning = 0; 01935 } 01936 else 01937 convert_tfacematerial(main, ma); 01938 continue; 01939 } 01940 01941 /* no conflicts in this material - 90% of cases 01942 * convert from tface system to material */ 01943 else if (ma->game.flag < 0) { 01944 decode_tfaceflag(ma, -(ma->game.flag), 1); 01945 01946 /* material is good make sure all faces using 01947 * this material are set to converted */ 01948 if (fileload) { 01949 for(me=main->mesh.first; me; me=me->id.next){ 01950 /* check if this mesh uses this material */ 01951 for(a=0;a<me->totcol;a++) 01952 if(me->mat[a] == ma) break; 01953 01954 /* no material found */ 01955 if (a == me->totcol) continue; 01956 01957 /* get the active tface layer */ 01958 index= CustomData_get_active_layer_index(&me->fdata, CD_MTFACE); 01959 cdl= (index == -1)? NULL: &me->fdata.layers[index]; 01960 if (!cdl) continue; 01961 01962 /* loop over all the faces and stop at the ones that use the material*/ 01963 for (a=0, mf=me->mface; a<me->totface; a++, mf++) { 01964 if (me->mat[mf->mat_nr] == ma) { 01965 /* texface data for this face */ 01966 tf = ((MTFace*)cdl->data) + a; 01967 tf->mode |= TF_CONVERTED; 01968 } 01969 } 01970 } 01971 } 01972 } 01973 /* material is not used by faces with texface 01974 * set the default flag - do it only once */ 01975 else 01976 if (fileload) 01977 ma->game.flag = GEMAT_BACKCULL; 01978 } 01979 01980 return nowarning; 01981 } 01982