5 * $Id: material.c 12708 2007-11-28 18:43:09Z ton $
7 * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version. The Blender
13 * Foundation also sells licenses for use in proprietary software under
14 * the Blender License. See http://www.blender.org/BL/ for information
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software Foundation,
24 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
27 * All rights reserved.
29 * The Original Code is: all of this file.
31 * Contributor(s): none yet.
33 * ***** END GPL/BL DUAL LICENSE BLOCK *****
39 #include "MEM_guardedalloc.h"
41 #include "DNA_curve_types.h"
42 #include "DNA_material_types.h"
43 #include "DNA_mesh_types.h"
44 #include "DNA_meta_types.h"
45 #include "DNA_node_types.h"
46 #include "DNA_object_types.h"
47 #include "DNA_scene_types.h"
48 #include "DNA_texture_types.h"
50 #include "BLI_blenlib.h"
51 #include "BLI_arithb.h"
53 #include "BKE_bad_level_calls.h"
54 #include "BKE_blender.h"
55 #include "BKE_displist.h"
56 #include "BKE_global.h"
57 #include "BKE_icons.h"
58 #include "BKE_library.h"
60 #include "BKE_material.h"
63 #include "BKE_utildefines.h"
65 #include "BPY_extern.h"
67 /* used in UI and render */
70 /* called on startup, creator.c */
71 void init_def_material(void)
73 init_material(&defmaterial
);
76 /* not material itself */
77 void free_material(Material
*ma
)
82 BPY_free_scriptlink(&ma
->scriptlink
);
84 for(a
=0; a
<MAX_MTEX
; a
++) {
86 if(mtex
&& mtex
->tex
) mtex
->tex
->id
.us
--;
87 if(mtex
) MEM_freeN(mtex
);
90 if(ma
->ramp_col
) MEM_freeN(ma
->ramp_col
);
91 if(ma
->ramp_spec
) MEM_freeN(ma
->ramp_spec
);
93 BKE_icon_delete((struct ID
*)ma
);
96 /* is no lib link block, but material extension */
98 ntreeFreeTree(ma
->nodetree
);
99 MEM_freeN(ma
->nodetree
);
103 void init_material(Material
*ma
)
105 ma
->r
= ma
->g
= ma
->b
= ma
->ref
= 0.8;
106 ma
->specr
= ma
->specg
= ma
->specb
= 1.0;
107 ma
->mirr
= ma
->mirg
= ma
->mirb
= 1.0;
111 ma
->spec
= ma
->hasize
= 0.5;
113 ma
->starc
= ma
->ringc
= 4;
116 ma
->flaresize
= ma
->subsize
= 1.0;
129 ma
->strand_sta
= ma
->strand_end
= 1.0f
;
133 ma
->ray_depth_tra
= 2;
134 ma
->fresnel_mir
= 0.0;
135 ma
->fresnel_tra
= 0.0;
136 ma
->fresnel_tra_i
= 1.25;
137 ma
->fresnel_mir_i
= 1.25;
140 ma
->shad_alpha
= 1.0f
;
142 ma
->gloss_mir
= ma
->gloss_tra
= 1.0;
143 ma
->samp_gloss_mir
= ma
->samp_gloss_tra
= 18;
144 ma
->adapt_thresh_mir
= ma
->adapt_thresh_tra
= 0.005;
146 ma
->fadeto_mir
= MA_RAYMIR_FADETOSKY
;
148 ma
->rampfac_col
= 1.0;
149 ma
->rampfac_spec
= 1.0;
150 ma
->pr_lamp
= 3; /* two lamps, is bits */
151 ma
->pr_type
= MA_SPHERE
;
153 ma
->sss_radius
[0]= 1.0f
;
154 ma
->sss_radius
[1]= 1.0f
;
155 ma
->sss_radius
[2]= 1.0f
;
156 ma
->sss_col
[0]= 0.8f
;
157 ma
->sss_col
[1]= 0.8f
;
158 ma
->sss_col
[2]= 0.8f
;
159 ma
->sss_error
= 0.05f
;
162 ma
->sss_colfac
= 1.0f
;
163 ma
->sss_texfac
= 0.0f
;
167 ma
->mode
= MA_TRACEBLE
|MA_SHADBUF
|MA_SHADOW
|MA_RADIO
|MA_RAYBIAS
|MA_TANGENT_STR
;
170 Material
*add_material(char *name
)
174 ma
= alloc_libblock(&G
.main
->mat
, ID_MA
, name
);
181 Material
*copy_material(Material
*ma
)
186 man
= copy_libblock(ma
);
188 id_us_plus((ID
*)man
->ipo
);
189 id_us_plus((ID
*)man
->group
);
192 for(a
=0; a
<MAX_MTEX
; a
++) {
194 man
->mtex
[a
]= MEM_mallocN(sizeof(MTex
), "copymaterial");
195 memcpy(man
->mtex
[a
], ma
->mtex
[a
], sizeof(MTex
));
196 id_us_plus((ID
*)man
->mtex
[a
]->tex
);
200 BPY_copy_scriptlink(&ma
->scriptlink
);
202 if(ma
->ramp_col
) man
->ramp_col
= MEM_dupallocN(ma
->ramp_col
);
203 if(ma
->ramp_spec
) man
->ramp_spec
= MEM_dupallocN(ma
->ramp_spec
);
206 man
->nodetree
= ntreeCopyTree(ma
->nodetree
, 0); /* 0 == full new tree */
212 void make_local_material(Material
*ma
)
219 int a
, local
=0, lib
=0;
221 /* - only lib users: do nothing
222 * - only local users: set flag
226 if(ma
->id
.lib
==0) return;
229 ma
->id
.flag
= LIB_LOCAL
;
230 new_id(0, (ID
*)ma
, 0);
231 for(a
=0; a
<MAX_MTEX
; a
++) {
232 if(ma
->mtex
[a
]) id_lib_extern((ID
*)ma
->mtex
[a
]->tex
);
239 ob
= G
.main
->object
.first
;
242 for(a
=0; a
<ob
->totcol
; a
++) {
244 if(ob
->id
.lib
) lib
= 1;
252 me
= G
.main
->mesh
.first
;
255 for(a
=0; a
<me
->totcol
; a
++) {
257 if(me
->id
.lib
) lib
= 1;
265 cu
= G
.main
->curve
.first
;
268 for(a
=0; a
<cu
->totcol
; a
++) {
270 if(cu
->id
.lib
) lib
= 1;
278 mb
= G
.main
->mball
.first
;
281 for(a
=0; a
<mb
->totcol
; a
++) {
283 if(mb
->id
.lib
) lib
= 1;
291 if(local
&& lib
==0) {
293 ma
->id
.flag
= LIB_LOCAL
;
295 for(a
=0; a
<MAX_MTEX
; a
++) {
296 if(ma
->mtex
[a
]) id_lib_extern((ID
*)ma
->mtex
[a
]->tex
);
299 new_id(0, (ID
*)ma
, 0);
301 else if(local
&& lib
) {
303 man
= copy_material(ma
);
307 ob
= G
.main
->object
.first
;
310 for(a
=0; a
<ob
->totcol
; a
++) {
323 me
= G
.main
->mesh
.first
;
326 for(a
=0; a
<me
->totcol
; a
++) {
339 cu
= G
.main
->curve
.first
;
342 for(a
=0; a
<cu
->totcol
; a
++) {
355 mb
= G
.main
->mball
.first
;
358 for(a
=0; a
<mb
->totcol
; a
++) {
373 Material
***give_matarar(Object
*ob
)
379 if(ob
->type
==OB_MESH
) {
383 else if ELEM3(ob
->type
, OB_CURVE
, OB_FONT
, OB_SURF
) {
387 else if(ob
->type
==OB_MBALL
) {
394 short *give_totcolp(Object
*ob
)
400 if(ob
->type
==OB_MESH
) {
402 return &(me
->totcol
);
404 else if ELEM3(ob
->type
, OB_CURVE
, OB_FONT
, OB_SURF
) {
406 return &(cu
->totcol
);
408 else if(ob
->type
==OB_MBALL
) {
410 return &(mb
->totcol
);
415 Material
*give_current_material(Object
*ob
, int act
)
417 Material
***matarar
, *ma
;
420 if(ob
==NULL
) return NULL
;
422 /* if object cannot have material, totcolp==NULL */
423 totcolp
= give_totcolp(ob
);
424 if(totcolp
==NULL
|| ob
->totcol
==0) return NULL
;
426 if(act
>ob
->totcol
) act
= ob
->totcol
;
427 else if(act
<=0) act
= 1;
429 if( BTST(ob
->colbits
, act
-1) ) { /* in object */
434 /* check for inconsistancy */
435 if(*totcolp
< ob
->totcol
)
436 ob
->totcol
= *totcolp
;
437 if(act
>ob
->totcol
) act
= ob
->totcol
;
439 matarar
= give_matarar(ob
);
441 if(matarar
&& *matarar
) ma
= (*matarar
)[act
-1];
449 ID
*material_from(Object
*ob
, int act
)
454 if(ob
->totcol
==0) return ob
->data
;
457 if( BTST(ob
->colbits
, act
-1) ) return (ID
*)ob
;
458 else return ob
->data
;
461 /* GS reads the memory pointed at in a specific ordering. There are,
462 * however two definitions for it. I have jotted them down here, both,
463 * but I think the first one is actually used. The thing is that
464 * big-endian systems might read this the wrong way round. OTOH, we
465 * constructed the IDs that are read out with this macro explicitly as
466 * well. I expect we'll sort it out soon... */
469 #define GS(a) (*((short *)(a)))
471 /* from misc_util: flip the bytes from x */
472 /* #define GS(x) (((unsigned char *)(x))[0] << 8 | ((unsigned char *)(x))[1]) */
474 void test_object_materials(ID
*id
)
476 /* make the ob mat-array same size as 'ob->data' mat-array */
486 if( GS(id
->name
)==ID_ME
) {
490 else if( GS(id
->name
)==ID_CU
) {
494 else if( GS(id
->name
)==ID_MB
) {
500 ob
= G
.main
->object
.first
;
511 else if(ob
->totcol
<totcol
) {
512 newmatar
= MEM_callocN(sizeof(void *)*totcol
, "newmatar");
514 memcpy(newmatar
, ob
->mat
, sizeof(void *)*ob
->totcol
);
520 if(ob
->totcol
&& ob
->actcol
==0) ob
->actcol
= 1;
521 if(ob
->actcol
>ob
->totcol
) ob
->actcol
= ob
->totcol
;
528 void assign_material(Object
*ob
, Material
*ma
, int act
)
530 Material
*mao
, **matar
, ***matarar
;
533 if(act
>MAXMAT
) return;
538 totcolp
= give_totcolp(ob
);
539 matarar
= give_matarar(ob
);
541 if(totcolp
==0 || matarar
==0) return;
543 if( act
> *totcolp
) {
544 matar
= MEM_callocN(sizeof(void *)*act
, "matarray1");
546 memcpy(matar
, *matarar
, sizeof(void *)*( *totcolp
));
553 if(act
> ob
->totcol
) {
554 matar
= MEM_callocN(sizeof(void *)*act
, "matarray2");
556 memcpy(matar
, ob
->mat
, sizeof(void *)*( ob
->totcol
));
565 if( BTST(ob
->colbits
, act
-1) ) { /* in object */
567 if(mao
) mao
->id
.us
--;
571 mao
= (*matarar
)[act
-1];
572 if(mao
) mao
->id
.us
--;
573 (*matarar
)[act
-1]= ma
;
575 id_us_plus((ID
*)ma
);
576 test_object_materials(ob
->data
);
579 int find_material_index(Object
*ob
, Material
*ma
)
584 if(ma
==NULL
) return 0;
586 totcolp
= give_totcolp(ob
);
587 matarar
= give_matarar(ob
);
589 if(totcolp
==NULL
|| matarar
==NULL
) return 0;
591 for(a
=0; a
<*totcolp
; a
++)
592 if((*matarar
)[a
]==ma
)
599 void new_material_to_objectdata(Object
*ob
)
604 if(ob
->totcol
>=MAXMAT
) return;
606 ma
= give_current_material(ob
, ob
->actcol
);
608 ma
= add_material("Material");
610 ma
= copy_material(ma
);
612 ma
->id
.us
= 0; /* eeh... */
615 if( BTST(ob
->colbits
, ob
->actcol
-1) ) {
616 ob
->colbits
= BSET(ob
->colbits
, ob
->totcol
);
620 assign_material(ob
, ma
, ob
->totcol
+1);
621 ob
->actcol
= ob
->totcol
;
624 static void do_init_render_material(Material
*ma
, int r_mode
, float *amb
)
629 if(ma
->flarec
==0) ma
->flarec
= 1;
631 /* add all texcoflags from mtex, texco and mapto were cleared in advance */
632 for(a
=0; a
<MAX_MTEX
; a
++) {
634 /* separate tex switching */
635 if(ma
->septex
& (1<<a
)) continue;
638 if(mtex
&& mtex
->tex
&& mtex
->tex
->type
) {
640 ma
->texco
|= mtex
->texco
;
641 ma
->mapto
|= mtex
->mapto
;
643 if ELEM3(mtex
->tex
->type
, TEX_IMAGE
, TEX_PLUGIN
, TEX_ENVMAP
) ma
->texco
|= TEXCO_OSA
;
646 if(ma
->texco
& (TEXCO_ORCO
|TEXCO_REFL
|TEXCO_NORM
|TEXCO_STRAND
|TEXCO_STRESS
)) needuv
= 1;
647 else if(ma
->texco
& (TEXCO_GLOB
|TEXCO_UV
|TEXCO_OBJECT
|TEXCO_SPEED
)) needuv
= 1;
648 else if(ma
->texco
& (TEXCO_LAVECTOR
|TEXCO_VIEW
|TEXCO_STICKY
)) needuv
= 1;
653 if(ma
->mode
& MA_RADIO
) needuv
= 1;
655 if(ma
->mode
& (MA_VERTEXCOL
|MA_VERTEXCOLP
|MA_FACETEXTURE
)) {
657 if(r_mode
& R_OSA
) ma
->texco
|= TEXCO_OSA
; /* for texfaces */
659 if(needuv
) ma
->texco
|= NEED_UV
;
661 /* since the raytracer doesnt recalc O structs for each ray, we have to preset them all */
662 if(r_mode
& R_RAYTRACE
) {
663 if(ma
->mode
& (MA_RAYMIRROR
|MA_RAYTRANSP
|MA_SHADOW_TRA
)) {
664 ma
->texco
|= NEED_UV
|TEXCO_ORCO
|TEXCO_REFL
|TEXCO_NORM
;
665 if(r_mode
& R_OSA
) ma
->texco
|= TEXCO_OSA
;
670 ma
->ambr
= ma
->amb
*amb
[0];
671 ma
->ambg
= ma
->amb
*amb
[1];
672 ma
->ambb
= ma
->amb
*amb
[2];
674 /* will become or-ed result of all node modes */
675 ma
->mode_l
= ma
->mode
;
676 ma
->mode_l
&= ~MA_SHLESS
;
679 static void init_render_nodetree(bNodeTree
*ntree
, Material
*basemat
, int r_mode
, float *amb
)
683 for(node
=ntree
->nodes
.first
; node
; node
= node
->next
) {
685 if(GS(node
->id
->name
)==ID_MA
) {
686 Material
*ma
= (Material
*)node
->id
;
688 do_init_render_material(ma
, r_mode
, amb
);
689 basemat
->texco
|= ma
->texco
;
690 basemat
->mode_l
|= ma
->mode_l
;
693 else if(node
->type
==NODE_GROUP
)
694 init_render_nodetree((bNodeTree
*)node
->id
, basemat
, r_mode
, amb
);
697 /* parses the geom+tex nodes */
698 ntreeShaderGetTexcoMode(ntree
, r_mode
, &basemat
->texco
, &basemat
->mode_l
);
701 void init_render_material(Material
*mat
, int r_mode
, float *amb
)
704 do_init_render_material(mat
, r_mode
, amb
);
706 if(mat
->nodetree
&& mat
->use_nodes
) {
707 init_render_nodetree(mat
->nodetree
, mat
, r_mode
, amb
);
709 ntreeBeginExecTree(mat
->nodetree
); /* has internal flag to detect it only does it once */
713 void init_render_materials(int r_mode
, float *amb
)
717 /* clear these flags before going over materials, to make sure they
718 * are cleared only once, otherwise node materials contained in other
719 * node materials can go wrong */
720 for(ma
= G
.main
->mat
.first
; ma
; ma
= ma
->id
.next
) {
727 /* two steps, first initialize, then or the flags for layers */
728 for(ma
= G
.main
->mat
.first
; ma
; ma
= ma
->id
.next
) {
729 /* is_used flag comes back in convertblender.c */
730 ma
->flag
&= ~MA_IS_USED
;
732 init_render_material(ma
, r_mode
, amb
);
735 do_init_render_material(&defmaterial
, r_mode
, amb
);
738 /* only needed for nodes now */
739 void end_render_material(Material
*mat
)
741 if(mat
&& mat
->nodetree
&& mat
->use_nodes
)
742 ntreeEndExecTree(mat
->nodetree
); /* has internal flag to detect it only does it once */
745 void end_render_materials(void)
748 for(ma
= G
.main
->mat
.first
; ma
; ma
= ma
->id
.next
)
750 end_render_material(ma
);
753 static int material_in_nodetree(bNodeTree
*ntree
, Material
*mat
)
757 for(node
=ntree
->nodes
.first
; node
; node
= node
->next
) {
758 if(node
->id
&& GS(node
->id
->name
)==ID_MA
) {
759 if(node
->id
==(ID
*)mat
)
762 else if(node
->type
==NODE_GROUP
)
763 if(material_in_nodetree((bNodeTree
*)node
->id
, mat
))
770 int material_in_material(Material
*parmat
, Material
*mat
)
774 else if(parmat
->nodetree
&& parmat
->use_nodes
)
775 return material_in_nodetree(parmat
->nodetree
, mat
);
780 /* ****************** */
782 char colname_array
[125][20]= {
783 "Black","DarkRed","HalveRed","Red","Red",
784 "DarkGreen","DarkOlive","Brown","Chocolate","OrangeRed",
785 "HalveGreen","GreenOlive","DryOlive","Goldenrod","DarkOrange",
786 "LightGreen","Chartreuse","YellowGreen","Yellow","Gold",
787 "Green","LawnGreen","GreenYellow","LightOlive","Yellow",
788 "DarkBlue","DarkPurple","HotPink","VioletPink","RedPink",
789 "SlateGray","DarkGrey","PalePurple","IndianRed","Tomato",
790 "SeaGreen","PaleGreen","GreenKhaki","LightBrown","LightSalmon",
791 "SpringGreen","PaleGreen","MediumOlive","YellowBrown","LightGold",
792 "LightGreen","LightGreen","LightGreen","GreenYellow","PaleYellow",
793 "HalveBlue","DarkSky","HalveMagenta","VioletRed","DeepPink",
794 "SteelBlue","SkyBlue","Orchid","LightHotPink","HotPink",
795 "SeaGreen","SlateGray","MediumGrey","Burlywood","LightPink",
796 "SpringGreen","Aquamarine","PaleGreen","Khaki","PaleOrange",
797 "SpringGreen","SeaGreen","PaleGreen","PaleWhite","YellowWhite",
798 "LightBlue","Purple","MediumOrchid","Magenta","Magenta",
799 "RoyalBlue","SlateBlue","MediumOrchid","Orchid","Magenta",
800 "DeepSkyBlue","LightSteelBlue","LightSkyBlue","Violet","LightPink",
801 "Cyan","DarkTurquoise","SkyBlue","Grey","Snow",
802 "Mint","Mint","Aquamarine","MintCream","Ivory",
803 "Blue","Blue","DarkMagenta","DarkOrchid","Magenta",
804 "SkyBlue","RoyalBlue","LightSlateBlue","MediumOrchid","Magenta",
805 "DodgerBlue","SteelBlue","MediumPurple","PalePurple","Plum",
806 "DeepSkyBlue","PaleBlue","LightSkyBlue","PalePurple","Thistle",
807 "Cyan","ColdBlue","PaleTurquoise","GhostWhite","White"
810 void automatname(Material
*ma
)
816 if(ma
->mode
& MA_SHLESS
) ref
= 1.0;
819 r
= (int)(4.99*(ref
*ma
->r
));
820 g
= (int)(4.99*(ref
*ma
->g
));
821 b
= (int)(4.99*(ref
*ma
->b
));
824 new_id(&G
.main
->mat
, (ID
*)ma
, colname_array
[nr
]);
829 void delete_material_index()
831 Material
*mao
, ***matarar
;
839 error("Unable to perform function in EditMode");
842 ob
= ((G
.scene
->basact
)? (G
.scene
->basact
->object
) : 0) ;
843 if(ob
==0 || ob
->totcol
==0) return;
845 /* take a mesh/curve/mball as starting point, remove 1 index,
846 * AND with all objects that share the ob->data
848 * after that check indices in mesh/curve/mball!!!
851 totcolp
= give_totcolp(ob
);
852 matarar
= give_matarar(ob
);
854 /* we delete the actcol */
856 mao
= (*matarar
)[ob
->actcol
-1];
857 if(mao
) mao
->id
.us
--;
860 for(a
=ob
->actcol
; a
<ob
->totcol
; a
++) {
861 (*matarar
)[a
-1]= (*matarar
)[a
];
871 obt
= G
.main
->object
.first
;
874 if(obt
->data
==ob
->data
) {
876 /* WATCH IT: do not use actcol from ob or from obt (can become zero) */
877 mao
= obt
->mat
[actcol
-1];
878 if(mao
) mao
->id
.us
--;
880 for(a
=actcol
; a
<obt
->totcol
; a
++) obt
->mat
[a
-1]= obt
->mat
[a
];
882 if(obt
->actcol
> obt
->totcol
) obt
->actcol
= obt
->totcol
;
892 /* check indices from mesh */
894 if(ob
->type
==OB_MESH
) {
895 Mesh
*me
= get_mesh(ob
);
896 mesh_delete_material_index(me
, actcol
-1);
897 freedisplist(&ob
->disp
);
899 else if ELEM(ob
->type
, OB_CURVE
, OB_SURF
) {
904 if(nu
->mat_nr
&& nu
->mat_nr
>=actcol
-1) {
906 if (ob
->type
== OB_CURVE
) nu
->charidx
--;
910 freedisplist(&ob
->disp
);
915 /* r g b = current value, col = new value, fac==0 is no change */
916 /* if g==NULL, it only does r channel */
917 void ramp_blend(int type
, float *r
, float *g
, float *b
, float fac
, float *col
)
919 float tmp
, facm
= 1.0-fac
;
923 *r
= facm
*(*r
) + fac
*col
[0];
925 *g
= facm
*(*g
) + fac
*col
[1];
926 *b
= facm
*(*b
) + fac
*col
[2];
937 *r
*= (facm
+ fac
*col
[0]);
939 *g
*= (facm
+ fac
*col
[1]);
940 *b
*= (facm
+ fac
*col
[2]);
944 *r
= 1.0 - (facm
+ fac
*(1.0 - col
[0])) * (1.0 - *r
);
946 *g
= 1.0 - (facm
+ fac
*(1.0 - col
[1])) * (1.0 - *g
);
947 *b
= 1.0 - (facm
+ fac
*(1.0 - col
[2])) * (1.0 - *b
);
950 case MA_RAMP_OVERLAY
:
952 *r
*= (facm
+ 2.0f
*fac
*col
[0]);
954 *r
= 1.0 - (facm
+ 2.0f
*fac
*(1.0 - col
[0])) * (1.0 - *r
);
957 *g
*= (facm
+ 2.0f
*fac
*col
[1]);
959 *g
= 1.0 - (facm
+ 2.0f
*fac
*(1.0 - col
[1])) * (1.0 - *g
);
961 *b
*= (facm
+ 2.0f
*fac
*col
[2]);
963 *b
= 1.0 - (facm
+ 2.0f
*fac
*(1.0 - col
[2])) * (1.0 - *b
);
975 *r
= facm
*(*r
) + fac
*(*r
)/col
[0];
978 *g
= facm
*(*g
) + fac
*(*g
)/col
[1];
980 *b
= facm
*(*b
) + fac
*(*b
)/col
[2];
984 *r
= facm
*(*r
) + fac
*fabs(*r
-col
[0]);
986 *g
= facm
*(*g
) + fac
*fabs(*g
-col
[1]);
987 *b
= facm
*(*b
) + fac
*fabs(*b
-col
[2]);
992 if(tmp
< *r
) *r
= tmp
;
995 if(tmp
< *g
) *g
= tmp
;
997 if(tmp
< *b
) *b
= tmp
;
1002 if(tmp
> *r
) *r
= tmp
;
1005 if(tmp
> *g
) *g
= tmp
;
1007 if(tmp
> *b
) *b
= tmp
;
1014 tmp
= 1.0 - fac
*col
[0];
1017 else if ((tmp
= (*r
) / tmp
)> 1.0)
1024 tmp
= 1.0 - fac
*col
[1];
1027 else if ((tmp
= (*g
) / tmp
) > 1.0 )
1033 tmp
= 1.0 - fac
*col
[2];
1036 else if ((tmp
= (*b
) / tmp
) > 1.0 )
1046 tmp
= facm
+ fac
*col
[0];
1050 else if (( tmp
= (1.0 - (1.0 - (*r
)) / tmp
)) < 0.0)
1058 tmp
= facm
+ fac
*col
[1];
1061 else if (( tmp
= (1.0 - (1.0 - (*g
)) / tmp
)) < 0.0 )
1068 tmp
= facm
+ fac
*col
[2];
1071 else if (( tmp
= (1.0 - (1.0 - (*b
)) / tmp
)) < 0.0 )
1082 float colH
,colS
,colV
;
1083 float tmpr
,tmpg
,tmpb
;
1084 rgb_to_hsv(col
[0],col
[1],col
[2],&colH
,&colS
,&colV
);
1086 rgb_to_hsv(*r
,*g
,*b
,&rH
,&rS
,&rV
);
1087 hsv_to_rgb( colH
, rS
, rV
, &tmpr
, &tmpg
, &tmpb
);
1088 *r
= facm
*(*r
) + fac
*tmpr
;
1089 *g
= facm
*(*g
) + fac
*tmpg
;
1090 *b
= facm
*(*b
) + fac
*tmpb
;
1097 float colH
,colS
,colV
;
1098 rgb_to_hsv(*r
,*g
,*b
,&rH
,&rS
,&rV
);
1100 rgb_to_hsv(col
[0],col
[1],col
[2],&colH
,&colS
,&colV
);
1101 hsv_to_rgb( rH
, (facm
*rS
+fac
*colS
), rV
, r
, g
, b
);
1108 float colH
,colS
,colV
;
1109 rgb_to_hsv(*r
,*g
,*b
,&rH
,&rS
,&rV
);
1110 rgb_to_hsv(col
[0],col
[1],col
[2],&colH
,&colS
,&colV
);
1111 hsv_to_rgb( rH
, rS
, (facm
*rV
+fac
*colV
), r
, g
, b
);
1117 float colH
,colS
,colV
;
1118 float tmpr
,tmpg
,tmpb
;
1119 rgb_to_hsv(col
[0],col
[1],col
[2],&colH
,&colS
,&colV
);
1121 rgb_to_hsv(*r
,*g
,*b
,&rH
,&rS
,&rV
);
1122 hsv_to_rgb( colH
, colS
, rV
, &tmpr
, &tmpg
, &tmpb
);
1123 *r
= facm
*(*r
) + fac
*tmpr
;
1124 *g
= facm
*(*g
) + fac
*tmpg
;
1125 *b
= facm
*(*b
) + fac
*tmpb
;