1 /****************************************************************************
4 * This module implements solid texturing functions that perturb the surface
5 * normal to create a bumpy effect.
7 * from Persistence of Vision(tm) Ray Tracer
8 * Copyright 1996,1999 Persistence of Vision Team
9 *---------------------------------------------------------------------------
10 * NOTICE: This source code file is provided so that users may experiment
11 * with enhancements to POV-Ray and to port the software to platforms other
12 * than those supported by the POV-Ray Team. There are strict rules under
13 * which you are permitted to use this file. The rules are in the file
14 * named POVLEGAL.DOC which should be distributed with this file.
15 * If POVLEGAL.DOC is not available or for more info please contact the POV-Ray
16 * Team Coordinator by email to team-coord@povray.org or visit us on the web at
17 * http://www.povray.org. The latest version of POV-Ray may be found at this site.
19 * This program is based on the popular DKB raytracer version 2.12.
20 * DKBTrace was originally written by David K. Buck.
21 * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
23 *****************************************************************************/
26 * Some texture ideas garnered from SIGGRAPH '85 Volume 19 Number 3,
27 * "An Image Synthesizer" By Ken Perlin.
29 * Further Ideas Garnered from "The RenderMan Companion" (Addison Wesley)
45 /*****************************************************************************
46 * Local preprocessor defines
47 ******************************************************************************/
51 /*****************************************************************************
53 ******************************************************************************/
57 /*****************************************************************************
59 ******************************************************************************/
62 VECTOR Pyramid_Vect
[4]= {{ 0.942809041,-0.333333333, 0.0},
63 {-0.471404521,-0.333333333, 0.816496581},
64 {-0.471404521,-0.333333333,-0.816496581},
68 /*****************************************************************************
70 ******************************************************************************/
72 static void ripples (VECTOR EPoint
, TNORMAL
*Tnormal
, VECTOR Vector
);
73 static void waves (VECTOR EPoint
, TNORMAL
*Tnormal
, VECTOR Vector
);
74 static void bumps (VECTOR EPoint
, TNORMAL
*Tnormal
, VECTOR normal
);
75 static void dents (VECTOR EPoint
, TNORMAL
*Tnormal
, VECTOR normal
);
76 static void wrinkles (VECTOR EPoint
, TNORMAL
*Tnormal
, VECTOR normal
);
77 static void quilted (VECTOR EPoint
, TNORMAL
*Tnormal
, VECTOR normal
);
78 static DBL
Hermite_Cubic (DBL T1
,UV_VECT UV1
,UV_VECT UV2
);
79 static DBL
Do_Slope_Map (DBL value
, BLEND_MAP
*Blend_Map
);
80 static void Do_Average_Normals (VECTOR EPoint
, TNORMAL
*Tnormal
, VECTOR normal
);
83 /*****************************************************************************
103 ******************************************************************************/
105 static void ripples (VECTOR EPoint
, TNORMAL
*Tnormal
, VECTOR normal
)
107 register unsigned int i
;
108 register DBL length
, scalar
, index
;
111 for (i
= 0 ; i
< Number_Of_Waves
; i
++)
113 VSub (point
, EPoint
, Wave_Sources
[i
]);
114 VLength (length
, point
);
119 index
= length
* Tnormal
->Frequency
+ Tnormal
->Phase
;
121 scalar
= cycloidal(index
) * Tnormal
->Amount
;
123 VAddScaledEq(normal
, scalar
/ (length
* (DBL
)Number_Of_Waves
), point
);
129 /*****************************************************************************
149 ******************************************************************************/
151 static void waves (VECTOR EPoint
, TNORMAL
*Tnormal
, VECTOR normal
)
153 register unsigned int i
;
154 register DBL length
, scalar
, index
, sinValue
;
157 for (i
= 0 ; i
< Number_Of_Waves
; i
++)
159 VSub (point
, EPoint
, Wave_Sources
[i
]);
161 VLength (length
, point
);
168 index
= length
* Tnormal
->Frequency
* frequency
[i
] + Tnormal
->Phase
;
170 sinValue
= cycloidal(index
);
172 scalar
= sinValue
* Tnormal
->Amount
/ frequency
[i
];
174 VAddScaledEq(normal
, scalar
/ (length
* (DBL
)Number_Of_Waves
), point
);
180 /*****************************************************************************
200 ******************************************************************************/
202 static void bumps (VECTOR EPoint
, TNORMAL
*Tnormal
, VECTOR normal
)
206 /* Get normal displacement value. */
208 DNoise (bump_turb
, EPoint
);
210 /* Displace "normal". */
212 VAddScaledEq(normal
, Tnormal
->Amount
, bump_turb
);
217 /*****************************************************************************
232 * Dents is similar to bumps, but uses noise() to control the amount of
233 * dnoise() perturbation of the object normal...
237 ******************************************************************************/
239 static void dents (VECTOR EPoint
, TNORMAL
*Tnormal
, VECTOR normal
)
244 noise
= Noise (EPoint
);
246 noise
= noise
* noise
* noise
* Tnormal
->Amount
;
248 /* Get normal displacement value. */
250 DNoise(stucco_turb
, EPoint
);
252 /* Displace "normal". */
254 VAddScaledEq(normal
, noise
, stucco_turb
);
260 /*****************************************************************************
276 * Wrinkles - This is my implementation of the dented() routine, using
277 * a surface iterative fractal derived from DTurbulence.
279 * This is a 3-D version (thanks to DNoise()...) of the usual version
280 * using the singular Noise()...
282 * Seems to look a lot like wrinkles, however... (hmmm)
284 * Idea garnered from the April 89 Byte Graphics Supplement on RenderMan,
285 * refined from "The RenderMan Companion, by Steve Upstill of Pixar,
286 * (C) 1990 Addison-Wesley.
290 ******************************************************************************/
292 static void wrinkles (VECTOR EPoint
, TNORMAL
*Tnormal
, VECTOR normal
)
295 register DBL scale
= 1.0;
296 VECTOR result
, value
, value2
;
298 Make_Vector(result
, 0.0, 0.0, 0.0);
300 for (i
= 0; i
< 10; scale
*= 2.0, i
++)
302 VScale(value2
,EPoint
,scale
);
303 DNoise(value
, value2
);
305 result
[X
] += fabs(value
[X
] / scale
);
306 result
[Y
] += fabs(value
[Y
] / scale
);
307 result
[Z
] += fabs(value
[Z
] / scale
);
310 /* Displace "normal". */
312 VAddScaledEq(normal
, Tnormal
->Amount
, result
);
316 /*****************************************************************************
336 ******************************************************************************/
338 static void quilted (VECTOR EPoint
, TNORMAL
*Tnormal
, VECTOR normal
)
343 value
[X
] = EPoint
[X
]-FLOOR(EPoint
[X
])-0.5;
344 value
[Y
] = EPoint
[Y
]-FLOOR(EPoint
[Y
])-0.5;
345 value
[Z
] = EPoint
[Z
]-FLOOR(EPoint
[Z
])-0.5;
347 t
= sqrt(value
[X
]*value
[X
]+value
[Y
]*value
[Y
]+value
[Z
]*value
[Z
]);
349 t
= quilt_cubic(t
, Tnormal
->Vals
.Quilted
.Control0
, Tnormal
->Vals
.Quilted
.Control1
);
355 VAddScaledEq (normal
, Tnormal
->Amount
,value
);
358 /*****************************************************************************
370 * pointer to the created Tnormal
376 * DESCRIPTION : Allocate memory for new Tnormal and initialize it to
377 * system default values.
381 ******************************************************************************/
384 TNORMAL
*Create_Tnormal ()
388 New
= (TNORMAL
*)POV_MALLOC(sizeof(TNORMAL
), "normal");
390 Init_TPat_Fields((TPATTERN
*)New
);
399 /*****************************************************************************
419 ******************************************************************************/
421 TNORMAL
*Copy_Tnormal (TNORMAL
*Old
)
427 New
= Create_Tnormal();
429 Copy_TPat_Fields ((TPATTERN
*)New
, (TPATTERN
*)Old
);
431 New
->Amount
= Old
->Amount
;
443 /*****************************************************************************
463 ******************************************************************************/
465 void Destroy_Tnormal(TNORMAL
*Tnormal
)
469 Destroy_TPat_Fields ((TPATTERN
*)Tnormal
);
477 /*****************************************************************************
497 ******************************************************************************/
499 void Post_Tnormal (TNORMAL
*Tnormal
)
506 if (Tnormal
->Flags
& POST_DONE
)
511 if (Tnormal
->Type
== NO_PATTERN
)
513 Error("No normal type given.");
516 Tnormal
->Flags
|= POST_DONE
;
518 if ((Map
= Tnormal
->Blend_Map
) != NULL
)
520 for (i
= 0; i
< Map
->Number_Of_Entries
; i
++)
526 Post_Pigment(Map
->Blend_Map_Entries
[i
].Vals
.Pigment
);
532 Post_Tnormal(Map
->Blend_Map_Entries
[i
].Vals
.Tnormal
);
538 Post_Textures(Map
->Blend_Map_Entries
[i
].Vals
.Texture
);
550 Error("Unknown pattern type in Post_Tnormal.");
559 /*****************************************************************************
579 ******************************************************************************/
583 void Perturb_Normal(VECTOR Layer_Normal
, TNORMAL
*Tnormal
, VECTOR EPoint
)
586 DBL value1
,value2
,Amount
;
588 BLEND_MAP
*Blend_Map
;
589 BLEND_MAP_ENTRY
*Prev
, *Cur
;
596 /* If normal_map present, use it and return */
598 if ((Blend_Map
=Tnormal
->Blend_Map
) != NULL
)
600 if ((Blend_Map
->Type
== NORMAL_TYPE
) && (Tnormal
->Type
!= AVERAGE_PATTERN
))
602 value1
= Evaluate_TPat((TPATTERN
*)Tnormal
,EPoint
);
604 Search_Blend_Map (value1
,Blend_Map
,&Prev
,&Cur
);
606 Assign_Vector(P1
,Layer_Normal
);
608 Warp_EPoint (TPoint
, EPoint
, (TPATTERN
*)Tnormal
);
609 Perturb_Normal(Layer_Normal
,Cur
->Vals
.Tnormal
,TPoint
);
613 Perturb_Normal(P1
,Prev
->Vals
.Tnormal
,TPoint
);
615 value2
= (value1
-Prev
->value
)/(Cur
->value
-Prev
->value
);
618 VLinComb2(Layer_Normal
,value1
,P1
,value2
,Layer_Normal
)
621 VNormalizeEq(Layer_Normal
);
629 if (Tnormal
->Type
<= LAST_NORM_ONLY_PATTERN
)
631 Warp_EPoint (TPoint
, EPoint
, (TPATTERN
*)Tnormal
);
632 switch (Tnormal
->Type
)
634 case BITMAP_PATTERN
: bump_map (TPoint
, Tnormal
, Layer_Normal
); break;
635 case BUMPS_PATTERN
: bumps (TPoint
, Tnormal
, Layer_Normal
); break;
636 case DENTS_PATTERN
: dents (TPoint
, Tnormal
, Layer_Normal
); break;
637 case RIPPLES_PATTERN
:ripples (TPoint
, Tnormal
, Layer_Normal
); break;
638 case WAVES_PATTERN
: waves (TPoint
, Tnormal
, Layer_Normal
); break;
639 case WRINKLES_PATTERN
:wrinkles (TPoint
, Tnormal
, Layer_Normal
);break;
640 case QUILTED_PATTERN
:quilted (TPoint
, Tnormal
, Layer_Normal
); break;
641 case AVERAGE_PATTERN
: Do_Average_Normals (TPoint
, Tnormal
, Layer_Normal
); break;
643 Error("Normal pattern not yet implemented.");
648 Amount
=Tnormal
->Amount
* -5.0; /*fudge factor*/
650 /* Note, even though DELTA and Pyramid_Vect are constants, we may later
651 make DELTA a user-defined parameter. Good optimising compilers
652 should merge the constants anyway. */
656 VAddScaled(P1
,EPoint
,DELTA
,Pyramid_Vect
[i
]);
657 value1
= Do_Slope_Map(Evaluate_TPat((TPATTERN
*)Tnormal
,P1
),Blend_Map
);
658 VAddScaledEq(Layer_Normal
,value1
*Amount
,Pyramid_Vect
[i
]);
663 VNormalizeEq(Layer_Normal
);
668 /*****************************************************************************
684 ******************************************************************************/
686 static DBL
Do_Slope_Map (DBL value
,BLEND_MAP
*Blend_Map
)
689 BLEND_MAP_ENTRY
*Prev
, *Cur
;
691 if (Blend_Map
== NULL
)
696 Search_Blend_Map (value
,Blend_Map
,&Prev
,&Cur
);
700 return(Cur
->Vals
.Point_Slope
[0]);
703 Result
= (value
-Prev
->value
)/(Cur
->value
-Prev
->value
);
705 return(Hermite_Cubic(Result
,Prev
->Vals
.Point_Slope
,Cur
->Vals
.Point_Slope
));
710 /*****************************************************************************
726 ******************************************************************************/
733 static DBL
Hermite_Cubic(DBL T1
,UV_VECT UV1
,UV_VECT UV2
)
737 DBL rv
; /* simplified equation for poor Symantec */
739 rv
= TTT
*(S1
+S2
+2.0*(P1
-P2
));
740 rv
+= -TT
*(2.0*S1
+S2
+3.0*(P1
-P2
));
748 /*****************************************************************************
764 ******************************************************************************/
766 static void Do_Average_Normals (VECTOR EPoint
,TNORMAL
*Tnormal
,VECTOR normal
)
769 BLEND_MAP
*Map
= Tnormal
->Blend_Map
;
774 Make_Vector (V1
, 0.0, 0.0, 0.0);
776 for (i
= 0; i
< Map
->Number_Of_Entries
; i
++)
778 Value
= Map
->Blend_Map_Entries
[i
].value
;
780 Assign_Vector(V2
,normal
);
782 Perturb_Normal(V2
,Map
->Blend_Map_Entries
[i
].Vals
.Tnormal
,EPoint
);
784 VAddScaledEq(V1
,Value
,V2
);
789 VInverseScale(normal
,V1
,Total
);