1 /*******************************************************************************
2  * pattern.cpp
3  *
4  * This module implements texturing functions that return a value to be
5  * used in a pigment or normal.
6  *
7  * ---------------------------------------------------------------------------
8  * Persistence of Vision Ray Tracer ('POV-Ray') version 3.7.
9  * Copyright 1991-2013 Persistence of Vision Raytracer Pty. Ltd.
10  *
11  * POV-Ray is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Affero General Public License as
13  * published by the Free Software Foundation, either version 3 of the
14  * License, or (at your option) any later version.
15  *
16  * POV-Ray is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU Affero General Public License for more details.
20  *
21  * You should have received a copy of the GNU Affero General Public License
22  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23  * ---------------------------------------------------------------------------
24  * POV-Ray is based on the popular DKB raytracer version 2.12.
25  * DKBTrace was originally written by David K. Buck.
26  * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
27  * ---------------------------------------------------------------------------
28  * $File: //depot/public/povray/3.x/source/backend/pattern/pattern.cpp $
29  * $Revision: #1 $
30  * $Change: 6069 $
31  * $DateTime: 2013/11/06 11:59:40 $
32  * $Author: chrisc $
33  *******************************************************************************/
34 
35 /*
36  * Some texture ideas garnered from SIGGRAPH '85 Volume 19 Number 3,
37  * "An Image Synthesizer" By Ken Perlin.
38  * Further Ideas Garnered from "The RenderMan Companion" (Addison Wesley).
39  */
40 
41 // frame.h must always be the first POV file included (pulls in platform config)
42 #include "backend/frame.h"
43 #include "backend/pattern/pattern.h"
44 #include "backend/texture/texture.h"
45 #include "backend/texture/pigment.h"
46 #include "backend/scene/objects.h"
47 #include "backend/scene/scene.h"
48 #include "backend/support/imageutil.h"
49 #include "backend/colour/colour.h"
50 #include "backend/parser/parse.h"
51 #include "backend/math/vector.h"
52 #include "backend/math/matrices.h"
53 #include "backend/vm/fnpovfpu.h"
54 #include "backend/support/fileutil.h"
55 #include "base/fileinputoutput.h"
56 
57 #include <algorithm>
58 #include <climits>
59 
60 // this must be the last file included
61 #include "base/povdebug.h"
62 
63 namespace pov
64 {
65 
66 using namespace pov_base;
67 
68 /*****************************************************************************
69 * Local preprocessor defines
70 ******************************************************************************/
71 
72 #define CLIP_DENSITY(r) { if((r) < 0.0) { (r) = 1.0; } else if((r) > 1.0) { (r) = 0.0; } else { (r) = 1.0 - (r); } }
73 
74 const int FRACTAL_MAX_EXPONENT = 33;
75 
76 /*****************************************************************************
77 * Local variables
78 ******************************************************************************/
79 
80 static RandomDoubleSequence PatternRands(0.0, 1.0, 32768);
81 static int BinomialCoefficients[((FRACTAL_MAX_EXPONENT+1)*(FRACTAL_MAX_EXPONENT+2))/2]; // GLOBAL VARIABLE
82 boost::hash<Crackle_Cell_Coord> Crackle_Cell_Hasher;
83 static int CrackleCubeTable[81*3];
84 
85 /*****************************************************************************
86 * Static functions
87 ******************************************************************************/
88 
89 static DBL agate_pattern (const VECTOR EPoint, const TPATTERN *TPat, int noise_generator);
90 static DBL boxed_pattern (const VECTOR EPoint);
91 static DBL brick_pattern (const VECTOR EPoint, const TPATTERN *TPat);
92 static DBL cells_pattern (const VECTOR EPoint);
93 static DBL checker_pattern (const VECTOR EPoint);
94 static DBL crackle_pattern (const VECTOR EPoint, const TPATTERN *TPat, TraceThreadData *Thread);
95 static DBL cylindrical_pattern (const VECTOR EPoint);
96 static DBL dents_pattern (const VECTOR EPoint, int noise_generator);
97 static DBL density_pattern (const VECTOR EPoint, const TPATTERN *TPat);
98 static DBL function_pattern (const VECTOR EPoint, const TPATTERN *TPat, TraceThreadData *Thread);
99 static DBL gradient_pattern (const VECTOR EPoint, const TPATTERN *TPat);
100 static DBL granite_pattern (const VECTOR EPoint, int noise_generator);
101 static DBL hexagon_pattern (const VECTOR EPoint);
102 static DBL square_pattern (const VECTOR EPoint);
103 static DBL triangular_pattern (const VECTOR EPoint);
104 static DBL cubic_pattern (const VECTOR EPoint);
105 static DBL julia_pattern (const VECTOR EPoint, const TPATTERN *TPat);
106 static DBL julia3_pattern (const VECTOR EPoint, const TPATTERN *TPat);
107 static DBL julia4_pattern (const VECTOR EPoint, const TPATTERN *TPat);
108 static DBL juliax_pattern (const VECTOR EPoint, const TPATTERN *TPat);
109 static DBL leopard_pattern (const VECTOR EPoint);
110 static DBL magnet1m_pattern (const VECTOR EPoint, const TPATTERN *TPat);
111 static DBL magnet1j_pattern (const VECTOR EPoint, const TPATTERN *TPat);
112 static DBL magnet2m_pattern (const VECTOR EPoint, const TPATTERN *TPat);
113 static DBL magnet2j_pattern (const VECTOR EPoint, const TPATTERN *TPat);
114 static DBL mandel_pattern (const VECTOR EPoint, const TPATTERN *TPat);
115 static DBL mandel3_pattern (const VECTOR EPoint, const TPATTERN *TPat);
116 static DBL mandel4_pattern (const VECTOR EPoint, const TPATTERN *TPat);
117 static DBL mandelx_pattern (const VECTOR EPoint, const TPATTERN *TPat);
118 static DBL marble_pattern (const VECTOR EPoint, const TPATTERN *TPat, int noise_generator);
119 static DBL object_pattern (const VECTOR EPoint, const TPATTERN *TPat, TraceThreadData *Thread);
120 static DBL onion_pattern (const VECTOR EPoint);
121 static DBL pavement_pattern (const VECTOR EPoint, const TPATTERN *TPat);
122 static DBL pigment_pattern (const VECTOR EPoint, const TPATTERN *TPat, const Intersection *isect, const Ray *ray, TraceThreadData *Thread);
123 static DBL planar_pattern (const VECTOR EPoint);
124 static DBL quilted_pattern (const VECTOR EPoint, const TPATTERN *TPat);
125 static DBL radial_pattern (const VECTOR EPoint);
126 static DBL ripples_pattern (const VECTOR EPoint, const TPATTERN *TPat, const TraceThreadData *Thread);
127 static DBL slope_pattern (const VECTOR EPoint, const TPATTERN *TPat, const Intersection *Intersection);
128 static DBL aoi_pattern (const Intersection *Intersection, const Ray *ray);
129 static DBL spiral1_pattern (const VECTOR EPoint, const TPATTERN *TPat, int noise_generator);
130 static DBL spiral2_pattern (const VECTOR EPoint, const TPATTERN *TPat, int noise_generator);
131 static DBL spherical_pattern (const VECTOR EPoint);
132 static DBL tiling_pattern (const VECTOR EPoint, const TPATTERN *TPat);
133 static DBL waves_pattern (const VECTOR EPoint, const TPATTERN *TPat, const TraceThreadData *Thread);
134 static DBL wood_pattern (const VECTOR EPoint, const TPATTERN *TPat);
135 static DBL wrinkles_pattern (const VECTOR EPoint, int noise_generator);
136 
137 static DBL fractal_exterior_color(const TPATTERN *TPat, int iters, DBL a, DBL b);
138 static DBL fractal_interior_color(const TPATTERN *TPat, int iters, DBL a, DBL b, DBL mindist2);
139 static const TURB *Search_For_Turb(const WARP *Warps);
140 static unsigned short readushort(IStream *infile);
141 static unsigned int readuint(IStream *infile);
142 
143 #define SQRT3_2     0.86602540378443864676372317075294  ///< sqrt(3)/2
144 #define SQRT3       1.7320508075688772935274463415059   ///< sqrt(3)
145 #define SQRT2       1.4142135623730950488016887242097   ///< sqrt(2)
146 #define SQRT2_2     0.70710678118654752440084436210485  ///< sqrt(2)/2
147 
148 #define SIN18       0.30901699437494742410229341718282  ///< sin(18 deg)
149 #define SIN36       0.58778525229247312916870595463907  ///< sin(36 deg)
150 #define SIN54       0.80901699437494742410229341718282  ///< sin(54 deg)
151 #define SIN72       0.95105651629515357211643933337938  ///< sin(72 deg)
152 #define SIN108      SIN72                               ///< sin(108 deg)
153 #define SIN144      SIN36                               ///< sin(144 deg)
154 #define SIN162      SIN18                               ///< sin(162 deg)
155 #define COS18       SIN72                               ///< cos(18 deg)
156 #define COS36       SIN54                               ///< cos(36 deg)
157 #define COS54       SIN36                               ///< cos(54 deg)
158 #define COS72       SIN18                               ///< cos(72 deg)
159 #define COS108      (-COS72)                            ///< cos(108 deg)
160 #define COS126      (-COS54)                            ///< cos(126 deg)
161 #define COS144      (-COS36)                            ///< cos(144 deg)
162 #define COS162      (-COS18)                            ///< cos(162 deg)
163 #define TAN18       0.32491969623290632615587141221513  ///< tan(18 deg)
164 #define TAN36       0.72654252800536088589546675748062  ///< tan(36 deg)
165 #define TAN54       1.3763819204711735382072095819109   ///< tan(54 deg)
166 #define TAN72       3.0776835371752534025702905760369   ///< tan(72 deg)
167 #define TAN108      (-TAN72)                            ///< tan(108 deg)
168 #define TAN126      (-TAN54)                            ///< tan(126 deg)
169 #define TAN144      (-TAN36)                            ///< tan(144 deg)
170 #define TAN162      (-TAN18)                            ///< tan(162 deg)
171 
172 #define PHI         1.6180339887498948482045868343656   ///< golden ratio = (1+sqrt(5))/2
173 #define INVPHI      0.61803398874989484820458683436564  ///< inverse of golden ratio (= golden ratio -1)
174 #define SQRPHI      2.6180339887498948482045868343656   ///< square of golden ratio (= golden ratio +1)
175 #define INVSQRPHI   0.38196601125010515179541316563436  ///< inverse square of golden ratio (= 2 - golden ratio)
176 
177 #define TILING_EPSILON 1e-6
178 
179 /*****************************************************************************/
180 
GetNoiseGen(const TPATTERN * TPat,const TraceThreadData * Thread)181 int GetNoiseGen (const TPATTERN *TPat, const TraceThreadData *Thread)
182 {
183 	int noise_gen = (TPat->Flags & NOISE_FLAGS) / NOISE_FLAG_1;
184 	if (!noise_gen)
185 		noise_gen = Thread->GetSceneData()->noiseGenerator;
186 	return noise_gen;
187 }
188 
189 /*****************************************************************************
190 *
191 * FUNCTION
192 *
193 *   Evaluate_Pattern
194 *
195 * INPUT
196 *
197 *   EPoint -- The point in 3d space at which the pattern
198 *   is evaluated.
199 *   TPat   -- Texture pattern struct
200 *   Intersection - intersection structure
201 *
202 * OUTPUT
203 *
204 * RETURNS
205 *
206 *   DBL result usual 0.0 to 1.0 but may be 2.0 in hexagon
207 *
208 * AUTHOR
209 *
210 *   Adapted from Add_Pigment by Chris Young
211 *
212 * DESCRIPTION
213 *
214 * CHANGES
215 *
216 ******************************************************************************/
217 
Evaluate_TPat(const TPATTERN * TPat,const VECTOR EPoint,const Intersection * Isection,const Ray * ray,TraceThreadData * Thread)218 DBL Evaluate_TPat (const TPATTERN *TPat, const VECTOR EPoint, const Intersection *Isection, const Ray *ray, TraceThreadData *Thread)
219 {
220 	DBL value = 0.0;
221 
222 	/* NK 19 Nov 1999 removed Warp_EPoint call */
223 
224 	switch(TPat->Type)
225 	{
226 		case AGATE_PATTERN:       value = agate_pattern      (EPoint, TPat, GetNoiseGen(TPat, Thread)); break;
227 		case BOZO_PATTERN:
228 		case SPOTTED_PATTERN:
229 		case BUMPS_PATTERN:       value = Noise              (EPoint,       GetNoiseGen(TPat, Thread)); break;
230 		case BRICK_PATTERN:       value = brick_pattern      (EPoint, TPat);                            break;
231 		case CELLS_PATTERN:       value = cells_pattern      (EPoint);                                  break;
232 		case CHECKER_PATTERN:     value = checker_pattern    (EPoint);                                  break;
233 		case CRACKLE_PATTERN:     value = crackle_pattern    (EPoint, TPat, Thread);                    break;
234 		case GRADIENT_PATTERN:    value = gradient_pattern   (EPoint, TPat);                            break;
235 		case GRANITE_PATTERN:     value = granite_pattern    (EPoint,       GetNoiseGen(TPat, Thread)); break;
236 		case HEXAGON_PATTERN:     value = hexagon_pattern    (EPoint);                                  break;
237 		case SQUARE_PATTERN:      value = square_pattern     (EPoint);                                  break;
238 		case TRIANGULAR_PATTERN:  value = triangular_pattern (EPoint);                                  break;
239 		case CUBIC_PATTERN:       value = cubic_pattern      (EPoint);                                  break;
240 		case JULIA_PATTERN:       value = julia_pattern      (EPoint, TPat);                            break;
241 		case JULIA3_PATTERN:      value = julia3_pattern     (EPoint, TPat);                            break;
242 		case JULIA4_PATTERN:      value = julia4_pattern     (EPoint, TPat);                            break;
243 		case JULIAX_PATTERN:      value = juliax_pattern     (EPoint, TPat);                            break;
244 		case LEOPARD_PATTERN:     value = leopard_pattern    (EPoint);                                  break;
245 		case MAGNET1M_PATTERN:    value = magnet1m_pattern   (EPoint, TPat);                            break;
246 		case MAGNET1J_PATTERN:    value = magnet1j_pattern   (EPoint, TPat);                            break;
247 		case MAGNET2M_PATTERN:    value = magnet2m_pattern   (EPoint, TPat);                            break;
248 		case MAGNET2J_PATTERN:    value = magnet2j_pattern   (EPoint, TPat);                            break;
249 		case MANDEL_PATTERN:      value = mandel_pattern     (EPoint, TPat);                            break;
250 		case MANDEL3_PATTERN:     value = mandel3_pattern    (EPoint, TPat);                            break;
251 		case MANDEL4_PATTERN:     value = mandel4_pattern    (EPoint, TPat);                            break;
252 		case MANDELX_PATTERN:     value = mandelx_pattern    (EPoint, TPat);                            break;
253 		case MARBLE_PATTERN:      value = marble_pattern     (EPoint, TPat, GetNoiseGen(TPat, Thread)); break;
254 		case ONION_PATTERN:       value = onion_pattern      (EPoint);                                  break;
255 		case RADIAL_PATTERN:      value = radial_pattern     (EPoint);                                  break;
256 		case SPIRAL1_PATTERN:     value = spiral1_pattern    (EPoint, TPat, GetNoiseGen(TPat, Thread)); break;
257 		case SPIRAL2_PATTERN:     value = spiral2_pattern    (EPoint, TPat, GetNoiseGen(TPat, Thread)); break;
258 		case WOOD_PATTERN:        value = wood_pattern       (EPoint, TPat);                            break;
259 		case WAVES_PATTERN:       value = waves_pattern      (EPoint, TPat, Thread);                    break;
260 		case RIPPLES_PATTERN:     value = ripples_pattern    (EPoint, TPat, Thread);                    break;
261 		case WRINKLES_PATTERN:    value = wrinkles_pattern   (EPoint,       GetNoiseGen(TPat, Thread)); break;
262 		case DENTS_PATTERN:       value = dents_pattern      (EPoint,       GetNoiseGen(TPat, Thread)); break;
263 		case QUILTED_PATTERN:     value = quilted_pattern    (EPoint, TPat);                            break;
264 		case FUNCTION_PATTERN:    value = function_pattern   (EPoint, TPat, Thread);                    break;
265 		case PLANAR_PATTERN:      value = planar_pattern     (EPoint);                                  break;
266 		case BOXED_PATTERN:       value = boxed_pattern      (EPoint);                                  break;
267 		case SPHERICAL_PATTERN:   value = spherical_pattern  (EPoint);                                  break;
268 		case CYLINDRICAL_PATTERN: value = cylindrical_pattern(EPoint);                                  break;
269 		case DENSITY_FILE_PATTERN:value = density_pattern    (EPoint, TPat);                            break;
270 		case IMAGE_PATTERN:       value = image_pattern      (EPoint, TPat);                            break;
271 		case SLOPE_PATTERN:       value = slope_pattern      (EPoint, TPat, Isection);                  break;
272 		case AOI_PATTERN:         value = aoi_pattern        (Isection, ray);                           break;
273 		case PAVEMENT_PATTERN:    value = pavement_pattern   (EPoint, TPat);                            break;
274 		case TILING_PATTERN:      value = tiling_pattern     (EPoint, TPat);                            break;
275 		case PIGMENT_PATTERN:     value = pigment_pattern    (EPoint, TPat, Isection, ray, Thread);     break;
276 		case OBJECT_PATTERN:      value = object_pattern     (EPoint, TPat, Thread);                    break;
277 
278 		default: throw POV_EXCEPTION_STRING("Problem in Evaluate_TPat.");
279 	}
280 
281 	if(TPat->Frequency != 0.0)
282 		value = fmod(value * TPat->Frequency + TPat->Phase, 1.00001); // TODO FIXME - magic number! Should be 1.0+SOME_EPSILON (or maybe actually 1.0?)
283 
284 	/* allow negative Frequency */
285 	if(value < 0.0)
286 		value -= floor(value);
287 
288 	switch(TPat->Wave_Type)
289 	{
290 		case RAMP_WAVE:
291 			break;
292 		case SINE_WAVE:
293 			value = (1.0 + cycloidal(value)) * 0.5;
294 			break;
295 		case TRIANGLE_WAVE:
296 			value = Triangle_Wave(value);
297 			break;
298 		case SCALLOP_WAVE:
299 			value = fabs(cycloidal(value * 0.5));
300 			break;
301 		case CUBIC_WAVE:
302 			value = Sqr(value) * ((-2.0 * value) + 3.0);
303 			break;
304 		case POLY_WAVE:
305 			value = pow(value, (DBL) TPat->Exponent);
306 			break;
307 		default:
308 			throw POV_EXCEPTION_STRING("Unknown Wave Type.");
309 	}
310 
311 	return value;
312 }
313 
314 
315 /*****************************************************************************
316 *
317 * FUNCTION
318 *
319 * INPUT
320 *
321 * OUTPUT
322 *
323 * RETURNS
324 *
325 * AUTHOR
326 *
327 * DESCRIPTION
328 *
329 * CHANGES
330 *
331 ******************************************************************************/
332 
Init_TPat_Fields(TPATTERN * Tpat)333 void Init_TPat_Fields (TPATTERN *Tpat)
334 {
335 	Tpat->Type       = NO_PATTERN;
336 	Tpat->Wave_Type  = RAMP_WAVE;
337 	Tpat->Flags      = NO_FLAGS;
338 	Tpat->References = 1;
339 	Tpat->Exponent   = 1.0;
340 	Tpat->Frequency  = 1.0;
341 	Tpat->Phase      = 0.0;
342 	Tpat->Warps      = NULL;
343 	Tpat->Next       = NULL;
344 	Tpat->Blend_Map  = NULL;
345 }
346 
347 
348 /*****************************************************************************
349 *
350 * FUNCTION
351 *
352 * INPUT
353 *
354 * OUTPUT
355 *
356 * RETURNS
357 *
358 * AUTHOR
359 *
360 * DESCRIPTION
361 *
362 * CHANGES
363 *
364 ******************************************************************************/
365 
Copy_TPat_Fields(TPATTERN * New,const TPATTERN * Old)366 void Copy_TPat_Fields (TPATTERN *New, const TPATTERN *Old)
367 {
368 	*New = *Old;
369 
370 	/* Copy warp chain */
371 	New->Warps = Copy_Warps(Old->Warps);
372 
373 	New->Blend_Map = Copy_Blend_Map(Old->Blend_Map);
374 
375 	/* Note, cannot copy Old->Next because we don't know what kind of
376 	   thing this is.  It must be copied by Copy_Pigment, Copy_Tnormal etc.
377 	*/
378 
379 	/* NK 1998 - added IMAGE_PATTERN */
380 	if ((Old->Type == BITMAP_PATTERN) || (Old->Type == IMAGE_PATTERN))
381 	{
382 		New->Vals.image = Copy_Image(Old->Vals.image);
383 	}
384 
385 	if (Old->Type == DENSITY_FILE_PATTERN)
386 	{
387 		New->Vals.Density_File = Copy_Density_File(Old->Vals.Density_File);
388 	}
389 
390 	if (Old->Type == PIGMENT_PATTERN )
391 	{
392 		New->Vals.Pigment = Copy_Pigment(Old->Vals.Pigment);
393 	}
394 
395 	if (Old->Type == OBJECT_PATTERN)
396 	{
397 		if(Old->Vals.Object != NULL)
398 		{
399 			New->Vals.Object = reinterpret_cast<ObjectPtr>(Copy_Object(Old->Vals.Object));
400 		}
401 	}
402 
403 	if (Old->Type == FUNCTION_PATTERN)
404 	{
405 		if (Old->Vals.Function.Fn != NULL)
406 		{
407 			New->Vals.Function.Fn = reinterpret_cast<void *>(Parser::Copy_Function( Old->Vals.Function.vm, (FUNCTION_PTR)(Old->Vals.Function.Fn) ));
408 		}
409 	}
410 }
411 
412 
413 /*****************************************************************************
414 *
415 * FUNCTION
416 *
417 * INPUT
418 *
419 * OUTPUT
420 *
421 * RETURNS
422 *
423 * AUTHOR
424 *
425 * DESCRIPTION
426 *
427 * CHANGES
428 *
429 ******************************************************************************/
430 
Destroy_TPat_Fields(TPATTERN * Tpat)431 void Destroy_TPat_Fields(TPATTERN *Tpat)
432 {
433 	Destroy_Warps(Tpat->Warps);
434 	Destroy_Blend_Map(Tpat->Blend_Map);
435 	/* Note, cannot destroy Tpat->Next nor pattern itself because we don't
436 	   know what kind of thing this is.  It must be destroied by Destroy_Pigment, etc.
437 	*/
438 
439 	if ((Tpat->Type == BITMAP_PATTERN) || (Tpat->Type == IMAGE_PATTERN))
440 	{
441 		Destroy_Image(Tpat->Vals.image);
442 	}
443 
444 	if (Tpat->Type == DENSITY_FILE_PATTERN)
445 	{
446 		Destroy_Density_File(Tpat->Vals.Density_File);
447 	}
448 
449 	if (Tpat->Type == OBJECT_PATTERN)
450 	{
451 		if(Tpat->Vals.Object != NULL)
452 		{
453 			Destroy_Object(reinterpret_cast<ObjectPtr>(Tpat->Vals.Object));
454 		}
455 	}
456 
457 	if (Tpat->Type == PIGMENT_PATTERN)
458 	{
459 		if (Tpat->Vals.Pigment != NULL)
460 		{
461 			Destroy_Pigment( Tpat->Vals.Pigment );
462 		}
463 	}
464 
465 	if (Tpat->Type == FUNCTION_PATTERN)
466 	{
467 		if (Tpat->Vals.Function.Fn != NULL)
468 		{
469 			Parser::Destroy_Function(Tpat->Vals.Function.vm, (FUNCTION_PTR)(Tpat->Vals.Function.Fn));
470 		}
471 	}
472 }
473 
474 
475 /*****************************************************************************
476 *
477 * FUNCTION
478 *
479 * INPUT
480 *
481 * OUTPUT
482 *
483 * RETURNS
484 *
485 * AUTHOR
486 *
487 * DESCRIPTION
488 *
489 * CHANGES
490 *
491 ******************************************************************************/
492 
Create_Turb()493 TURB *Create_Turb()
494 {
495 	TURB *New;
496 
497 	New = reinterpret_cast<TURB *>(POV_MALLOC(sizeof(TURB),"turbulence struct"));
498 
499 	Make_Vector(New->Turbulence, 0.0, 0.0, 0.0);
500 
501 	New->Octaves = 6;
502 	New->Omega = 0.5;
503 	New->Lambda = 2.0;
504 
505 	return(New);
506 }
507 
508 
509 /*****************************************************************************
510 *
511 * FUNCTION
512 *
513 *   Translate_Tpattern
514 *
515 * INPUT
516 *
517 * OUTPUT
518 *
519 * RETURNS
520 *
521 * AUTHOR
522 *
523 *   POV-Ray Team
524 *
525 * DESCRIPTION
526 *
527 * CHANGES
528 *
529 ******************************************************************************/
530 
Translate_Tpattern(TPATTERN * Tpattern,const VECTOR Vector)531 void Translate_Tpattern(TPATTERN *Tpattern, const VECTOR Vector)
532 {
533 	TRANSFORM Trans;
534 
535 	if (Tpattern != NULL)
536 	{
537 		Compute_Translation_Transform (&Trans, Vector);
538 
539 		Transform_Tpattern (Tpattern, &Trans);
540 	}
541 }
542 
543 
544 /*****************************************************************************
545 *
546 * FUNCTION
547 *
548 *   Rotate_Tpattern
549 *
550 * INPUT
551 *
552 * OUTPUT
553 *
554 * RETURNS
555 *
556 * AUTHOR
557 *
558 *   POV-Ray Team
559 *
560 * DESCRIPTION
561 *
562 * CHANGES
563 *
564 ******************************************************************************/
565 
Rotate_Tpattern(TPATTERN * Tpattern,const VECTOR Vector)566 void Rotate_Tpattern(TPATTERN *Tpattern, const VECTOR Vector)
567 {
568 	TRANSFORM Trans;
569 
570 	if (Tpattern != NULL)
571 	{
572 		Compute_Rotation_Transform (&Trans, Vector);
573 
574 		Transform_Tpattern (Tpattern, &Trans);
575 	}
576 }
577 
578 
579 /*****************************************************************************
580 *
581 * FUNCTION
582 *
583 *   Scale_Tpattern
584 *
585 * INPUT
586 *
587 * OUTPUT
588 *
589 * RETURNS
590 *
591 * AUTHOR
592 *
593 *   POV-Ray Team
594 *
595 * DESCRIPTION
596 *
597 * CHANGES
598 *
599 ******************************************************************************/
600 
Scale_Tpattern(TPATTERN * Tpattern,const VECTOR Vector)601 void Scale_Tpattern(TPATTERN *Tpattern, const VECTOR Vector)
602 {
603 	TRANSFORM Trans;
604 
605 	if (Tpattern != NULL)
606 	{
607 		Compute_Scaling_Transform (&Trans, Vector);
608 
609 		Transform_Tpattern (Tpattern, &Trans);
610 	}
611 }
612 
613 
614 /*****************************************************************************
615 *
616 * FUNCTION
617 *
618 *   Transform_Tpattern
619 *
620 * INPUT
621 *
622 * OUTPUT
623 *
624 * RETURNS
625 *
626 * AUTHOR
627 *
628 *   POV-Ray Team
629 *
630 * DESCRIPTION
631 *
632 * CHANGES
633 *
634 ******************************************************************************/
635 
Transform_Tpattern(TPATTERN * Tpattern,const TRANSFORM * Trans)636 void Transform_Tpattern(TPATTERN *Tpattern, const TRANSFORM *Trans)
637 {
638 	WARP *Temp;
639 
640 	if (Tpattern != NULL)
641 	{
642 		if (Tpattern->Warps == NULL)
643 		{
644 			Tpattern->Warps = Create_Warp(TRANSFORM_WARP);
645 		}
646 		else
647 		{
648 			if (Tpattern->Warps->Warp_Type != TRANSFORM_WARP)
649 			{
650 				Temp = Tpattern->Warps;
651 
652 				Tpattern->Warps = Create_Warp(TRANSFORM_WARP);
653 
654 				Tpattern->Warps->Next_Warp = Temp;
655 				if(Tpattern->Warps->Next_Warp != NULL)
656 					Tpattern->Warps->Next_Warp->Prev_Warp = Tpattern->Warps;
657 			}
658 		}
659 
660 		Compose_Transforms (&( (reinterpret_cast<TRANS *>(Tpattern->Warps))->Trans), Trans);
661 	}
662 }
663 
664 
665 /*****************************************************************************
666 *
667 * FUNCTION
668 *
669 * INPUT
670 *
671 * OUTPUT
672 *
673 * RETURNS
674 *
675 * AUTHOR
676 *
677 * DESCRIPTION
678 *
679 * CHANGES
680 *
681 ******************************************************************************/
682 
Search_Blend_Map(DBL value,const BLEND_MAP * Blend_Map,const BLEND_MAP_ENTRY ** Prev,const BLEND_MAP_ENTRY ** Cur)683 void Search_Blend_Map (DBL value, const BLEND_MAP *Blend_Map, const BLEND_MAP_ENTRY **Prev, const BLEND_MAP_ENTRY **Cur)
684 {
685 	BLEND_MAP_ENTRY *P, *C;
686 	int Max_Ent=Blend_Map->Number_Of_Entries-1;
687 
688 	/* if greater than last, use last. */
689 
690 	if (value >= Blend_Map->Blend_Map_Entries[Max_Ent].value)
691 	{
692 		P = C = &(Blend_Map->Blend_Map_Entries[Max_Ent]);
693 	}
694 	else
695 	{
696 		P = C = &(Blend_Map->Blend_Map_Entries[0]);
697 
698 		while (value > C->value)
699 		{
700 			P = C++;
701 		}
702 	}
703 
704 	if (value == C->value)
705 	{
706 		P = C;
707 	}
708 
709 	*Prev = P;
710 	*Cur  = C;
711 }
712 
713 
714 /*****************************************************************************
715 *
716 * FUNCTION
717 *
718 * INPUT
719 *
720 * OUTPUT
721 *
722 * RETURNS
723 *
724 * AUTHOR
725 *
726 * DESCRIPTION
727 *
728 * CHANGES
729 *
730 ******************************************************************************/
731 
Search_For_Turb(const WARP * Warps)732 static const TURB *Search_For_Turb(const WARP *Warps)
733 {
734 	const WARP* Temp=Warps;
735 
736 	if (Temp!=NULL)
737 	{
738 		while (Temp->Next_Warp != NULL)
739 		{
740 			Temp=Temp->Next_Warp;
741 		}
742 
743 		if (Temp->Warp_Type != CLASSIC_TURB_WARP)
744 		{
745 			Temp=NULL;
746 		}
747 	}
748 
749 	return (reinterpret_cast<const TURB *>(Temp));
750 }
751 
752 /* Tiling & Pavement */
753 
754 
755 /*****************************************************************************
756 *
757 * FUNCTIONS
758 *
759 *   related to Tiling & Pavement
760 *
761 * INPUT
762 *
763 *   EPoint -- The point in 3d space at which the pattern
764 *   is evaluated.
765 * OUTPUT
766 *
767 * RETURNS
768 *
769 *   DBL value in the range 0.0 to 1.0
770 *
771 * AUTHOR
772 *
773 *   J. Grimbert
774 *
775 * DESCRIPTION
776 *
777 *   New colour function by J. Grimbert
778 *
779 *   Fill the X-Z plane with repeating pattern
780 *   When there is only one kind of form, 1 is the outside, 0 is most inside
781 *   When there is two kind of form, 0 & 1 are the most inside, 1/2 is
782 *    the outside
783 *
784 ******************************************************************************/
785 
tiling_square(const VECTOR EPoint)786 static DBL tiling_square (const VECTOR EPoint)
787 {
788 	/*
789 	 ** Classical square tiling
790 	 */
791 	DBL x,z;
792 	x = fabs(EPoint[X]);
793 	x -= floor(x);
794 	x = 2*fabs( x-0.5 );
795 
796 	z = fabs(EPoint[Z]);
797 	z -= floor(z);
798 	z = 2*fabs( z-0.5 );
799 
800 	return max(x,z);
801 }
802 
tiling_hexagon(const VECTOR EPoint)803 static DBL tiling_hexagon (const VECTOR EPoint)
804 {
805 	/*
806 	 ** Classical Hexagon tiling
807 	 */
808 	DBL x,z;
809 	DBL dist1,dist2;
810 	DBL answer;
811 
812 	x=EPoint[X];
813 	z=EPoint[Z];
814 	x += 0.5;
815 	x -= 3.0*floor(x/3.0);
816 	z -= SQRT3*floor(z/(SQRT3));
817 	/* x,z is in { [0.0, 3.0 [, [0.0, SQRT3 [ }
818 	 ** but there is some symmetry to simplify the testing
819 	 */
820 	if (z > SQRT3_2 )
821 	{
822 		z = SQRT3 - z;
823 	}
824 	/*
825 	 ** Now only [0,3[,[0,SQRT3/2[
826 	 */
827 	if (x > 1.5)
828 	{
829 		x -= 1.5 ; /* translate */
830 		z = SQRT3_2 -z; /* mirror */
831 	}
832 	/*
833 	 ** And now, it is even simpler :  [0,1.5],[0,SQRT3/2]
834 	 ** on the bottom left corner, part of some other hexagon
835 	 ** on the top right corner, center of the hexagon
836 	 */
837 	if ((SQRT3*x+z)<SQRT3_2)
838 	{
839 		x = 0.5 - x;
840 		z = SQRT3_2 -z; /* mirror */
841 	}
842 	if (x > 1.0)
843 	{
844 		x = 2.0 -x; /* mirror */
845 	}
846 	/* Hexagon */
847 	dist1 = 1.0 - ( z / SQRT3_2 );
848 	dist2 = 1.0 - (((SQRT3 * x + z - SQRT3_2) ) / SQRT3 );
849 	answer = max(dist1,dist2);
850 	answer = min(1.0,answer);
851 	answer = max(0.0,answer);
852 	return answer;
853 }
854 
tiling_triangle(const VECTOR EPoint)855 static DBL tiling_triangle (const VECTOR EPoint)
856 {
857 	DBL x,z;
858 	DBL slop1;
859 	DBL dist1,dist2;
860 	int delta;
861 	x=EPoint[X];
862 	z=EPoint[Z];
863 	delta = 0;
864 	x -= floor(x);
865 	z -= SQRT3*floor(z/SQRT3);
866 	/* x,z is in { [0.0, 1.0 [, [0.0, SQRT3 [ }
867 	 ** but there is some symmetry to simplify the testing
868 	 */
869 	if (z > SQRT3_2 )
870 	{
871 		z = SQRT3 - z; /* mirror */
872 		delta = 1 - delta;
873 	}
874 	if (x > 0.5)
875 	{
876 		x = 1.0 - x; /* mirror */
877 	}
878 	if (x != 0.0)
879 	{
880 		slop1 = z/x;
881 		if (slop1>SQRT3)
882 		{
883 			z = SQRT3_2 - z;
884 			x = 0.5 -x;
885 			delta = 1 - delta;
886 		}
887 	}
888 	else
889 	{
890 		z = SQRT3_2 -z;
891 		x = 0.5;
892 	}
893 	dist1 = 1.0 - (z * 2 * SQRT3 );
894 	dist2 = 1.0 - ((SQRT3 * x - z) * SQRT3 );
895 	return delta/2.0+(0.5)*max(dist1,dist2);
896 }
897 
tiling_lozenge(const VECTOR EPoint)898 static DBL tiling_lozenge (const VECTOR EPoint)
899 {
900 	DBL x,z;
901 	DBL slop1;
902 	DBL dist1,dist2;
903 
904 	x=EPoint[X];
905 	z=EPoint[Z];
906 
907 	x -= floor(x);
908 	z -= SQRT3*floor(z/SQRT3);
909 	/* x,z is in { [0.0, 1.0 [, [0.0, SQRT3 [ }
910 	 ** There is some mirror to reduce the problem
911 	 */
912 	if ( z > SQRT3_2 )
913 	{
914 		z -= SQRT3_2;
915 		x += 0.5;
916 	}
917 	if ( (2.0*z) > SQRT3_2 )
918 	{
919 		z = SQRT3_2 - z;
920 		x = 1.5 - x;
921 	}
922 	if (x > 0.75)
923 	{
924 		x -= 1.0;
925 	}
926 	if (x != 0.0)
927 	{
928 		slop1 = z/x;
929 		if (slop1>SQRT3)
930 		{
931 			z = SQRT3_2 - z;
932 			x = 0.5 -x;
933 		}
934 	}
935 	dist1 = 1.0 - (z * 4.0 * SQRT3 / 3.0 );
936 	dist2 = 1.0 - (fabs(SQRT3 * x - z) * SQRT3 *2.0 / 3.0);
937 	return max(dist1,dist2);
938 }
939 
tiling_rhombus(const VECTOR EPoint)940 static DBL tiling_rhombus (const VECTOR EPoint)
941 {
942 	DBL x,z;
943 	DBL answer;
944 	DBL slop1;
945 	DBL dist1,dist2;
946 	int delta;
947 	x=EPoint[X];
948 	z=EPoint[Z];
949 	delta = 0;
950 	x += 0.5;
951 	x -= 3.0*floor(x/3.0);
952 	z -= SQRT3*floor(z/SQRT3);
953 	/* x,z is in { [0.0, 3.0 [, [0.0, SQRT3 [ }
954 	 ** There is some mirror to reduce the problem
955 	 */
956 	if ( z > SQRT3_2 )
957 	{
958 		z = SQRT3 -z; /* mirror */
959 		delta = 2 - delta;
960 	}
961 	if (x > 1.5)
962 	{
963 		x -= 1.5 ; /* translate */
964 		z = SQRT3_2 -z; /* mirror */
965 		delta = 2 - delta;
966 	}
967 	/* Now in [0,1.5],[0,SQRT3/2]
968 	 ** from left to right
969 	 ** part of a horizontal (z=0)
970 	 ** half a vertical
971 	 ** part of a horizontal
972 	 */
973 	if (x < 0.5)
974 	{
975 		/* mirrror */
976 		x = 1.0 - x;
977 		delta = 2 - delta;
978 	}
979 	/*
980 	 ** Let shift the [0.5,1.5],[0,SQRT3/2] to [0,1]....
981 	 */
982 	x -= 0.5;
983 	if (x != 0.0)
984 	{
985 		slop1 = z/x;
986 		if (slop1>SQRT3)
987 		{ /* rotate the vertical to match the horizontal on the right */
988 			dist1 = ( x / 2.0 ) + ( z * SQRT3_2 );
989 			dist2 = ( z / 2.0 ) - ( x * SQRT3_2 );
990 			z = dist2;
991 			x = dist1;
992 			delta = 1;
993 		}
994 	}
995 	else
996 	{
997 		/* rotate the vertical to match the horizontal on the right */
998 		dist1 = ( x / 2.0 ) + ( z * SQRT3_2 );
999 		dist2 = ( z / 2.0 ) - ( x * SQRT3_2 );
1000 		z = dist2;
1001 		x = dist1;
1002 		delta = 1;
1003 	}
1004 	/* It may be similar to lozenge (in fact, IT IS !), now */
1005 
1006 	if ( (2.0*z) > SQRT3_2 )
1007 	{
1008 		z = SQRT3_2 - z;
1009 		x = 1.5 - x;
1010 	}
1011 	if (x > 0.75)
1012 	{
1013 		x -= 1.0;
1014 	}
1015 	if (x != 0.0)
1016 	{
1017 		slop1 = z/x;
1018 		if (slop1>SQRT3)
1019 		{
1020 			z = SQRT3_2 - z;
1021 			x = 0.5 -x;
1022 		}
1023 	}
1024 	dist1 = 1.0 - (z * 4.0 * SQRT3 / 3.0 );
1025 	dist2 = 1.0 - (fabs(SQRT3 * x - z) * SQRT3 *2.0 / 3.0);
1026 	answer = max(dist1,dist2);
1027 	answer /= 3.0;
1028 	answer += delta/3.0;
1029 	answer = min(1.0,answer);
1030 	answer = max(0.0,answer);
1031 	return answer;
1032 }
1033 
tiling_rectangle(const VECTOR EPoint)1034 static DBL tiling_rectangle (const VECTOR EPoint)
1035 {
1036 	/*
1037 	 ** Tiling with rectangles
1038 	 ** resolve to square [0,4][0,4]
1039 	 ** then 16 cases
1040 	 **
1041 	 **  +-----+--+  +
1042 	 **  |     |  |  |
1043 	 **  +--+--+  +--+
1044 	 **     |  |  |
1045 	 **  +--+  +--+--+
1046 	 **  |  |  |     |
1047 	 **  +  +--+--+--+
1048 	 **  |  |     |  |
1049 	 **  +--+-----+  +
1050 	 */
1051 	DBL x,z;
1052 	DBL delta;
1053 	DBL answer;
1054 	int valueX,valueZ;
1055 	x=EPoint[X];
1056 	z=EPoint[Z];
1057 	x -= 4.0*floor(x/4.0);
1058 	z -= 4.0*floor(z/4.0);
1059 	valueX = (int)x;
1060 	valueZ = (int)z;
1061 	delta = 1.0;
1062 	switch((valueX+valueZ*4))
1063 	{
1064 		case 0:
1065 		case 4:
1066 			z -= 1.0;
1067 			break;
1068 		case 1:
1069 		case 2:
1070 			x -= 2.0;
1071 			delta = 0.0;
1072 			break;
1073 		case 3:
1074 			x -= 3.0;
1075 			break;
1076 		case 5:
1077 		case 9:
1078 			x -= 1.0;
1079 			z -= 2.0;
1080 			break;
1081 		case 6:
1082 		case 7:
1083 			x -= 3.0;
1084 			z -= 1.0;
1085 			delta = 0.0;
1086 			break;
1087 		case 8:
1088 			z -= 2.0;
1089 			delta = 0.0;
1090 			break;
1091 		case 10:
1092 		case 14:
1093 			x -= 2.0;
1094 			z -= 3.0;
1095 			break;
1096 		case 11:
1097 			x -= 4.0;
1098 			z -= 2.0;
1099 			delta = 0.0;
1100 			break;
1101 		case 12:
1102 		case 13:
1103 			x -= 1.0;
1104 			z -= 3.0;
1105 			delta = 0.0;
1106 			break;
1107 		case 15:
1108 			x -= 3.0;
1109 			z -= 4.0;
1110 			break;
1111 	}
1112 	if (delta == 1.0)
1113 	{
1114 		x = 2*fabs( x-0.5 );
1115 		z = 2*( max(fabs( z),0.5) -0.5 );
1116 	}
1117 	else
1118 	{
1119 		x = 2*( max(fabs( x),0.5) -0.5 );
1120 		z = 2*fabs( z -0.5 );
1121 	}
1122 	answer = fabs(max(x,z)/2.0 + delta/2);
1123 	return answer;
1124 }
1125 
tiling_octa_square(const VECTOR EPoint)1126 static DBL tiling_octa_square (const VECTOR EPoint)
1127 {
1128 	/*
1129 	 ** Tiling with a square and an octagon
1130 	 */
1131 	DBL answer;
1132 	DBL x,z;
1133 	DBL dist1,dist2;
1134 	z=EPoint[Z];
1135 	z -= (SQRT2+1.0)*floor(z/(SQRT2+1.0));
1136 	z -= SQRT2_2+0.5;
1137 	z = fabs(z);
1138 	x=EPoint[X];
1139 	x -= (SQRT2+1.0)*floor(x/(SQRT2+1.0));
1140 	x -= SQRT2_2+0.5;
1141 	x = fabs(x);
1142 	if (z > x)
1143 	{
1144 		answer = x;
1145 		x = z;
1146 		z = answer;
1147 	}
1148 	if ( (x+z) < SQRT2_2)
1149 	{
1150 		/* Square tile */
1151 		return ( (x+z)/SQRT2 );
1152 	}
1153 	dist1 = 1.0-z;
1154 	dist2 = (SQRT2+SQRT2_2-(x+z))/SQRT2;
1155 
1156 	return max(0.500000000001,max(dist1,dist2)); // TODO FIXME - magic number! Use nextafter() instead (or maybe actually 0.5)
1157 }
1158 
tiling_square_triangle(const VECTOR EPoint)1159 static DBL tiling_square_triangle (const VECTOR EPoint)
1160 {
1161 	DBL x,z;
1162 	DBL slop1;
1163 	DBL dist1,dist2;
1164 	int delta;
1165 	x=EPoint[X];
1166 	z=EPoint[Z];
1167 	delta = 0;
1168 	x -= floor(x);
1169 	z -= (2.0+SQRT3)*floor(z/(SQRT3+2.0));
1170 	/* x,z is in { [0.0, 1.0 [, [0.0, 2+SQRT3 [ }
1171 	 ** but there is some symmetry to simplify the testing
1172 	 */
1173 	if (z > SQRT3_2+1.0 )
1174 	{
1175 		z -= SQRT3_2+1.0;
1176 		x += (x>0.5)?-0.5:0.5;
1177 	}
1178 	if (x > 0.5)
1179 	{
1180 		x = 1.0 - x; /* mirror */
1181 	}
1182 	z -= 1.0;
1183 	if (z > 0.0)
1184 	{ /* triangle */
1185 		if (x != 0.0)
1186 		{
1187 			slop1 = z/x;
1188 			if (slop1>SQRT3)
1189 			{
1190 				z = SQRT3_2 - z;
1191 				x = 0.5 -x;
1192 				delta = 1 - delta;
1193 			}
1194 		}
1195 		else
1196 		{
1197 			z = SQRT3_2 -z;
1198 			x = 0.5;
1199 			delta = 1 - delta;
1200 		}
1201 		dist1 = 1.0 - (2 * z * SQRT3 );
1202 		dist2 = 1.0 - ((SQRT3 * x - z) * SQRT3 );
1203 		return (delta+max(dist1,dist2))/3.0;
1204 	}
1205 	else
1206 	{ /* square */
1207 		if (z < -0.5)
1208 		{
1209 			z = -1.0 -z;
1210 		}
1211 		if (x > 0.5)
1212 		{
1213 			x = 1.0 - x;
1214 		}
1215 		dist1 = 2 + 2 * SQRT3 * fabs( x ) ;
1216 		dist2 = 2 + 2 * SQRT3 * fabs( z ) ;
1217 		dist1 = min(dist1,3.0);
1218 		dist2 = min(dist2,3.0);
1219 		return (5.0000001-min(dist1,dist2))/3.0; // TODO FIXME - magic number! Should use nextafter()
1220 	}
1221 }
1222 
tiling_hexa_triangle(const VECTOR EPoint)1223 static DBL tiling_hexa_triangle (const VECTOR EPoint)
1224 {
1225 	/*
1226 	 ** Tiling with a hexagon and 2 triangles
1227 	 */
1228 	DBL x,z;
1229 	DBL dist1,dist2;
1230 	DBL answer=0;
1231 	int delta;
1232 	x=EPoint[X];
1233 	z=EPoint[Z];
1234 	delta = 0;
1235 	x += 0.5;
1236 	x -= 2.0*floor(x/2.0);
1237 	z -= 2.0*SQRT3*floor(z/(SQRT3*2.0));
1238 	/* x,z is in { [0.0, 2.0 [, [0.0, 2*SQRT3 [ }
1239 	 ** but there is some symmetry to simplify the testing
1240 	 */
1241 	if (z > SQRT3 )
1242 	{
1243 		z -= SQRT3;
1244 		x += (x<1.0)?1.0:-1.0;
1245 	}
1246 	/*
1247 	 ** Now only [0,2[,[0,SQRT3[
1248 	 */
1249 	if (z > SQRT3_2 )
1250 	{
1251 		z = SQRT3 - z; /* mirror */
1252 		delta = 1 - delta;
1253 	}
1254 
1255 	if (x > 1.0)
1256 	{
1257 		x = 2.0 - x; /* mirror */
1258 	}
1259 	/*
1260 	 ** And now, it is even simpler :  [0,1],[0,SQRT3/2]
1261 	 ** on the bottom left corner, part of the triangle
1262 	 ** on the top right corner, center of the hexagon
1263 	 */
1264 	if ((SQRT3*x+z)<SQRT3_2)
1265 	{
1266 		/* Triangle */
1267 		dist1 = 1.0 - (z * 2 * SQRT3 );
1268 		dist2 = 1.0 + ((SQRT3 * x + z) - SQRT3_2 ) * SQRT3; /* really substracting */
1269 		answer = (delta + max(dist1,dist2))/3.0;
1270 	}
1271 	else
1272 	{
1273 		/* Hexagon */
1274 		dist1 = 2 + 2* (z * SQRT3 );
1275 		dist2 = 2 + 2* ((SQRT3 * x + z - SQRT3_2) ) * SQRT3_2 ;
1276 		answer = 5.0-min(dist1,dist2);
1277 		answer = max(answer,2.0000001); // TODO FIXME - magic number! Should use nextafter()
1278 		answer /= 3.0;
1279 	}
1280 	return answer;
1281 }
1282 
tiling_square_offset(const VECTOR EPoint)1283 static DBL tiling_square_offset (const VECTOR EPoint)
1284 {
1285 	/*
1286 	 ** Tiling with a square, offset of half size
1287 	 ** Reduce to rectangle [0,1][0,2]
1288 	 ** move x,[1,2] to [0,1][0,1] with new x = x+1/2
1289 	 */
1290 	DBL x,z;
1291 	z = EPoint[Z];
1292 	z -= 2.0*floor(z/2.0);
1293 	x = EPoint[X];
1294 	if (z > 1.0)
1295 	{
1296 		x += 0.5;
1297 		z -= 1.0;
1298 	}
1299 	x -= floor(x);
1300 	x = 2*fabs( x-0.5 );
1301 	z = 2*fabs( z-0.5 );
1302 
1303 	return max(x,z);
1304 }
1305 
tiling_square_rectangle(const VECTOR EPoint)1306 static DBL tiling_square_rectangle (const VECTOR EPoint)
1307 {
1308 	/*
1309 	 ** tiling with a central square and 4 rectangle (2x1)
1310 	 ** orbiting around the square
1311 	 ** Reduce to [0,3][0,3]
1312 	 ** then 9 cases
1313 	 **
1314 	 **  +-----+--+
1315 	 **  |     |  |
1316 	 **  +--+--+  |
1317 	 **  |  |  |  |
1318 	 **  |  +--+--+
1319 	 **  |  |     |
1320 	 **  +--+-----+
1321 	 */
1322 	DBL x,z;
1323 	DBL delta;
1324 	int valueX,valueZ;
1325 	x = EPoint[X];
1326 	x -= 3.0*floor(x/3.0);
1327 	z = EPoint[Z];
1328 	z -= 3.0*floor(z/3.0);
1329 	valueX = (int)x;
1330 	valueZ = (int)z;
1331 	delta = 2.0;
1332 	switch((valueX+valueZ*3))
1333 	{
1334 		case 0:
1335 		case 3:
1336 			z -= 1.0;
1337 			break;
1338 		case 1:
1339 		case 2:
1340 			x -= 2.0;
1341 			delta = 1.0;
1342 			break;
1343 		case 4:
1344 			x -= 1.0;
1345 			z -= 1.0;
1346 			delta = 0.0;
1347 			break;
1348 		case 5:
1349 		case 8:
1350 			x -= 2.0;
1351 			z -= 2.0;
1352 			break;
1353 		case 6:
1354 		case 7:
1355 			x -= 1.0;
1356 			z -= 2.0;
1357 			delta = 1.0;
1358 			break;
1359 	}
1360 	if (delta == 1.0)
1361 	{
1362 		x = fabs( x);
1363 		x = 2.0*( max( x,0.5) -0.5 );
1364 		z = 2.0*fabs( z -0.5 );
1365 	}
1366 	if (delta == 2.0)
1367 	{
1368 		x = 2.0*fabs( x-0.5 );
1369 		z = fabs(z);
1370 		z = 2.0*( max(z,0.5) - 0.5 );
1371 	}
1372 	if (delta == 0.0)
1373 	{
1374 		x = 2.0*fabs( x-0.5 );
1375 		z = 2.0*fabs( z-0.5 );
1376 	}
1377 	return ((max(x,z))+delta)/3.0 ;
1378 }
1379 
tiling_rectangle_square(const VECTOR EPoint)1380 static DBL tiling_rectangle_square (const VECTOR EPoint)
1381 {
1382 	/*
1383 	 ** Tiling with a central square and 4 rectangles (2x1)
1384 	 ** which turns around the square in both directions
1385 	 ** Reduce to [0,6][0,6], fold in four and back
1386 	 ** to 9 cases.
1387 	 **
1388 	 **  +-----+--+
1389 	 **  |     |  |
1390 	 **  +--+--+  |
1391 	 **  |  |  |  |
1392 	 **  |  +--+--+
1393 	 **  |  |     |
1394 	 **  +--+--+--+
1395 	 */
1396 	DBL x,z;
1397 	DBL delta;
1398 	int valueX,valueZ;
1399 	x = EPoint[X];
1400 	x -= 6.0*floor(x/6.0);
1401 	x -= 3.0;
1402 	x = fabs(x);
1403 	z = EPoint[Z];
1404 	z -= 6.0*floor(z/6.0);
1405 	z -= 3.0;
1406 	z = fabs(z);
1407 	valueX = (int)x;
1408 	valueZ = (int)z;
1409 	delta = 2.0;
1410 	switch((valueX+valueZ*3))
1411 	{
1412 		case 0:
1413 		case 3:
1414 			z -= 1.0;
1415 			break;
1416 		case 1:
1417 		case 2:
1418 			x -= 2.0;
1419 			delta = 1.0;
1420 			break;
1421 		case 4:
1422 			x -= 1.0;
1423 			z -= 1.0;
1424 			delta = 0.0;
1425 			break;
1426 		case 5:
1427 		case 8:
1428 			x -= 2.0;
1429 			z -= 2.0;
1430 			break;
1431 		case 6:
1432 		case 7:
1433 			x -= 1.0;
1434 			z -= 2.0;
1435 			delta = 1.0;
1436 			break;
1437 	}
1438 	if (delta == 1.0)
1439 	{
1440 		x = fabs( x);
1441 		x = 2.0*( max(x,0.5) -0.5 );
1442 		z = 2.0*fabs( z -0.5 );
1443 	}
1444 	if (delta == 2.0)
1445 	{
1446 		x = 2.0*fabs( x-0.5 );
1447 		z = fabs(z);
1448 		z = 2.0*( max(z,0.5) - 0.5 );
1449 	}
1450 	if (delta == 0.0)
1451 	{
1452 		x = 2.0*fabs( x-0.5 );
1453 		z = 2.0*fabs( z-0.5 );
1454 	}
1455 	return ((max(x,z))+delta)/3.0 ;
1456 }
1457 
tiling_square_internal(const VECTOR EPoint)1458 static DBL tiling_square_internal (const VECTOR EPoint)
1459 {
1460 	DBL answer=0;
1461 	DBL x,z;
1462 	DBL dist1,dist2;
1463 	int valueX,valueZ;
1464 	x=EPoint[X];
1465 	x *= SQRT2;
1466 	x -= 4.0 * floor(x/4.0);
1467 	x -= 2.0;
1468 	x = fabs(x);
1469 	z=EPoint[Z];
1470 	z *= SQRT2;
1471 	z -= 4.0 * floor(z/4.0);
1472 	z -= 2.0;
1473 	z = fabs(z);
1474 	valueX=(int)x;
1475 	valueZ=(int)z;
1476 	switch((valueX+valueZ*2))
1477 	{
1478 		case 0:
1479 			x -= 0.5;
1480 			x = max(x,0.0);
1481 			x *= 2.0;
1482 			z -= 0.5;
1483 			z = max(z,0.0);
1484 			z *= 2.0;
1485 			answer=max(x,z)/3.0;
1486 			break;
1487 		case 1:
1488 			answer=(2.0+fabs(1.5-x)*2.0)/3.0;
1489 			if (z>0.5)
1490 			{
1491 				dist2=(3.0-SQRT2*fabs(x-z))/3.0;
1492 				answer = max(answer,dist2);
1493 			}
1494 			break;
1495 		case 2:
1496 			answer=(1.0+fabs(1.5-z)*2.0)/3.0;
1497 			if (x>0.5)
1498 			{
1499 				dist2=(2.0-SQRT2*fabs(x-z))/3.0;
1500 				answer = max(answer,dist2);
1501 			}
1502 			break;
1503 		case 3:
1504 			if (x > z)
1505 			{
1506 				dist1=(2.0+fabs(1.5-x)*2.0)/3.0;
1507 				dist2=(3.0-SQRT2*fabs(z-x))/3.0;
1508 				answer=max(dist1,dist2);
1509 			}
1510 			else
1511 			{
1512 				dist1=(1.0+fabs(1.5-z)*2.0)/3.0;
1513 				dist2=(2.0-SQRT2*fabs(x-z))/3.0;
1514 				answer=max(dist1,dist2);
1515 			}
1516 			break;
1517 	}
1518 	return answer;
1519 }
1520 
tiling_square_internal_5(const VECTOR EPoint)1521 static DBL tiling_square_internal_5 (const VECTOR EPoint)
1522 {
1523 	DBL answer=0;
1524 	DBL x,z;
1525 	DBL dist1,dist2;
1526 	int mirX,mirZ;
1527 	int valueX,valueZ;
1528 	mirX=mirZ=0;
1529 	x=EPoint[X];
1530 	x *= SQRT2;
1531 	x -= 4.0 * floor(x/4.0);
1532 	x -= 2.0;
1533 	mirX = (x < 0)?1:0;
1534 	x = fabs(x);
1535 	z=EPoint[Z];
1536 	z *= SQRT2;
1537 	z -= 4.0 * floor(z/4.0);
1538 	z -= 2.0;
1539 	mirZ = (z < 0)?2:3;
1540 	z = fabs(z);
1541 	valueX=(int)x;
1542 	valueZ=(int)z;
1543 	switch((valueX+valueZ*2))
1544 	{
1545 		case 0:
1546 			x -= 0.5;
1547 			x = max(x,0.0);
1548 			x *= 2.0;
1549 			z -= 0.5;
1550 			z = max(z,0.0);
1551 			z *= 2.0;
1552 			answer=(4.000001 + max(x,z))/5.0; // TODO FIXME - magic number! Should use nextafter()
1553 			break;
1554 		case 1:
1555 			answer=fabs(1.5-x)*2.0;
1556 			if (z>0.5)
1557 			{
1558 				dist2=1.0-SQRT2*fabs(x-z);
1559 				answer = max(answer,dist2);
1560 			}
1561 			answer += mirX;
1562 			answer /= 5.0;
1563 			break;
1564 		case 2:
1565 			answer=fabs(1.5-z)*2.0;
1566 			if (x>0.5)
1567 			{
1568 				dist2=1.0-SQRT2*fabs(x-z);
1569 				answer = max(answer,dist2);
1570 			}
1571 			answer += mirZ;
1572 			answer /= 5.0;
1573 			break;
1574 		case 3:
1575 			if (x > z)
1576 			{
1577 				dist1=fabs(1.5-x)*2.0;
1578 				dist2=1.0-SQRT2*fabs(z-x);
1579 				answer=max(dist1,dist2) + mirX;
1580 			}
1581 			else
1582 			{
1583 				dist1=fabs(1.5-z)*2.0;
1584 				dist2=1.0-SQRT2*fabs(x-z);
1585 				answer=max(dist1,dist2) + mirZ;
1586 			}
1587 			answer /= 5.0;
1588 			break;
1589 	}
1590 	return answer;
1591 }
1592 
tiling_square_double(const VECTOR EPoint)1593 static DBL tiling_square_double (const VECTOR EPoint)
1594 {
1595 	/*
1596 	 ** Tiling with a square (1x1) and a square (2x2)
1597 	 ** Reduce to [0,5][0,5] then 25 cases
1598 	 **
1599 	 **  +--+     +--+--+
1600 	 **     |     |  |
1601 	 **     +--+--+--+
1602 	 **     |  |     |
1603 	 **  +--+--+     +--+
1604 	 **  |     |     |  |
1605 	 **  +     +--+--+--+
1606 	 **  |     |  |     |
1607 	 **  +--+--+--+     +
1608 	 **  |  |     |     |
1609 	 **  +--+     +--+--+
1610 	 */
1611 	DBL x,z;
1612 	DBL delta;
1613 	int valueX,valueZ;
1614 	x = EPoint[X];
1615 	x -= 5.0*floor(x/5.0);
1616 	z = EPoint[Z];
1617 	z -= 5.0*floor(z/5.0);
1618 	valueX = (int)x;
1619 	valueZ = (int)z;
1620 	delta = 0.50000001; // TODO FIXME - magic number! Should use nextafter()
1621 	switch((valueX+valueZ*5))
1622 	{
1623 		case 0:
1624 			delta = 0.0;
1625 			break;
1626 		case 1:
1627 		case 2:
1628 			x -= 2.0;
1629 			break;
1630 		case 3:
1631 		case 4:
1632 		case 8:
1633 		case 9:
1634 			x -= 4.0;
1635 			z -= 1.0;
1636 			break;
1637 		case 5 :
1638 		case 6 :
1639 		case 10:
1640 		case 11:
1641 			z -= 2.0;
1642 			x -= 1.0;
1643 			break;
1644 		case 7:
1645 			delta = 0.0;
1646 			x -= 2.0;
1647 			z -= 1.0;
1648 			break;
1649 		case 12:
1650 		case 13:
1651 		case 17:
1652 		case 18:
1653 			x -= 3.0;
1654 			z -= 3.0;
1655 			break;
1656 		case 14:
1657 			x -= 4.0;
1658 			z -= 2.0;
1659 			delta = 0.0;
1660 			break;
1661 		case 15:
1662 		case 20:
1663 			z -= 4.0;
1664 			break;
1665 		case 16:
1666 			x -= 1.0;
1667 			z -= 3.0;
1668 			delta = 0.0;
1669 			break;
1670 		case 21:
1671 		case 22:
1672 			x -= 2.0;
1673 			z -= 5.0;
1674 			break;
1675 		case 23:
1676 			x -= 3.0;
1677 			z -= 4.0;
1678 			delta = 0.0;
1679 			break;
1680 		case 24:
1681 		case 19:
1682 			x -= 5.0;
1683 			z -= 4.0;
1684 			break;
1685 	}
1686 	if (delta)
1687 	{
1688 		x = fabs(x);
1689 		x = 2*( max(x,0.5) -0.5 );
1690 		z = fabs(z);
1691 		z = 2*( max(z,0.5) -0.5 );
1692 	}
1693 	else
1694 	{
1695 		x = 2*fabs( x-0.5 );
1696 		z = 2*fabs( z-0.5 );
1697 	}
1698 	return fabs((max(x,z))/2.0+delta);
1699 }
1700 
tiling_hexa_square_triangle(const VECTOR EPoint)1701 static DBL tiling_hexa_square_triangle (const VECTOR EPoint)
1702 {
1703 	/*
1704 	 ** tiling with 1 hexagon, squares and triangles
1705 	 */
1706 	DBL x,z;
1707 	DBL dist1,dist2;
1708 	DBL answer=0;
1709 
1710 	x=EPoint[X];
1711 	z=EPoint[Z];
1712 	x += 0.5;
1713 	x -= (3.0+SQRT3)*floor(x/(3.0+SQRT3));
1714 	z -= 2.0*(1.0+SQRT3)*floor(z/((SQRT3+1.0)*2.0));
1715 	/* x,z is in { [0.0, 3.0+SQRT3 [, [0.0, 2*(1+SQRT3) [ }
1716 	 ** but there is some symmetry to simplify the testing
1717 	 */
1718 	if (x > (SQRT3_2+1.5))
1719 	{
1720 		x -= (SQRT3_2+1.5);
1721 		z += (z < SQRT3+1.0)?(SQRT3_2+0.5):(-1*(SQRT3_2+0.5));
1722 	}
1723 	if (z > (SQRT3+1.0) )
1724 	{
1725 		z -= SQRT3+1.0;
1726 	}
1727 	/*
1728 	 ** Now only [0, SQRT3/2+1.5 ], [0,SQRT3+1.0]
1729 	 */
1730 	if (z > (0.5+SQRT3_2 ) )
1731 	{
1732 		z = SQRT3+1.0 - z; /* mirror */
1733 	}
1734 
1735 	if (x > (1.0+SQRT3_2) )
1736 	{
1737 		x = SQRT3+2.0 - x; /* mirror */
1738 	}
1739 	/*
1740 	 ** And now, it is even simpler :  [0,1+(SQRT3/2)],[0,1+(SQRT3/2)]
1741 	 ** on the top right corner, center of the hexagon
1742 	 ** on the bottom right, middle of square, a triangle on the left
1743 	 ** on the top left corner, half a triangle
1744 	 ** bottom
1745 	 */
1746 	if (((SQRT3*x+z)<(SQRT3_2+2.0))&&(x < 0.5+SQRT3_2))
1747 	{
1748 		/* Triangle or square */
1749 		/* rotate in the lower part */
1750 		z -= 0.5 + SQRT3_2 ;
1751 		x -= 1.0 + SQRT3_2 ;
1752 		dist1 = ( x / 2.0 ) - ( z * SQRT3_2 );
1753 		dist2 = ( z / 2.0 ) + ( x * SQRT3_2 );
1754 		z = dist2;
1755 		x = dist1;
1756 		z += 0.5 + SQRT3_2 ;
1757 		x += 1.0 + SQRT3_2 ;
1758 		if (z < 0)
1759 		{
1760 			z *= -1;
1761 		}
1762 		if (x > (1.0+SQRT3_2) )
1763 		{
1764 			x = SQRT3+2.0 - x; /* mirror */
1765 		}
1766 	}
1767 	if ((!((SQRT3*x+z)<(SQRT3_2+2.0)))&&(!(z < 0.5)))
1768 	{
1769 		/* Hexagon */
1770 		z -= 0.5;
1771 		x -= SQRT3_2;
1772 		z= fabs(z);
1773 		x= fabs(x);
1774 		dist1 = 2* z * SQRT3 ;
1775 		dist2 = ((SQRT3 * x + z ) ) * SQRT3 - 1.5;
1776 		answer = 3.0-min(dist1,dist2);
1777 		answer = max(answer,2.0000001); // TODO FIXME - magic number! Should use nextafter()
1778 		answer /= 3.0;
1779 		return answer;
1780 	}
1781 	if (z < 0.5 )
1782 	{
1783 		if ( x > SQRT3_2+0.5)
1784 		{
1785 			/* square */
1786 			x -= SQRT3_2+0.5;
1787 			z -= 0.5;
1788 			dist1 = 1.0 + z*2 * SQRT3;
1789 			dist2 = 1.0 - x*2*SQRT3;
1790 			dist1 = max(dist1,0.0);
1791 			dist2 = max(dist2,0.0);
1792 			answer = max(dist1,dist2)/3.0;
1793 		}
1794 		else
1795 		{
1796 			/* triangle */
1797 			x -= SQRT3_2 + 0.5;
1798 			x = fabs(x);
1799 			dist2 = ((SQRT3 * z + x) ) * SQRT3 +0.5;
1800 			dist1 = 2.0 - (x * 2.0 * SQRT3 );
1801 			answer = (max(dist1,dist2))/3.0;
1802 		}
1803 	}
1804 	return answer;
1805 }
1806 
tiling_hexa_square_triangle_6(const VECTOR EPoint)1807 static DBL tiling_hexa_square_triangle_6 (const VECTOR EPoint)
1808 {
1809 	/*
1810 	 ** tiling with 1 hexagon, squares and triangles
1811 	 ** all tiles get its own colour (according to its orientation)
1812 	 ** 1 hexagon, 3 squares, 2 triangles
1813 	 */
1814 	DBL x,z;
1815 	DBL dist1,dist2;
1816 	DBL answer=0;
1817 	int mirX=0;
1818 	int mirZ=0;
1819 	int rota=0;
1820 	x=EPoint[X];
1821 	z=EPoint[Z];
1822 	x += 0.5;
1823 	x -= (3.0+SQRT3)*floor(x/(3.0+SQRT3));
1824 	z -= 2.0*(1.0+SQRT3)*floor(z/((SQRT3+1.0)*2.0));
1825 	/* x,z is in { [0.0, 3.0+SQRT3 [, [0.0, 2*(1+SQRT3) [ }
1826 	 ** but there is some symmetry to simplify the testing
1827 	 */
1828 	if (x > (SQRT3_2+1.5))
1829 	{
1830 		x -= (SQRT3_2+1.5);
1831 		z += (z < SQRT3+1.0)?(SQRT3_2+0.5):(-1*(SQRT3_2+0.5));
1832 	}
1833 	if (z > (SQRT3+1.0) )
1834 	{
1835 		z -= SQRT3+1.0;
1836 	}
1837 	/*
1838 	 ** Now only [0, SQRT3/2+1.5 ], [0,SQRT3+1.0]
1839 	 */
1840 	if (z > (0.5+SQRT3_2 ) )
1841 	{
1842 		z = SQRT3+1.0 - z; /* mirror */
1843 		mirZ = 1 - mirZ;
1844 	}
1845 
1846 	if (x > (1.0+SQRT3_2) )
1847 	{
1848 		x = SQRT3+2.0 - x; /* mirror */
1849 		mirX = 1 - mirX;
1850 	}
1851 	/*
1852 	 ** And now, it is even simpler :  [0,1+(SQRT3/2)],[0,1+(SQRT3/2)]
1853 	 ** on the top right corner, center of the hexagon
1854 	 ** on the bottom right, middle of square, a triangle on the left
1855 	 ** on the top left corner, half a triangle
1856 	 ** bottom
1857 	 */
1858 	if (((SQRT3*x+z)<(SQRT3_2+2.0))&&(x < 0.5+SQRT3_2))
1859 	{
1860 		/* Triangle or square */
1861 		/* rotate in the lower part */
1862 		z -= 0.5 + SQRT3_2 ;
1863 		x -= 1.0 + SQRT3_2 ;
1864 		dist1 = ( x / 2.0 ) - ( z * SQRT3_2 );
1865 		dist2 = ( z / 2.0 ) + ( x * SQRT3_2 );
1866 		z = dist2;
1867 		x = dist1;
1868 		z += 0.5 + SQRT3_2 ;
1869 		x += 1.0 + SQRT3_2 ;
1870 		rota = 1 - rota;
1871 		if (z < 0)
1872 		{
1873 			z *= -1;
1874 		}
1875 		if (x > (1.0+SQRT3_2) )
1876 		{
1877 			x = SQRT3+2.0 - x; /* mirror */
1878 			mirX = 1 - mirX;
1879 			mirZ = 1 - mirZ;
1880 		}
1881 	}
1882 	if ((!((SQRT3*x+z)<(SQRT3_2+2.0)))&&(!(z < 0.5)))
1883 	{
1884 		/* Hexagon */
1885 		z -= 0.5;
1886 		x -= SQRT3_2;
1887 		z= fabs(z);
1888 		x= fabs(x);
1889 		dist1 = 2* z * SQRT3 ;
1890 		dist2 = ((SQRT3 * x + z ) ) * SQRT3 - 1.5;
1891 		answer = 6.0 - min(dist1,dist2);
1892 		answer = max(answer,5.000001); // TODO FIXME - magic number! Should use nextafter()
1893 		answer /= 6.0;
1894 		return answer;
1895 	}
1896 	if (z < 0.5 )
1897 	{
1898 		if ( x > SQRT3_2+0.5)
1899 		{
1900 			/* square */
1901 			x -= SQRT3_2+0.5;
1902 			z -= 0.5;
1903 			dist1 = 1.0 + z*2 * SQRT3;
1904 			dist2 = 1.0 - x*2*SQRT3;
1905 			dist1 = max(dist1,0.0);
1906 			dist2 = max(dist2,0.0);
1907 			answer = (max(dist1,dist2) +  rota * (1.000001 + ((mirX + mirZ) % 2)))/6.0; // TODO FIXME - magic number! Should use nextafter()
1908 		}
1909 		else
1910 		{
1911 			/* triangle */
1912 			x -= SQRT3_2 + 0.5;
1913 			x = fabs(x);
1914 			dist2 = ((SQRT3 * z + x) ) * SQRT3 +0.5;
1915 			dist1 = 2.0 - (x * 2.0 * SQRT3 );
1916 			answer = max(dist1,dist2);
1917 			if ((rota + mirX)%2)
1918 			{
1919 				answer = 2.0 + answer;
1920 			}
1921 			else
1922 			{
1923 				answer = 3.0 + answer;
1924 			}
1925 			answer /= 6.0;
1926 		}
1927 	}
1928 	return answer;
1929 }
1930 
tiling_rectangle_pair(const VECTOR EPoint)1931 static DBL tiling_rectangle_pair (const VECTOR EPoint)
1932 {
1933 
1934 	/*
1935 	 ** Tiling with 2 rectangles (2x1)
1936 	 ** Reduce to [0,4][0,4] then 16 cases
1937 	 **
1938 	 **  +-----+--+--+
1939 	 **  |     |  |  |
1940 	 **  +-----+  +  +
1941 	 **  |     |  |  |
1942 	 **  +-----+--+--+
1943 	 **  |  |  |     |
1944 	 **  |  |  +-----+
1945 	 **  |  |  |     |
1946 	 **  +--+--+-----+
1947 	 */
1948 	DBL x,z;
1949 	DBL delta;
1950 	DBL answer;
1951 	int valueX,valueZ;
1952 	x=EPoint[X];
1953 	z=EPoint[Z];
1954 	x -= 4.0*floor(x/4.0);
1955 	z -= 4.0*floor(z/4.0);
1956 	valueX = (int)x;
1957 	valueZ = (int)z;
1958 	delta = 1.0;
1959 	switch((valueX+valueZ*4))
1960 	{
1961 		case 0:
1962 		case 4:
1963 			z -= 1.0;
1964 			break;
1965 		case 1:
1966 		case 5:
1967 			x -= 1.0;
1968 			z -= 1.0;
1969 			break;
1970 		case 2:
1971 		case 3:
1972 			x -= 3.0;
1973 			delta = 0.0;
1974 			break;
1975 		case 6:
1976 		case 7:
1977 			x -= 3.0;
1978 			z -= 1.0;
1979 			delta = 0.0;
1980 			break;
1981 		case 8:
1982 		case 9:
1983 			x -= 1.0;
1984 			z -= 2.0;
1985 			delta = 0.0;
1986 			break;
1987 		case 12:
1988 		case 13:
1989 			x -= 1.0;
1990 			z -= 3.0;
1991 			delta = 0.0;
1992 			break;
1993 		case 10:
1994 		case 14:
1995 			x -= 2.0;
1996 			z -= 3.0;
1997 			break;
1998 		case 11:
1999 		case 15:
2000 			x -= 3.0;
2001 			z -= 3.0;
2002 			break;
2003 	}
2004 	if (delta == 1.0)
2005 	{
2006 		x = 2*fabs( x-0.5 );
2007 		z = 2*( max(fabs( z),0.5) -0.5 );
2008 	}
2009 	else
2010 	{
2011 		x = 2*( max(fabs( x),0.5) -0.5 );
2012 		z = 2*fabs( z -0.5 );
2013 	}
2014 	answer = fabs((max(x,z)+delta)/2.0);
2015 	return answer;
2016 }
2017 
tiling_hexa_tri_right(const VECTOR EPoint)2018 static DBL tiling_hexa_tri_right (const VECTOR EPoint)
2019 {
2020 	DBL x,z;
2021 	DBL answer;
2022 	DBL slop1;
2023 	DBL dist1,dist2;
2024 	int zzof;
2025 	int delta;
2026 	x=EPoint[X];
2027 	z=EPoint[Z];
2028 	/* First, resume to a simple pattern */
2029 	zzof = z / SQRT3_2;
2030 	zzof /= 3;
2031 	if (z < 0)
2032 	{
2033 		zzof -= 1;
2034 	}
2035 	x += zzof / 2.0; /* right handed */
2036 	z -= 3*SQRT3_2*floor(z/(3*SQRT3_2));
2037 	x += 7.0;
2038 	x -= 7.0 *floor(x/7.0);
2039 	if ((x > 4.5) && (z > SQRT3))
2040 	{
2041 		x -= 4.5;
2042 		z -= SQRT3_2;
2043 	}
2044 	if ((x > 5.0) && (z < SQRT3_2))
2045 	{
2046 		x -= 5;
2047 		z += SQRT3;
2048 	}
2049 	if ((x > 2.5) && (z < SQRT3))
2050 	{
2051 		x -= 2.5;
2052 		z += SQRT3_2;
2053 	}
2054 	delta = 0;
2055 	zzof = z /SQRT3_2;
2056 	if ( zzof == 2)
2057 	{
2058 		zzof = 1;
2059 		z = 2 * SQRT3 - z;
2060 		delta = 1 - delta;
2061 	}
2062 	if ( (!zzof) || (x > 2.0) ||
2063 	     (( z + SQRT3*x < SQRT3) || ( SQRT3*x -z > SQRT3)) )
2064 	{
2065 		/* triangle */
2066 		x -= 1.0 *floor(x/1.0);
2067 		z -= SQRT3*floor(z/SQRT3);
2068 		/* x,z is in { [0.0, 1.0 [, [0.0, SQRT3 [ }
2069 		 ** but there is some symmetry to simplify the testing
2070 		 */
2071 		if (z > SQRT3_2 )
2072 		{
2073 			z = SQRT3 - z; /* mirror */
2074 			delta = 1 - delta;
2075 		}
2076 		if (x > 0.5)
2077 		{
2078 			x = 1.0 - x; /* mirror */
2079 		}
2080 		if (x != 0.0)
2081 		{
2082 			slop1 = z/x;
2083 			if (slop1>SQRT3)
2084 			{
2085 				z = SQRT3_2 - z;
2086 				x = 0.5 -x;
2087 				delta = 1 - delta;
2088 			}
2089 		}
2090 		else
2091 		{
2092 			z = SQRT3_2 -z;
2093 			x = 0.5;
2094 			delta = 1 - delta;
2095 		}
2096 		dist1 = 1.0 - (z * 2 * SQRT3 );
2097 		dist2 = 1.0 - ((SQRT3 * x - z) * SQRT3 );
2098 		return (delta+max(dist1,dist2))/3.0;
2099 	}
2100 	else
2101 	{ /* hexagon */
2102 		z -= SQRT3_2;
2103 		if (x > 1.0)
2104 		{
2105 			x = 2.0 - x; /* mirror */
2106 		}
2107 		/* Hexagon */
2108 		dist1 = 2 + 2* (z * SQRT3 );
2109 		dist2 = 2 + 2* ((SQRT3 * x + z - SQRT3_2) ) * SQRT3_2 ;
2110 		answer = 5.0-min(dist1,dist2);
2111 		answer = max(answer, 2.000001); // TODO FIXME - magic number! Should use nextafter()
2112 		answer /= 3.0;
2113 		return answer;
2114 	}
2115 }
2116 
tiling_hexa_tri_left(const VECTOR EPoint)2117 static DBL tiling_hexa_tri_left (const VECTOR EPoint)
2118 {
2119 	DBL x,z;
2120 	DBL slop1;
2121 	DBL dist1,dist2;
2122 	DBL answer;
2123 	int zzof;
2124 	int delta;
2125 	x=EPoint[X];
2126 	z=EPoint[Z];
2127 	/* First, resume to a simple pattern */
2128 	zzof = z / SQRT3_2;
2129 	zzof /= 3;
2130 	if (z < 0)
2131 	{
2132 		zzof -= 1;
2133 	}
2134 	x -= zzof / 2.0; /* left handed */
2135 	z -= 3*SQRT3_2*floor(z/(3*SQRT3_2));
2136 	x += 7.0;
2137 	x -= 7.0 *floor(x/7.0);
2138 	if ((x > 2.0) && (z < SQRT3_2))
2139 	{
2140 		x -= 2.0;
2141 		z += SQRT3;
2142 	}
2143 	if ((x > 4.5) && (z < SQRT3))
2144 	{
2145 		x -= 4.5;
2146 		z += SQRT3_2;
2147 	}
2148 	if ((x > 2.5) && (z > SQRT3))
2149 	{
2150 		x -= 2.5;
2151 		z -= SQRT3_2;
2152 	}
2153 	delta = 0;
2154 	zzof = z /SQRT3_2;
2155 	if ( zzof == 2)
2156 	{
2157 		zzof = 1;
2158 		z = 2 * SQRT3 - z;
2159 		delta = 1 - delta;
2160 	}
2161 	if ( (!zzof) || (x > 2.0) ||
2162 	     (( z + SQRT3*x < SQRT3) || ( SQRT3*x -z > SQRT3)) )
2163 	{
2164 		/* triangle */
2165 		x -= 1.0 *floor(x/1.0);
2166 		z -= SQRT3*floor(z/SQRT3);
2167 		/* x,z is in { [0.0, 1.0 [, [0.0, SQRT3 [ }
2168 		 ** but there is some symmetry to simplify the testing
2169 		 */
2170 		if (z > SQRT3_2 )
2171 		{
2172 			z = SQRT3 - z; /* mirror */
2173 			delta = 1 - delta;
2174 		}
2175 		if (x > 0.5)
2176 		{
2177 			x = 1.0 - x; /* mirror */
2178 		}
2179 		if (x != 0.0)
2180 		{
2181 			slop1 = z/x;
2182 			if (slop1>SQRT3)
2183 			{
2184 				z = SQRT3_2 - z;
2185 				x = 0.5 -x;
2186 				delta = 1 - delta;
2187 			}
2188 		}
2189 		else
2190 		{
2191 			z = SQRT3_2 -z;
2192 			x = 0.5;
2193 			delta = 1 - delta;
2194 		}
2195 		dist1 = 1.0 - (z * 2 * SQRT3 );
2196 		dist2 = 1.0 - ((SQRT3 * x - z) * SQRT3 );
2197 		return (delta+max(dist1,dist2))/3.0;
2198 	}
2199 	else
2200 	{ /* hexagon */
2201 		z -= SQRT3_2;
2202 		if (x > 1.0)
2203 		{
2204 			x = 2.0 - x; /* mirror */
2205 		}
2206 		/* Hexagon */
2207 		dist1 = 2 + 2* (z * SQRT3 );
2208 		dist2 = 2 + 2* ((SQRT3 * x + z - SQRT3_2) ) * SQRT3_2 ;
2209 		answer = 5.0-min(dist1,dist2);
2210 		answer = max(answer, 2.000001); // TODO FIXME - magic number! Should use nextafter()
2211 		answer /= 3.0;
2212 		return answer;
2213 	}
2214 }
2215 
tiling_square_tri(const VECTOR EPoint)2216 static DBL tiling_square_tri (const VECTOR EPoint)
2217 {
2218 	DBL x,z;
2219 	DBL slop1;
2220 	DBL dist1,dist2;
2221 	int delta;
2222 	int gamma,beta;
2223 	int xflop,zflop;
2224 	x=EPoint[X];
2225 	z=EPoint[Z];
2226 	delta = 0;
2227 	gamma = 0;
2228 	beta = 0;
2229 	x -= (1.0+SQRT3)*floor(x/(1.0+SQRT3));
2230 	z -= (1.0+SQRT3)*floor(z/(1.0+SQRT3));
2231 	/* x,z is in { [0.0, SQRT3+1.0 [, [0.0, SQRT3+1.0 [ }
2232 	 ** but there is some symmetry to simplify the testing
2233 	 */
2234 	if (z > 0.5 + SQRT3_2 )
2235 	{
2236 		z = 1.0 + SQRT3 - z; /* mirror */
2237 		delta = 1 - delta;
2238 	}
2239 	if (x > 0.5 + SQRT3_2)
2240 	{
2241 		x = 1.0 + SQRT3 - x; /* mirror */
2242 		delta = 1 - delta;
2243 		beta = 1;
2244 	}
2245 	/* x,z is in { [0.0, (SQRT3+1)/2 ], [0.0, (SQRT3+1)/2 ] }
2246 	 ** but there is still a symmetry and a rotation
2247 	 */
2248 	xflop = ( 2.0 * x + (SQRT3 -1.0)* 2.0 * z / ( SQRT3 + 1.0) > (SQRT3)) ? 1: 0;
2249 	zflop = ( 2.0 * z * SQRT3 + (SQRT3 -3.0)* 2.0 * x / ( SQRT3 + 1.0) > (SQRT3)) ? 1: 0;
2250 	switch (xflop + 2*zflop)
2251 	{
2252 		case 0: /* do nothing */
2253 			gamma = 2 * beta;
2254 			break;
2255 		case 1: /* rotate clockwise */
2256 			gamma = beta ? 1 + 2 * delta : 3 - 2 *delta;
2257 			slop1 = x;
2258 			x = z;
2259 			z = SQRT3_2 + 0.5 - slop1;
2260 			break;
2261 		case 2: /* rotate normal */
2262 			gamma = beta ? 3 - 2 * delta : 1 + 2 *delta;
2263 			slop1 = z;
2264 			z = x;
2265 			x = SQRT3_2 +0.5 - slop1;
2266 			break;
2267 		case 3: /* symmetry */
2268 			gamma = beta ? 0: 2 ;
2269 			x = SQRT3_2+0.5 -x;
2270 			z = SQRT3_2+0.5 -z;
2271 			break;
2272 	}
2273 
2274 	if (x == 0.0)
2275 	{
2276 		z = 0.0;
2277 		x = 0.0;
2278 	}
2279 	slop1 = (z * 2 * SQRT3) - SQRT3 + x * 2;
2280 	if (slop1 < 0)
2281 	{
2282 		/* triangle */
2283 
2284 		dist1 = -1.5 / SQRT3 * slop1;
2285 		dist2 = 2.0 * x * SQRT3;
2286 		slop1 = min(dist1,dist2);
2287 		return (gamma+1.0-slop1)/6.0;
2288 	}
2289 	else
2290 	{
2291 		/* square */
2292 		slop1 *= 1.5 / SQRT3;
2293 		slop1 = min(slop1,1.0);
2294 		if (delta)
2295 		{
2296 			slop1 *= -1;
2297 			slop1 += 6.0;
2298 			slop1 /= 6.0;
2299 			slop1 = max(slop1,5.000001/6.0); // TODO FIXME - magic number! Should use nextafter()
2300 			slop1 = min(slop1,1.0);
2301 		}
2302 		else
2303 		{
2304 			slop1 *= -1;
2305 			slop1 += 5.0;
2306 			slop1 /= 6.0;
2307 			slop1 = min(slop1,5.0/6.0);
2308 			slop1 = max(slop1,4.000001/6.0); // TODO FIXME - magic number! Should use nextafter()
2309 		}
2310 		return slop1;
2311 	}
2312 }
2313 
tiling_dodeca_tri(const VECTOR EPoint)2314 static DBL tiling_dodeca_tri (const VECTOR EPoint)
2315 {
2316 	DBL x,z;
2317 	DBL dist1,dist2,dist3,dist4,ret_value;
2318 	DBL tmpx,tmpz;
2319 	int toggle=0; /* switched each time a triangle get toggled */
2320 	x=EPoint[X];
2321 	z=EPoint[Z];
2322 	x -= (2.0+SQRT3)*floor(x/(2.0+SQRT3));
2323 	z -= (3.0+2.0*SQRT3)*floor(z/(3.0+2.0*SQRT3));
2324 	/* x,z is in { [0.0, SQRT3+2.0 [, [0.0, 2*SQRT3+3.0 [ }
2325 	 ** but there is some symmetry to simplify the testing
2326 	 */
2327 	if (z > SQRT3+1.5)
2328 	{
2329 		/* translate */
2330 		z -= SQRT3+1.5;
2331 		x += (x<(1.0+SQRT3_2) ? 1.0: -1.0)*(1.0+SQRT3_2);
2332 	}
2333 	if (x > 1.0+SQRT3_2)
2334 	{
2335 		x = 2.0 + SQRT3 -x;
2336 	}
2337 	if (z > 1.0+SQRT3_2)
2338 	{
2339 		z = 2.0 + SQRT3 -z;
2340 		toggle = 1 - toggle;
2341 	}
2342 	dist2 = x - SQRT3_2 - 0.5 + z * SQRT3;
2343 	if (dist2 < 0.0)
2344 	{
2345 		tmpx = x;
2346 		tmpz = z;
2347 		x = (1.0+SQRT3)/4.0 + 0.5 * tmpx - SQRT3_2 * tmpz ;
2348 		z = (3.0+SQRT3)/4.0 - SQRT3_2 * tmpx - 0.5 * tmpz ;
2349 		dist2 *= -1.0;
2350 	}
2351 	dist1 = (z * 3.0 ); /* from the bottom line */
2352 	dist3 =  z - SQRT3_2 - 0.5 + x * SQRT3;
2353 	dist3 *= SQRT3;
2354 	dist2 *= SQRT3;
2355 	dist4 = (x * 3.0 ); /* from the vertical line */
2356 	if (dist3 < 0.0)
2357 	{
2358 		ret_value = max(dist3,-1.0);
2359 		ret_value += 1+toggle;
2360 		ret_value /= 3.0;
2361 	}
2362 	else
2363 	{
2364 		/* dodecagon */
2365 		ret_value = min(dist1,dist2);
2366 		ret_value = min(ret_value,dist3);
2367 		ret_value = min(ret_value,dist4);
2368 		ret_value = min(ret_value,1.0);
2369 		ret_value = 3.0000001 - ret_value; // TODO FIXME - magic number! Should use nextafter()
2370 
2371 		ret_value /= 3.0;
2372 	}
2373 	return ret_value;
2374 }
2375 
tiling_dodeca_hex(const VECTOR EPoint)2376 static DBL tiling_dodeca_hex (const VECTOR EPoint)
2377 {
2378 	DBL x,z;
2379 	DBL dist1,dist2,dist3,dist4,ret_value;
2380 	DBL dist5,dist6,dist7;
2381 	DBL tmpx,tmpz;
2382 	x=EPoint[X];
2383 	z=EPoint[Z];
2384 	x -= (3.0+SQRT3)*floor(x/(3.0+SQRT3));
2385 	z -= (3.0+3.0*SQRT3)*floor(z/(3.0+3.0*SQRT3));
2386 	/* x,z is in { [0.0, SQRT3+3.0 [, [0.0, 3*SQRT3+3.0 [ }
2387 	 ** but there is some symmetry to simplify the testing
2388 	 */
2389 	if (z > 1.5*SQRT3+1.5)
2390 	{
2391 		/* translate */
2392 		z -= 1.5*SQRT3+1.5;
2393 		x += (x<(1.5+SQRT3_2) ? 1.0: -1.0)*(1.5+SQRT3_2);
2394 	}
2395 	if (x > 1.5+SQRT3_2)
2396 	{
2397 		x = 3.0 + SQRT3 -x;
2398 	}
2399 	if (z > 1.0+SQRT3)
2400 	{
2401 		z = 2.0 + 2.0*SQRT3 -z;
2402 	}
2403 	dist2 = x - SQRT3_2 - 1.5 + z * SQRT3;
2404 	if (dist2 < 0.0)
2405 	{
2406 		tmpx = x;
2407 		tmpz = z;
2408 		x = (3.0+SQRT3)/4.0 + 0.5 * tmpx - SQRT3_2 * tmpz ;
2409 		z = (3.0+3.0*SQRT3)/4.0 - SQRT3_2 * tmpx - 0.5 * tmpz ;
2410 	}
2411 	dist2 = x - SQRT3_2 - 2.5 + z * SQRT3;
2412 	dist1 = (z * 2.0 ) - SQRT3; /* from the bottom line */
2413 	dist3 = z - 1.5*SQRT3 - 0.5 + x * SQRT3;
2414 	dist4 = ((x-0.5) * 2.0 ); /* from the vertical line */
2415 	if ( (dist2 >= 0.0) &&
2416 	     (dist1 >= 0.0) &&
2417 	     (dist3 >= 0.0) &&
2418 	     (dist4 >= 0.0) )
2419 	{
2420 		/* dodecagon */
2421 		ret_value = min(dist1,dist2);
2422 		ret_value = min(ret_value,dist3);
2423 		ret_value = min(ret_value,dist4);
2424 		ret_value = min(ret_value,1.0);
2425 		ret_value = 3.000001 - ret_value; // TODO FIXME - magic number! Should use nextafter()
2426 	}
2427 	else
2428 	{
2429 		dist5 = 2*z - 2*SQRT3 - 1.0;
2430 		if (dist5 >= 0)
2431 		{
2432 			dist4 *= -1.0;
2433 			ret_value = min(dist5,dist4);
2434 			ret_value = 2.0 - ret_value;
2435 		}
2436 		else
2437 		{
2438 			dist6 = SQRT3 * x - z -SQRT3_2 +0.5;
2439 			dist7 = dist6 - 2.0;
2440 			switch((dist6 >= 0?0:1)+(dist7 >= 0.0 ?2:0))
2441 			{
2442 				case 1: /* left hexagon */
2443 					dist5 *= -1.0;
2444 					dist6 *= -1.0;
2445 					dist3 *= -1.0;
2446 					ret_value = min(dist6,dist3);
2447 					ret_value = min(ret_value,dist5);
2448 					ret_value = min(ret_value,1.0);
2449 					ret_value = 1.0 - ret_value;
2450 					break;
2451 				case 2: /* bottom hexagon */
2452 					dist1 *= -1.0;
2453 					ret_value = min(dist7,dist1);
2454 					ret_value = min(ret_value,1.0);
2455 					ret_value = 1.0 - ret_value;
2456 					break;
2457 				case 0:
2458 				default: /* slanted square */
2459 					dist2 *= -1.0;
2460 					dist7 *= -1.0;
2461 					ret_value = min(dist6,dist2);
2462 					ret_value = min(ret_value,dist7);
2463 					ret_value = 2.0 - ret_value;
2464 					break;
2465 			}
2466 		}
2467 	}
2468 	ret_value /= 3.0;
2469 	return ret_value;
2470 }
2471 
tiling_dodeca_hex_5(const VECTOR EPoint)2472 static DBL tiling_dodeca_hex_5 (const VECTOR EPoint)
2473 {
2474 	DBL x,z;
2475 	DBL dist1,dist2,dist3,dist4,ret_value;
2476 	DBL dist5,dist6,dist7;
2477 	DBL tmpx,tmpz;
2478 	int mirX,mirZ,rota;
2479 	mirX = mirZ = rota = 0;
2480 	x=EPoint[X];
2481 	z=EPoint[Z];
2482 	x -= (3.0+SQRT3)*floor(x/(3.0+SQRT3));
2483 	z -= (3.0+3.0*SQRT3)*floor(z/(3.0+3.0*SQRT3));
2484 	/* x,z is in { [0.0, SQRT3+3.0 [, [0.0, 3*SQRT3+3.0 [ }
2485 	 ** but there is some symmetry to simplify the testing
2486 	 */
2487 	if (z > 1.5*SQRT3+1.5)
2488 	{
2489 		/* translate */
2490 		z -= 1.5*SQRT3+1.5;
2491 		x += (x<(1.5+SQRT3_2) ? 1.0: -1.0)*(1.5+SQRT3_2);
2492 	}
2493 	if (x > 1.5+SQRT3_2)
2494 	{
2495 		x = 3.0 + SQRT3 -x;
2496 		mirX = 1 - mirX;
2497 	}
2498 	if (z > 1.0+SQRT3)
2499 	{
2500 		z = 2.0 + 2.0*SQRT3 -z;
2501 		mirZ = 1 - mirZ;
2502 	}
2503 	dist2 = x - SQRT3_2 - 1.5 + z * SQRT3;
2504 	if (dist2 < 0.0)
2505 	{
2506 		tmpx = x;
2507 		tmpz = z;
2508 		x = (3.0+SQRT3)/4.0 + 0.5 * tmpx - SQRT3_2 * tmpz ;
2509 		z = (3.0+3.0*SQRT3)/4.0 - SQRT3_2 * tmpx - 0.5 * tmpz ;
2510 	}
2511 	dist2 = x - SQRT3_2 - 2.5 + z * SQRT3;
2512 	dist1 = (z * 2.0 ) - SQRT3; /* from the bottom line */
2513 	dist3 = z - 1.5*SQRT3 - 0.5 + x * SQRT3;
2514 	dist4 = ((x-0.5) * 2.0 ); /* from the vertical line */
2515 	if ( (dist2 >= 0.0) &&
2516 	     (dist1 >= 0.0) &&
2517 	     (dist3 >= 0.0) &&
2518 	     (dist4 >= 0.0) )
2519 	{
2520 		/* dodecagon */
2521 		ret_value = min(dist1,dist2);
2522 		ret_value = min(ret_value,dist3);
2523 		ret_value = min(ret_value,dist4);
2524 		ret_value = min(ret_value,1.0);
2525 		ret_value = 5.000001 - ret_value; // TODO FIXME - magic number! Should use nextafter()
2526 	}
2527 	else
2528 	{
2529 		dist5 = 2*z - 2*SQRT3 - 1.0;
2530 		if (dist5 >= 0)
2531 		{
2532 			dist4 *= -1.0;
2533 			ret_value = min(dist5,dist4);
2534 			ret_value = 2.0 - ret_value;
2535 		}
2536 		else
2537 		{
2538 			dist6 = SQRT3 * x - z -SQRT3_2 +0.5;
2539 			dist7 = dist6 - 2.0;
2540 			switch((dist6 >= 0?0:1)+(dist7 >= 0.0 ?2:0))
2541 			{
2542 				case 1: /* left hexagon */
2543 					dist5 *= -1.0;
2544 					dist6 *= -1.0;
2545 					dist3 *= -1.0;
2546 					ret_value = min(dist6,dist3);
2547 					ret_value = min(ret_value,dist5);
2548 					ret_value = min(ret_value,1.0);
2549 					ret_value = 1.0 - ret_value;
2550 					break;
2551 				case 2: /* bottom hexagon */
2552 					dist1 *= -1.0;
2553 					ret_value = min(dist7,dist1);
2554 					ret_value = min(ret_value,1.0);
2555 					ret_value = 1.0 - ret_value;
2556 					break;
2557 				case 0:
2558 				default: /* slanted square */
2559 					dist2 *= -1.0;
2560 					dist7 *= -1.0;
2561 					ret_value = min(dist6,dist2);
2562 					ret_value = min(ret_value,dist7);
2563 					ret_value = (mirZ + mirX) %2 + 3.0 - ret_value;
2564 					break;
2565 			}
2566 		}
2567 	}
2568 	ret_value /= 5.0;
2569 	return ret_value;
2570 }
2571 
2572 static DBL tiling_penrose_halfkite (DBL pX, DBL pZ, int depth, bool rhombs);
2573 static DBL tiling_penrose_halfdart (DBL pX, DBL pZ, int depth, bool rhombs);
2574 
tiling_penrose_halfkite(DBL pX,DBL pZ,int depth,bool rhombs)2575 static DBL tiling_penrose_halfkite (DBL pX, DBL pZ, int depth, bool rhombs)
2576 {
2577 	DBL x = pX;
2578 	DBL z = fabs(pZ);
2579 
2580 	if (depth > 0)
2581 	{
2582 		if (z < (x - INVPHI) * TAN144)
2583 		{
2584 			return tiling_penrose_halfdart(x*PHI, z*PHI, depth-1, rhombs);
2585 		}
2586 		else
2587 		{
2588 			x -= COS36;
2589 			z -= SIN36;
2590 			DBL rotX = x*COS108 - z*SIN108;
2591 			DBL rotZ = z*COS108 + x*SIN108;
2592 			return tiling_penrose_halfkite(rotX*PHI, rotZ*PHI, depth-1, rhombs);
2593 		}
2594 	}
2595 	else if (rhombs)
2596 	{
2597 		if (z < (x - INVPHI) * TAN72)
2598 		{
2599 			DBL dist1 = fabs( SIN72  * (x-INVPHI) - COS72  * z ) * 5.55; // TODO FIXME - the factor is just an empiric value
2600 			DBL dist2 = fabs( SIN108 * (x-1)      - COS108 * z ) * 5.55;
2601 			return max3(1.0-dist1/2,1.0-dist2/2,0.5+TILING_EPSILON);
2602 		}
2603 		else
2604 		{
2605 			DBL dist1 = fabs( z )                              * 5.55; // TODO FIXME - the factor is just an empiric value
2606 			DBL dist2 = fabs( SIN72 * (x-INVPHI) - COS72 * z ) * 5.55;
2607 			return min(max3(0.5-dist1/2,0.5-dist2/2,0.0),0.5-TILING_EPSILON);
2608 		}
2609 	}
2610 	else
2611 	{
2612 		DBL dist1 = fabs( SIN36  *  x    - COS36  * z ) * 4.46; // TODO FIXME - the factor is just an empiric value
2613 		DBL dist2 = fabs( SIN108 * (x-1) - COS108 * z ) * 4.46;
2614 		return min(max3(0.5-dist1/2,0.5-dist2/2,0.0),0.5-TILING_EPSILON);
2615 	}
2616 }
2617 
tiling_penrose_halfdart(DBL pX,DBL pZ,int depth,bool rhombs)2618 static DBL tiling_penrose_halfdart (DBL pX, DBL pZ, int depth, bool rhombs)
2619 {
2620 	DBL x = pX;
2621 	DBL z = fabs(pZ);
2622 
2623 	if (depth > 0)
2624 	{
2625 		if (z < (x - INVPHI) * TAN108)
2626 		{
2627 			DBL rotX = x*COS36 + z*SIN36;
2628 			DBL rotZ = z*COS36 - x*SIN36;
2629 			return tiling_penrose_halfkite(rotX*PHI, rotZ*PHI, depth-1, rhombs);
2630 		}
2631 		else
2632 		{
2633 			x -= 1;
2634 			DBL rotX = x*COS144 + z*SIN144;
2635 			DBL rotZ = z*COS144 - x*SIN144;
2636 			return tiling_penrose_halfdart(rotX*PHI, rotZ*PHI, depth-1, rhombs);
2637 		}
2638 	}
2639 	else if (rhombs)
2640 	{
2641 		DBL dist1 = fabs( SIN36  *  x    - COS36  * z ) * 5.55; // TODO FIXME - the factor is just an empiric value
2642 		DBL dist2 = fabs( SIN144 * (x-1) - COS144 * z ) * 5.55;
2643 		return min(max3(0.5-dist1/2,0.5-dist2/2,0.0),0.5-TILING_EPSILON);
2644 	}
2645 	else
2646 	{
2647 		DBL dist1 = fabs( z )                           * 4.46; // TODO FIXME - the factor is just an empiric value
2648 		DBL dist2 = fabs( SIN144 * (x-1) - COS144 * z ) * 4.46;
2649 		return max3(1.0-dist1/2,1.0-dist2/2,0.5+TILING_EPSILON);
2650 	}
2651 }
2652 
tiling_penrose(const VECTOR EPoint,bool rhombs,bool centerFlag)2653 static DBL tiling_penrose (const VECTOR EPoint, bool rhombs, bool centerFlag)
2654 {
2655 	// Penrose tiling
2656 	// rhombs=false: P2 ("kite and dart") Penrose tiling
2657 	//   centerFlag=false: 5 darts at center forming a star
2658 	//   centerFlag=true:  5 kites at center forming a regular decagon ("sun")
2659 	// rhombs=true:  P3 ("rhombus") Penrose tiling
2660 	//   centerFlag=false: 5 wide rhombs at center, surrounded by 5 narrow rhombs to form a regular decagon
2661 	//   centerFlag=true:  5 wide rhombs at center, surrounded by 10 narrow rhombs to form a pointed star
2662 
2663 	DBL x,z;
2664 	x = EPoint[X];
2665 	z = EPoint[Z];
2666 
2667 	DBL r = sqrt(x*x+z*z);
2668 	if (r <= EPSILON)
2669 		return 1.0;
2670 
2671 	// exploit trivial mirror symmetry
2672 	z = fabs(z);
2673 
2674 	// exploit rotational & mirror symmetry
2675 	if (x < r * COS36)
2676 	{
2677 		DBL rotSin;
2678 		DBL rotCos;
2679 		if (x < r *COS108)
2680 		{
2681 			rotSin = SIN144;
2682 			rotCos = COS144;
2683 		}
2684 		else
2685 		{
2686 			rotSin = SIN72;
2687 			rotCos = COS72;
2688 		}
2689 		DBL rotX = x*rotCos + z*rotSin;
2690 		DBL rotZ = z*rotCos - x*rotSin;
2691 
2692 		x =      rotX;
2693 		z = fabs(rotZ);
2694 	}
2695 
2696 	if (rhombs)
2697 	{
2698 		x *= INVPHI;
2699 		z *= INVPHI;
2700 	}
2701 
2702 	DBL dist = fabs( SIN108 * x - COS108 * z ) / COS18;
2703 
2704 	int depth = max(0, (int)ceil(log(dist)/log(SQRPHI)));
2705 
2706 	x *= pow(INVSQRPHI,depth);
2707 	z *= pow(INVSQRPHI,depth);
2708 
2709 	if (depth % 2)
2710 	{
2711 		DBL rotX = x*COS36 + z*SIN36;
2712 		DBL rotZ = z*COS36 - x*SIN36;
2713 		x = rotX;
2714 		z = fabs(rotZ);
2715 	}
2716 
2717 	depth *= 2;
2718 
2719 	if (centerFlag)
2720 	{
2721 		depth += 1;
2722 		x *= INVPHI;
2723 		z *= INVPHI;
2724 	}
2725 
2726 	return tiling_penrose_halfkite(x, z, depth, rhombs);
2727 }
2728 
2729 static DBL tiling_penrose1_pentagon1 (DBL pX, DBL pZ, int depth);
2730 static DBL tiling_penrose1_pentagon2 (DBL pX, DBL pZ, int depth, bool insideQuad);
2731 static DBL tiling_penrose1_pentagon3 (DBL pX, DBL pZ, int depth, bool insideWedge);
2732 static DBL tiling_penrose1_star (DBL pX, DBL pZ, int depth);
2733 static DBL tiling_penrose1_boat (DBL pX, DBL pZ, int depth, bool insideWedge);
2734 static DBL tiling_penrose1_diamond (DBL pX, DBL pZ, int depth, bool sideA);
2735 
tiling_penrose1_pentagon_symmetry(DBL & x,DBL & z,DBL r)2736 static void tiling_penrose1_pentagon_symmetry(DBL& x, DBL& z, DBL r)
2737 {
2738 	z = fabs(z);
2739 
2740 	if (x < r * COS36)
2741 	{
2742 		DBL rotSin;
2743 		DBL rotCos;
2744 		if (x < r *COS108)
2745 		{
2746 			rotSin = SIN144;
2747 			rotCos = COS144;
2748 		}
2749 		else
2750 		{
2751 			rotSin = SIN72;
2752 			rotCos = COS72;
2753 		}
2754 		DBL rotX = x*rotCos + z*rotSin;
2755 		DBL rotZ = z*rotCos - x*rotSin;
2756 
2757 		x =      rotX;
2758 		z = fabs(rotZ);
2759 	}
2760 }
2761 
tiling_penrose1_pentagon_symmetry(DBL & x,DBL & z)2762 static void tiling_penrose1_pentagon_symmetry(DBL& x, DBL& z)
2763 {
2764 	tiling_penrose1_pentagon_symmetry (x, z, sqrt(x*x+z*z));
2765 }
2766 
tiling_penrose1_pentagon_dist(DBL pX,DBL pZ)2767 static DBL tiling_penrose1_pentagon_dist (DBL pX, DBL pZ)
2768 {
2769 	return fabs( pX - 0.5/TAN36 ) * 5.55 * INVPHI; // TODO FIXME - the factor is just an empiric value
2770 }
2771 
tiling_penrose1_pentagon1(DBL pX,DBL pZ,int depth)2772 static DBL tiling_penrose1_pentagon1 (DBL pX, DBL pZ, int depth)
2773 {
2774 	DBL x = pX;
2775 	DBL z = fabs(pZ);
2776 
2777 	tiling_penrose1_pentagon_symmetry (x, z);
2778 
2779 	if (depth > 0)
2780 	{
2781 		if (z < (x - 0.5/TAN36) * TAN54 + 0.5)
2782 		{
2783 			DBL rotX = x - 0.5/TAN36 - INVPHI*0.5*COS72/SIN36;
2784 			DBL rotZ = z;
2785 			return tiling_penrose1_pentagon2 (rotX*PHI, rotZ*PHI, depth-1, false);
2786 		}
2787 		else
2788 		{
2789 			DBL rotX = x*COS36 + z*SIN36;
2790 			DBL rotZ = z*COS36 - x*SIN36;
2791 			return tiling_penrose1_star (rotX*PHI, rotZ*PHI, depth-1);
2792 		}
2793 	}
2794 	else
2795 	{
2796 		DBL dist = tiling_penrose1_pentagon_dist (x, z);
2797 		return min(max(1.0/6-dist/6,0.0),1.0/6-TILING_EPSILON);
2798 	}
2799 }
2800 
tiling_penrose1_pentagon2(DBL pX,DBL pZ,int depth,bool insideQuad)2801 static DBL tiling_penrose1_pentagon2 (DBL pX, DBL pZ, int depth, bool insideQuad)
2802 {
2803 	DBL x = pX;
2804 	DBL z = fabs(pZ);
2805 
2806 	if (depth > 0)
2807 	{
2808 		if (insideQuad)
2809 		{
2810 			if (z < (x - INVSQRPHI*0.5/SIN36) * TAN54)
2811 			{
2812 				DBL rotX = x - 0.5/SIN36;
2813 				DBL rotZ = z;
2814 				return tiling_penrose1_pentagon1 (rotX*PHI, rotZ*PHI, depth-1);
2815 			}
2816 			else if (z < (x - INVSQRPHI*0.5/SIN36) * TAN162)
2817 			{
2818 				DBL rotX = -x;
2819 				DBL rotZ =  z;
2820 				return tiling_penrose1_diamond (rotX*PHI, rotZ*PHI, depth-1, true);
2821 			}
2822 			else
2823 			{
2824 				DBL rotX = x*COS108 - z*SIN108 + INVPHI*0.5/SIN36;
2825 				DBL rotZ = z*COS108 + x*SIN108;
2826 				return tiling_penrose1_pentagon2 (rotX*PHI, rotZ*PHI, depth-1, true);
2827 			}
2828 		}
2829 		else if (z < (x + 0.5/SIN36) * TAN18)
2830 		{
2831 			DBL rotX = x + 0.5/SIN36 - INVSQRPHI*0.5/SIN36;
2832 			DBL rotZ = z;
2833 			return tiling_penrose1_diamond (rotX*PHI, rotZ*PHI, depth-1, false);
2834 		}
2835 		else
2836 		{
2837 			DBL rotX = - (x*COS36 + z*SIN36) - COS72*0.5/SIN36;
2838 			DBL rotZ =   (z*COS36 - x*SIN36) - SIN72*0.5/SIN36;
2839 			return tiling_penrose1_pentagon3 (rotX*PHI, rotZ*PHI, depth-1, false);
2840 		}
2841 	}
2842 	else
2843 	{
2844 		tiling_penrose1_pentagon_symmetry (x, z);
2845 		DBL dist = tiling_penrose1_pentagon_dist (x, z);
2846 		return min(max(2.0/6-dist/6,1.0/6+TILING_EPSILON),2.0/6-TILING_EPSILON);
2847 	}
2848 }
2849 
tiling_penrose1_pentagon3(DBL pX,DBL pZ,int depth,bool insideWedge)2850 static DBL tiling_penrose1_pentagon3 (DBL pX, DBL pZ, int depth, bool insideWedge)
2851 {
2852 	DBL x = pX;
2853 	DBL z = fabs(pZ);
2854 
2855 	if (depth > 0)
2856 	{
2857 		if (insideWedge && (x > INVSQRPHI*0.5*COS72/SIN36))
2858 		{
2859 			DBL rotX = -(x - INVSQRPHI*0.5*COS72/SIN36 - INVPHI*0.5/TAN36);
2860 			DBL rotZ =   z;
2861 			return tiling_penrose1_pentagon2 (rotX*PHI, rotZ*PHI, depth-1, true);
2862 			return 1.0/6 + TILING_EPSILON;
2863 		}
2864 		else if (!insideWedge && (x < 0.5*COS108/SIN36))
2865 		{
2866 			DBL rotX = x*COS144 + z*SIN144 - 0.5/SIN36;
2867 			DBL rotZ = z*COS144 - x*SIN144;
2868 			return tiling_penrose1_pentagon2 (rotX*PHI, rotZ*PHI, depth-1, false);
2869 		}
2870 		else if (!insideWedge && (z > (x - INVSQRPHI*0.5/SIN36)*TAN126))
2871 		{
2872 			DBL rotX = - (x*COS36 - z*SIN36) - COS72*0.5/SIN36;
2873 			DBL rotZ =   (z*COS36 + x*SIN36) - SIN72*0.5/SIN36;
2874 			return tiling_penrose1_pentagon3 (rotX*PHI, rotZ*PHI, depth-1, false);
2875 		}
2876 		else
2877 		{
2878 			return tiling_penrose1_boat (x*PHI, z*PHI, depth-1, insideWedge);
2879 		}
2880 	}
2881 	else
2882 	{
2883 		tiling_penrose1_pentagon_symmetry (x, z);
2884 		DBL dist = tiling_penrose1_pentagon_dist (x, z);
2885 		return min(max(3.0/6-dist/6,2.0/6+TILING_EPSILON),3.0/6-TILING_EPSILON);
2886 	}
2887 }
2888 
tiling_penrose1_star(DBL pX,DBL pZ,int depth)2889 static DBL tiling_penrose1_star (DBL pX, DBL pZ, int depth)
2890 {
2891 	DBL x = pX;
2892 	DBL z = fabs(pZ);
2893 
2894 	if (depth > 0)
2895 	{
2896 		if (x < INVPHI * 0.5/TAN36)
2897 		{
2898 			return tiling_penrose1_pentagon1(x*PHI, z*PHI, depth-1);
2899 		}
2900 		else
2901 		{
2902 			DBL rotX = -(x - INVPHI/TAN36);
2903 			DBL rotZ =   z;
2904 			return tiling_penrose1_pentagon3(rotX*PHI, rotZ*PHI, depth-1, true);
2905 		}
2906 	}
2907 	else
2908 	{
2909 		DBL dist = fabs( SIN162 * (x - PHI*0.5/SIN36) - COS162 * z) * 5.55 * INVPHI; // TODO FIXME - the factor is just an empiric value
2910 		return min(max(4.0/6-dist/6,3.0/6+TILING_EPSILON),4.0/6-TILING_EPSILON);
2911 	}
2912 }
2913 
tiling_penrose1_boat(DBL pX,DBL pZ,int depth,bool insideWedge)2914 static DBL tiling_penrose1_boat (DBL pX, DBL pZ, int depth, bool insideWedge)
2915 {
2916 	DBL x = pX;
2917 	DBL z = fabs(pZ);
2918 
2919 	if (depth > 0)
2920 	{
2921 		if (insideWedge && (x > PHI*0.5*COS108/SIN36))
2922 		{
2923 			DBL rotX = -x;
2924 			DBL rotZ =  z;
2925 			return tiling_penrose1_pentagon1 (rotX*PHI, rotZ*PHI, depth-1);
2926 		}
2927 		else
2928 		{
2929 			DBL rotX, rotZ;
2930 			if (insideWedge)
2931 			{
2932 				rotX = x;
2933 				rotZ = z;
2934 			}
2935 			else
2936 			{
2937 				rotX = x*COS72 - z*SIN72;
2938 				rotZ = z*COS72 + x*SIN72;
2939 			}
2940 			rotX += 0.5/SIN36;
2941 			return tiling_penrose1_pentagon3 (rotX*PHI, rotZ*PHI, depth-1, true);
2942 		}
2943 	}
2944 	else
2945 	{
2946 		DBL dist1 = fabs( x - INVPHI*0.5*COS72/SIN36) * 5.55 * INVPHI; // TODO FIXME - the factor is just an empiric value
2947 		x = -x;
2948 		tiling_penrose1_pentagon_symmetry (x, z);
2949 		DBL dist2 = fabs( SIN162 * (x - PHI*0.5/SIN36) - COS162 * z) * 5.55 * INVPHI; // TODO FIXME - the factor is just an empiric value
2950 		return min(max3(5.0/6-dist1/6,5.0/6-dist2/6,4.0/6+TILING_EPSILON),5.0/6-TILING_EPSILON);
2951 	}
2952 }
2953 
tiling_penrose1_diamond(DBL pX,DBL pZ,int depth,bool sideA)2954 static DBL tiling_penrose1_diamond (DBL pX, DBL pZ, int depth, bool sideA)
2955 {
2956 	DBL x = pX;
2957 	DBL z = fabs(pZ);
2958 
2959 	if (depth > 0)
2960 	{
2961 		if (sideA)
2962 		{
2963 			return tiling_penrose1_pentagon1(x*PHI, z*PHI, depth-1);
2964 		}
2965 		else
2966 		{
2967 			return tiling_penrose1_pentagon3(x*PHI, z*PHI, depth-1, true);
2968 		}
2969 	}
2970 	else
2971 	{
2972 		DBL dist = fabs( SIN18 * (x + INVPHI*0.5/SIN36) - COS18 * z) * 5.55 * INVPHI; // TODO FIXME - the factor is just an empiric value
2973 		return min(max(6.0/6-dist/6,5.0/6+TILING_EPSILON),6.0/6-TILING_EPSILON);
2974 	}
2975 }
2976 
tiling_penrose1(const VECTOR EPoint,bool centerFlag)2977 static DBL tiling_penrose1 (const VECTOR EPoint, bool centerFlag)
2978 {
2979 	// Penrose P1 ("pentagon, star, boat and diamond") tiling
2980 	//   centerFlag=false: pentagon at center
2981 	//   centerFlag=true:  pentagram (star) at center
2982 
2983 	DBL x,z;
2984 	x = EPoint[X];
2985 	z = EPoint[Z];
2986 
2987 	DBL r = sqrt(x*x+z*z);
2988 	if (r <= EPSILON)
2989 		return 1.0;
2990 
2991 	tiling_penrose1_pentagon_symmetry (x, z, r);
2992 
2993 	DBL dist = x * 2 * TAN36;
2994 
2995 	int depth = max(0, (int)ceil(log(dist)/log(SQRPHI*SQRPHI)));
2996 
2997 	x *= pow(INVSQRPHI*INVSQRPHI,depth);
2998 	z *= pow(INVSQRPHI*INVSQRPHI,depth);
2999 
3000 	depth *= 4;
3001 
3002 	/*
3003 	if (centerFlag)
3004 	{
3005 		depth += 1;
3006 		x *= INVPHI;
3007 		z *= INVPHI;
3008 	}
3009 	*/
3010 
3011 	return tiling_penrose1_pentagon1(x, z, depth);
3012 }
3013 
3014 static unsigned char digon[]={ 0x0E, 0x0B };
3015 static unsigned char trigon[][6]=
3016 {
3017 	{ 0x0D, 0x05, 0x07 , 0x0D, 5,7 },
3018 	{ 0x0E, 0x0D, 0x16, 0x49, 7, 0x0B }
3019 };
3020 
3021 static unsigned char tetragon[][16]=
3022 {
3023 	{ 0x0D, 5, 5, 7, 0x0D, 5, 5, 7, 0x0D, 5, 5, 7, 0x0D, 5, 5, 7 },
3024 	{ 0x0E, 0x0D, 5, 0x16, 0x49, 5, 7, 0x0B, 0x0E, 0x0D, 5, 0x16, 0x49, 5, 7, 0x0B },
3025 	{ 0x0D, 0x34, 0x7, 0x0B, 0x07, 0x0B, 0x0D, 0x34, 0x0D, 0x34, 0x7, 0x0B, 0x07, 0x0B, 0x0D, 0x34},
3026 	{ 0x0C, 0x06, 0x0C, 0x06, 0x09, 0x03, 0x09, 0x03, 0x0C, 0x06, 0x0C, 0x06, 0x09, 0x03, 0x09, 0x03 },
3027 	{ 7, 0x2C, 7, 0x2C, 0x0D, 0x83, 0x0D, 0x83, 0x2C, 7, 0x2C,7, 0x83, 0x0D, 0x83, 0x0D  }
3028 };
3029 
3030 static unsigned char pentagon[][10]=
3031 {
3032 	{ 0x0D, 5,5,5,7 , 0x0D, 5,5,5,7},
3033 	{ 0x0E, 0x0D,5,5,0x16, 0x49, 5,5,7,0x0B},
3034 	{ 7, 0x0C, 6, 0x0C, 0x24, 0x0D, 0x81, 3, 9, 3 },
3035 	{ 0x0D, 5, 0x34, 7, 0x0B, 15,15,15,15,15 },
3036 	{ 0x0D, 0xF0, 7, 0x0B, 0x0E , 15,15,15,15,15 },
3037 	{ 0x0E, 0x0A, 0x49, 5, 7, 0x0D, 5, 0x16, 0x0A, 0x0B },
3038 	{ 0x0B, 0x0E, 0x49, 0x16, 0x49, 7, 0x0D, 0x16, 0x49, 0x16 },
3039 	{ 0x2C, 5, 0x16, 0x0B, 0x0E, 0x0B, 0x0E, 0x49, 5, 0x83 },
3040 	{ 0x0E, 0x49, 5, 0x16, 0x0B, 0x0E, 0x49, 5, 0x16, 0x0B },
3041 	{ 0x0E, 0x0D, 0xC1, 0x16, 0x0B, 0x49, 0x34, 7, 0x0B, 0x0E },
3042 	{ 7, 0x2C, 5, 7, 0x2C, 0x0D, 0x83, 0x0D, 5, 0x83 },
3043 	{ 0x0D, 0x34, 7, 0x0D, 0xC1, 7, 0x0A, 0x0B, 0x0E, 0x0A}
3044 };
3045 
3046 static unsigned char hexagon[][12]=
3047 {
3048 	{ 0x0D, 5, 5, 5, 5, 7, 0x0D, 5, 5, 5, 5, 7},
3049 	{ 0x2C, 5, 5, 5, 7, 0x0E, 0x0B, 0x0D, 5, 5, 5, 0x83 },
3050 	{ 0x0D, 0x34, 5, 5, 7, 0x0E, 7, 0x0B, 0x0D, 5, 5, 0xC1 },
3051 	{ 0x0D, 5, 0x34, 5, 7, 0x0E, 5, 7, 0x0B, 0x0D, 5, 0xC1 },
3052 	{ 0x0D, 0x83, 0x2C, 5, 5, 7 , 15,15,15,15,15,15},
3053 
3054 	{ 0x0C, 0x24, 5, 7, 0x0C, 6, 9, 3, 0x0D, 5, 0x81, 3 },
3055 	{ 7, 0x0C, 6, 0x0D, 0x14, 0x24, 0x0D, 0x81, 0x41, 7, 9, 3},
3056 	{ 0x0D, 5, 0x83, 0x2C, 5, 7, 15,15,15,15,15,15},
3057 	{ 7, 0x0C, 0x24, 7, 0x0C, 0x24, 0x0D, 0x81, 3, 0x0D, 0x81, 3},
3058 	{ 0x0C, 4, 6, 0x0C, 4, 6, 9, 1, 3, 9, 1, 3 },
3059 
3060 	{ 0x0E, 0x0D, 0x14, 6, 0x48, 6, 9, 0x12, 9, 0x41, 7, 0x0B},
3061 	{ 0x0D, 5, 0x16, 0x49, 0x16, 0x0B, 15,15,15,15,15,15},
3062 	{ 0x0D, 0x34, 5, 0x16, 0x0E, 0x0B, 0x0E, 0x0B, 0x49, 5, 0xC1, 7},
3063 	{ 0x0D, 0x34, 7, 0x16, 0x0A, 0x0D, 0x0A, 0x49, 7, 0xC1, 7, 0x0D},
3064 	{ 0x0D, 0x14, 0x82, 0x0E, 9, 3, 15,15,15,15,15,15},
3065 
3066 	{ 0x0E, 0x0D, 0xD0, 6, 9, 3, 15,15,15,15,15,15},
3067 	{ 0x0D, 0xF0, 5, 7, 0x0E, 0x0B, 0x0E, 0x0B, 0x0D, 5, 0xF0, 7},
3068 	{ 0x0E, 0x0B, 0x0D, 5, 5, 0x92, 0x68, 5, 5, 7, 0x0E, 0x0B},
3069 	{ 0x0E, 0x49, 5, 0x16, 0x0A, 0x0B, 15,15,15,15,15,15},
3070 	{ 0x0B, 0x2C, 5, 5, 0x83, 0x0E, 15,15,15,15,15,15},
3071 
3072 	{ 0x0B, 0x0A, 0x2C, 5, 5, 7, 15,15,15,15,15,15},
3073 	{ 0x2C, 5, 5, 0x16, 0x0B, 0x0E, 0x0E, 0x0B, 5, 0x83, 0x49, 5},
3074 	{ 0x0A, 0x0D, 0xC1, 0x16, 0x49, 0x34, 7, 0x0A, 0x0E, 0x0B, 0x0E, 0x0B},
3075 	{ 0x0D, 0x16, 0x0D, 5, 0x92, 0x0B, 0x0E, 0x68, 5, 7, 0x49, 7},
3076 	{ 0x0D, 0x16, 0x0D, 0x16, 0x16, 0x49, 0x16, 0x49, 0x49, 7, 0x49, 7},
3077 
3078 	{ 0x0C, 6, 0x0C, 6, 9, 0x12, 9, 0x12, 7, 0x49, 7, 0x49 },
3079 	{ 0x2C, 7, 0x2C, 7, 0x92, 0x0D, 0x92, 0x0D, 0x49, 7, 0x49, 7},
3080 	{ 0x0E, 0x49, 5, 0x16, 0x49, 7, 15,15,15,15,15,15},
3081 	{ 0x0D, 0x16, 0x0B, 0x0E, 0x49, 7, 0x16, 0x49, 5, 0x83, 0x2C, 5},
3082 	{ 7, 0x0E, 0x49, 0x34, 7, 0x49, 0x0D, 0xC1, 0x16, 0x0B, 0x0D, 0x16},
3083 
3084 	{ 0x2C, 5, 0xC1, 7, 0x0E, 0x0B, 0x0B, 0x0D, 0x34, 5, 0x83, 0x0E },
3085 	{ 0x0E, 0x0B, 0x0D, 0x34, 0xC1, 7, 15,15,15,15,15,15},
3086 	{ 0x0D, 5, 0x16, 0x2C, 7, 0x0A, 0x0A, 0x0D, 0x83, 0x49, 5, 7 },
3087 	{ 0x2C, 0xC1, 5, 7, 0x0E, 0x0B, 0x0E, 0x0B, 0x0D, 5, 0x34, 0x83 },
3088 	{ 0x0A, 0x0D, 5, 0x92, 0x68, 5, 7, 0x0A, 0x0B, 0x0E, 0x0E, 0x0B}
3089 };
3090 
tetragonal(const VECTOR EPoint,const TPATTERN * TPat)3091 static DBL tetragonal (const VECTOR EPoint, const TPATTERN *TPat)
3092 {
3093 	unsigned char how;
3094 	long xv,zv;
3095 	DBL return_value=0;
3096 	DBL value;
3097 	DBL value1;
3098 	DBL value2;
3099 	DBL x,y;
3100 	int lng=0;
3101 	zv = floor(y=EPoint[Z]);
3102 	xv = floor(x=EPoint[X]);
3103 	switch(TPat->Vals.Pavement.Tile)
3104 	{
3105 		case 6:
3106 			switch(TPat->Vals.Pavement.Number-1)
3107 			{
3108 				case 0:
3109 				case 1:
3110 				case 2:
3111 				case 3:
3112 				case 5:
3113 				case 6:
3114 				case 8:
3115 				case 9:
3116 					xv %= 6; if (xv < 0) { xv += 6 ;}
3117 					zv &= 0x01;
3118 					lng = 6;
3119 					break;
3120 				case 4:
3121 				case 7:
3122 				case 19:
3123 				case 20:
3124 					lng = 0;
3125 					zv %= 6; if (zv <0) { zv += 6;}
3126 					xv += 5*zv;
3127 					xv %= 6; if (xv <0) { xv += 6; }
3128 					break;
3129 				case 11:
3130 				case 18:
3131 				case 27:
3132 					lng = 0;
3133 					zv %= 6; if (zv <0) { zv += 6;}
3134 					xv += zv;
3135 					xv %= 6; if (xv <0) { xv += 6; }
3136 					break;
3137 				case 10:
3138 				case 12:
3139 				case 21:
3140 				case 22:
3141 				case 24:
3142 				case 25:
3143 				case 26:
3144 					lng = 4;
3145 					xv &= 0x03;
3146 					zv %= 3; if (zv<0) { zv += 3;}
3147 					break;
3148 				case 13:
3149 				case 32:
3150 					lng = 3;
3151 					zv &= 0x03;
3152 					xv %= 3; if (xv < 0) { xv += 3; }
3153 					break;
3154 				case 14:
3155 					lng = 3;
3156 					zv %= 6; if (zv < 0) { zv += 6; }
3157 					xv += 2 * (zv/2);
3158 					zv &= 0x01;
3159 					xv %= 3; if (xv < 0) { xv += 3; }
3160 					break;
3161 				case 15:
3162 					lng = 2;
3163 					xv %= 6; if (xv < 0) { xv+= 6; }
3164 					zv += (xv/2);
3165 					xv &= 0x01;
3166 					zv %= 3; if (zv<0) { zv += 3;}
3167 					break;
3168 				case 16:
3169 				case 17:
3170 					lng = 6;
3171 					zv %= 12; if (zv <0) { zv+=12; }
3172 					xv += zv/2;
3173 					zv &= 0x01;
3174 					xv %= 6; if (xv < 0) { xv+= 6; }
3175 					break;
3176 				case 23:
3177 				case 28:
3178 					lng = 6;
3179 					zv %= 12; if (zv <0) { zv+=12; }
3180 					xv += 4* (zv/2);
3181 					zv &= 0x01;
3182 					xv %= 6; if (xv < 0) { xv+= 6; }
3183 					break;
3184 				case 29:
3185 				case 30:
3186 					lng = 6;
3187 					zv &= 0x03;
3188 					xv += 3* (zv/2);
3189 					zv &= 0x01;
3190 					xv %= 6; if (xv < 0) { xv+= 6; }
3191 					break;
3192 				case 31:
3193 					lng = 0;
3194 					zv %= 3; if (zv <0) { zv+=3; }
3195 					xv += 4* zv;
3196 					xv %= 6; if (xv < 0) { xv+= 6; }
3197 					break;
3198 				case 33:
3199 					lng = 0;
3200 					zv %= 12; if (zv < 0) { zv+= 12; }
3201 					xv += 7*zv;
3202 					xv %= 12; if (xv < 0) { xv+= 12; }
3203 					break;
3204 				case 34:
3205 					lng = 4;
3206 					zv %= 6; if (zv<0) { zv+=6;}
3207 					xv += 2 * (zv/3);
3208 					xv &= 0x03;
3209 					zv %= 3; if (zv<0) { zv += 3;}
3210 					break;
3211 			}
3212 			how = hexagon[TPat->Vals.Pavement.Number-1][xv+zv*lng];
3213 			break;
3214 		case 5:
3215 			switch(TPat->Vals.Pavement.Number-1)
3216 			{
3217 				case 0:
3218 				case 1:
3219 					xv %= 5; if (xv <0) { xv += 5 ; }
3220 					zv &= 0x01;
3221 					break;
3222 				case 2:
3223 				case 9:
3224 					zv %= 10; if (zv <0) { zv += 10;}
3225 					xv += 3 * (zv/2);
3226 					xv %= 5; if (xv <0) { xv += 5;  }
3227 					zv &= 0x01;
3228 					break;
3229 				case 10:
3230 					zv %= 10; if (zv <0) { zv += 10;}
3231 					xv += 4*(zv/2);
3232 					xv %= 5; if (xv <0) { xv += 5 ;  }
3233 					zv &= 0x01;
3234 					break;
3235 				case 3:
3236 					zv %= 5; if (zv <0) { zv += 5;}
3237 					xv += 2*zv;
3238 					xv %= 5; if (xv <0) { xv += 5 ;  }
3239 					zv = 0x0;
3240 					break;
3241 				case 4:
3242 					zv %= 5; if (zv <0) { zv += 5;}
3243 					xv += 2 * zv;
3244 					xv %= 5; if (xv <0) { xv += 5;  }
3245 					zv = 0x00;
3246 					break;
3247 				case 5:
3248 				case 6:
3249 				case 8:
3250 					zv %= 10; if (zv <0) { zv += 10;}
3251 					xv += zv;
3252 					xv %= 10; if (xv <0) { xv += 10;  }
3253 					zv = 0x00;
3254 					break;
3255 				case 11:
3256 					zv %= 10; if (zv <0) { zv += 10;}
3257 					xv += 8* zv;
3258 					xv %= 10; if (xv <0) { xv += 10;  }
3259 					zv = 0x00;
3260 					break;
3261 				case 7:
3262 					zv %= 10; if (zv <0) { zv += 10;}
3263 					xv += 3*zv;
3264 					xv %= 10; if (xv <0) { xv += 10;  }
3265 					zv = 0x00;
3266 					break;
3267 			}
3268 			how = pentagon[TPat->Vals.Pavement.Number-1][xv+zv*5];
3269 			break;
3270 		case 4:
3271 			xv &= 0x03;
3272 			zv &= 0x03;
3273 			how = tetragon[TPat->Vals.Pavement.Number-1][xv+zv*4];
3274 			break;
3275 		case 3:
3276 			xv %= 3; if (xv < 0) { xv += 3; }
3277 			zv &= 0x01;
3278 			how = trigon[TPat->Vals.Pavement.Number-1][xv+zv*3];
3279 			break;
3280 		case 2:
3281 			zv &= 0x01;
3282 			how = digon[zv];
3283 			break;
3284 		case 1:
3285 		default:
3286 			how = 0x0F;
3287 			break;
3288 	}
3289 	/*
3290 	 **   5---1---6
3291 	 **   |       |
3292 	 **   4       2
3293 	 **   |       |
3294 	 **   8---3---7
3295 	 */
3296 	x -= floor(x);
3297 	y -= floor(y);
3298 	switch(TPat->Vals.Pavement.Form)
3299 	{
3300 		case 2:
3301 			if ((how & 0x16) == 0x16)
3302 			{
3303 				value1 = 2*x;
3304 				value2 = 2 - 2*y;
3305 				value = fabs(sqrt(value1*value1+value2*value2) - 1.0);
3306 				return_value = min(value,1.0);
3307 				return return_value;
3308 			}
3309 			if ((how & 0x2C) == 0x2C)
3310 			{
3311 				value1 = 2 - 2*x;
3312 				value2 = 2 - 2*y;
3313 				value = fabs(sqrt(value1*value1+value2*value2) - 1.0);
3314 				return_value = min(value,1.0);
3315 				return return_value;
3316 			}
3317 			if ((how & 0x49) == 0x49)
3318 			{
3319 				value1 = 2 - 2*x;
3320 				value2 = 2*y;
3321 				value = fabs(sqrt(value1*value1+value2*value2) - 1.0);
3322 				return_value = min(value,1.0);
3323 				return return_value;
3324 			}
3325 			if ((how & 0x83) == 0x83)
3326 			{
3327 				value1 = 2*x;
3328 				value2 = 2*y;
3329 				value = fabs(sqrt(value1*value1+value2*value2) - 1.0);
3330 				return_value = min(value,1.0);
3331 				return return_value;
3332 			}
3333 			break;
3334 		case 1:
3335 			if ((how & 0x16) == 0x16)
3336 			{
3337 				value1 = 2*x;
3338 				value2 = 2*y;
3339 				value = fabs(value1 - value2 + 1.0);
3340 				return_value = min(value,1.0);
3341 				return return_value;
3342 			}
3343 			if ((how & 0x2C) == 0x2C)
3344 			{
3345 				value1 = 2*x;
3346 				value2 = 2 - 2*y;
3347 				value = fabs(value2 - value1 + 1.0);
3348 				return_value = min(value,1.0);
3349 				return return_value;
3350 			}
3351 			if ((how & 0x49) == 0x49)
3352 			{
3353 				value1 = 2*x;
3354 				value2 = 2*y;
3355 				value = fabs(value2 - value1 + 1.0);
3356 				return_value = min(value,1.0);
3357 				return return_value;
3358 			}
3359 			if ((how & 0x83) == 0x83)
3360 			{
3361 				value1 = 2*x;
3362 				value2 = 2 - 2*y;
3363 				value = fabs(value1 - value2 + 1.0);
3364 				return_value = min(value,1.0);
3365 				return return_value;
3366 			}
3367 			break;
3368 		case 0:
3369 			if ((how & 0x16) == 0x16)
3370 			{
3371 				value1 = 2*x -1;
3372 				value2 = 1 - 2*y;
3373 				return_value = max(value1,value2);
3374 				value1 = 1 - 2*x;
3375 				value2 = 2*y - 1;
3376 				value = min(value1,value2);
3377 				return_value = max(return_value,value);
3378 				return return_value;
3379 			}
3380 			if ((how & 0x2C) == 0x2C)
3381 			{
3382 				value1 = 1 - 2*x;
3383 				value2 = 1 - 2*y;
3384 				return_value = max(value1,value2);
3385 				value1 = 2*x - 1;
3386 				value2 = 2*y - 1;
3387 				value = min(value1,value2);
3388 				return_value = max(return_value,value);
3389 				return return_value;
3390 			}
3391 			if ((how & 0x49) == 0x49)
3392 			{
3393 				value1 = 1 - 2*x;
3394 				value2 = 2*y - 1;
3395 				return_value = max(value1,value2);
3396 				value1 = 2*x - 1;
3397 				value2 = 1 - 2*y;
3398 				value = min(value1,value2);
3399 				return_value = max(return_value,value);
3400 				return return_value;
3401 			}
3402 			if ((how & 0x83) == 0x83)
3403 			{
3404 				value1 = 2*x -1;
3405 				value2 = 2*y -1;
3406 				return_value = max(value1,value2);
3407 				value1 = 1 - 2*x;
3408 				value2 = 1 - 2*y;
3409 				value = min(value1,value2);
3410 				return_value = max(return_value,value);
3411 				return return_value;
3412 			}
3413 			break;
3414 		default:
3415 		case 3:
3416 			break;
3417 	}
3418 	if (how & 0x01)
3419 	{
3420 		value = 2*y - 1;
3421 		return_value = max(return_value,value);
3422 	}
3423 	if (how & 0x02)
3424 	{
3425 		value = 2*x -1;
3426 		return_value = max(return_value,value);
3427 	}
3428 	if (how & 0x04)
3429 	{
3430 		value = 1 - 2*y;
3431 		return_value = max(return_value,value);
3432 	}
3433 	if (how & 0x08)
3434 	{
3435 		value = 1 - 2*x;
3436 		return_value = max(return_value,value);
3437 	}
3438 	switch(TPat->Vals.Pavement.Interior)
3439 	{
3440 		case 2:
3441 			if (how & 0x40)
3442 			{
3443 				value1 = 2 - 2*x;
3444 				value2 = 2*y;
3445 				value = 1.0- sqrt(value1*value1+value2*value2);
3446 				return_value = max(return_value,value);
3447 			}
3448 			if (how & 0x80)
3449 			{
3450 				value1 = 2*x;
3451 				value2 = 2*y;
3452 				value = 1.0- sqrt(value1*value1+value2*value2);
3453 				return_value = max(return_value,value);
3454 			}
3455 			if (how & 0x10)
3456 			{
3457 				value1 = 2*x;
3458 				value2 = 2 - 2*y;
3459 				value = 1.0- sqrt(value1*value1+value2*value2);
3460 				return_value = max(return_value,value);
3461 			}
3462 			if (how & 0x20)
3463 			{
3464 				value1 = 2 - 2*x;
3465 				value2 = 2 - 2*y;
3466 				value = 1.0- sqrt(value1*value1+value2*value2);
3467 				return_value = max(return_value,value);
3468 			}
3469 			break;
3470 		case 1:
3471 			if (how & 0x40)
3472 			{
3473 				value1 = 2 - 2*x;
3474 				value2 = 2*y;
3475 				value = 1.0- (value1+value2);
3476 				return_value = max(return_value,value);
3477 			}
3478 			if (how & 0x80)
3479 			{
3480 				value1 = 2*x;
3481 				value2 = 2*y;
3482 				value = 1.0- (value1+value2);
3483 				return_value = max(return_value,value);
3484 			}
3485 			if (how & 0x10)
3486 			{
3487 				value1 = 2*x;
3488 				value2 = 2 - 2*y;
3489 				value = 1.0- (value1+value2);
3490 				return_value = max(return_value,value);
3491 			}
3492 			if (how & 0x20)
3493 			{
3494 				value1 = 2 - 2*x;
3495 				value2 = 2 - 2*y;
3496 				value = 1.0- (value1+value2);
3497 				return_value = max(return_value,value);
3498 			}
3499 			break;
3500 		default:
3501 		case 0:
3502 			if (how & 0x10)
3503 			{
3504 				value1 = 1 - 2*x;
3505 				value2 = 2*y - 1;
3506 				value = min(value1,value2);
3507 				return_value = max(return_value,value);
3508 			}
3509 			if (how & 0x20)
3510 			{
3511 				value1 = 2*x - 1;
3512 				value2 = 2*y - 1;
3513 				value = min(value1,value2);
3514 				return_value = max(return_value,value);
3515 			}
3516 			if (how & 0x40)
3517 			{
3518 				value1 = 2*x - 1;
3519 				value2 = 1 - 2*y;
3520 				value = min(value1,value2);
3521 				return_value = max(return_value,value);
3522 			}
3523 			if (how & 0x80)
3524 			{
3525 				value1 = 1 - 2*x;
3526 				value2 = 1 - 2*y;
3527 				value = min(value1,value2);
3528 				return_value = max(return_value,value);
3529 			}
3530 			break;
3531 	}
3532 	switch(TPat->Vals.Pavement.Exterior)
3533 	{
3534 		case 2:
3535 			value1 = 2*x - 1;
3536 			value2 = 2*y - 1;
3537 			if ( (((how & 0x06) == 0x06)&&(value1>=0.0)&&(value2<=0.0)) ||
3538 			     (((how & 0x0C) == 0x0C)&&(value1<=0.0)&&(value2<=0.0)) ||
3539 			     (((how & 0x09) == 0x09)&&(value1<=0.0)&&(value2>=0.0)) ||
3540 			     (((how & 0x03) == 0x03)&&(value1>=0.0)&&(value2>=0.0)) )
3541 			{
3542 				value = sqrt(value1*value1+value2*value2);
3543 				value = min(value,1.0);
3544 				return_value = max(return_value,value);
3545 			}
3546 			break;
3547 		case 1:
3548 			if ((how & 0x06) == 0x06)
3549 			{
3550 				value1 = 2 - 2*x;
3551 				value2 = 2*y;
3552 				value = 2.0- (value1+value2);
3553 				value = min(value,1.0);
3554 				return_value = max(return_value,value);
3555 			}
3556 			if ((how & 0x0C) == 0x0C)
3557 			{
3558 				value1 = 2*x;
3559 				value2 = 2*y;
3560 				value = 2.0- (value1+value2);
3561 				value = min(value,1.0);
3562 				return_value = max(return_value,value);
3563 			}
3564 			if ((how & 0x09) == 0x09)
3565 			{
3566 				value1 = 2*x;
3567 				value2 = 2 - 2*y;
3568 				value = 2.0- (value1+value2);
3569 				value = min(value,1.0);
3570 				return_value = max(return_value,value);
3571 			}
3572 			if ((how & 0x03) == 0x03)
3573 			{
3574 				value1 = 2 - 2*x;
3575 				value2 = 2 - 2*y;
3576 				value = 2.0- (value1+value2);
3577 				value = min(value,1.0);
3578 				return_value = max(return_value,value);
3579 			}
3580 			break;
3581 		default:
3582 		case 0:
3583 			break;
3584 	}
3585 	return return_value;
3586 }
3587 
3588 static unsigned short tritrigon[][6]=
3589 {
3590 	{0x215,0x344,0x126,   0x126,0x344,0x215}
3591 };
3592 
3593 static unsigned short tritetragon[][8]=
3594 {
3595 	{0x126,0x126,0x144,0x144, 0x126,0x126,0x144,0x144},
3596 	{0x611,0x344,0x126,0x423, 0x611,0x344,0x126,0x423},
3597 	{5,0,6,3, 0,5,3,6}
3598 };
3599 
3600 static unsigned short tripentagon[][10]=
3601 {
3602 	{0x215,0x244,4,0x144,0x126, 0x126,0x144,4,0x244,0x215},
3603 	{0x215,0x244,0x244,0x611,0x611, 0x244,0x244,0x215,0x423,0x423},
3604 	{0x146,0x126,0x344,0x611,0x611, 0x344, 0x126,0x146,0x522,0x522},
3605 	{5,0,0x244,0x215,3, 3,0x215,0x244,0,5}
3606 };
3607 
3608 static unsigned short trihexagon[][12]=
3609 {
3610 	{0x215,0x244,4,4,0x244,0x215, 0x215,0x244,4,4,0x244,0x215},
3611 	{0x413,0x522,0x144,4,0x244,0x215, 0x413,0x522,0x144,4,0x244,0x215},
3612 	{3,0x126,0x144,0,0x244,0x215, 3,0x126,0x144,0,0x244,0x215},
3613 	{0x215,0x244,4,0,6,3, 4,0x244,0x215,3,6,0},
3614 	{5,0,0x244,0x215,0x245,0x211, 5,0x211,0x245,0x215,0x244,0},
3615 	{0x245,0x211,0x215,0x244,0x244,0x211, 0x245,0x211,0x244,0x244,0x215,0x211},
3616 	{0x215,0x244,0x244,0x611, 0x522,0x146,0x146,0x522, 0x611,0x244,0x244,0x215},
3617 	{5,0,0x244,0x215, 0x146,0x122,0x122,0x146, 0x215,0x244,0,5},
3618 	{5,0,6,0x126,0x344,0x211, 5,0x211,0x344,0x126,6,0},
3619 	{0x215,0x344,0x122,0x122,0x344,0x215, 0x215,0x344,0x122,0x122,0x344,0x215},
3620 	{5,0,6,6,0,5, 6,0,5,5,0,6},
3621 	{0x691,0x3C4,0x5A2,0x5A2,0x3C4,0x691, 0x5A2,0x3C4,0x691,0x691,0x3C4,0x5A2},
3622 };
3623 
trigonal(const VECTOR EPoint,const TPATTERN * TPat)3624 static DBL trigonal (const VECTOR EPoint, const TPATTERN *TPat)
3625 {
3626 	unsigned short how;
3627 	long xv,zv;
3628 	DBL return_value=0;
3629 	DBL value;
3630 	DBL value1;
3631 	DBL value2;
3632 	DBL dist1;
3633 	DBL dist2;
3634 	DBL dist3;
3635 	DBL x,z;
3636 	int lng=0;
3637 
3638 	x=EPoint[X];
3639 	z=EPoint[Z];
3640 
3641 	xv = floor(x);
3642 	zv = floor(z/SQRT3);
3643 	x -= xv;
3644 	z -= SQRT3*zv;
3645 	/* x,z is in { [0.0, 1.0 [, [0.0, SQRT3 [ }
3646 	 ** There is some mirror to reduce the problem
3647 	 */
3648 	zv *= 2;
3649 	xv *= 2;
3650 	if ( z > SQRT3_2 )
3651 	{
3652 		z -= SQRT3_2;
3653 		if (x>0.5)
3654 		{
3655 			x -= 0.5;
3656 			xv++;
3657 		}
3658 		else
3659 		{
3660 			x += 0.5;
3661 			xv--;
3662 		}
3663 		zv++;
3664 	}
3665 	if ((x == 0.0)||(z/x>SQRT3))
3666 	{
3667 		z = SQRT3_2 - z;
3668 		x = 0.5 -x;
3669 		xv--;
3670 	}
3671 	if ((x == 1.0)||(z/(1.0-x)>SQRT3))
3672 	{
3673 		z = SQRT3_2 - z;
3674 		x = 1.5 -x;
3675 		xv++;
3676 	}
3677 	switch(TPat->Vals.Pavement.Tile)
3678 	{
3679 		case 6:
3680 			switch(TPat->Vals.Pavement.Number-1)
3681 			{
3682 				case 0:
3683 				case 1:
3684 				case 9:
3685 					xv += 5*zv;
3686 					zv = 0;
3687 					xv %= 6; if (xv <0) { xv += 6;}
3688 					lng = 0;
3689 					break;
3690 				case 2:
3691 				case 10:
3692 				case 11:
3693 					zv &= 0x01;
3694 					xv += 3*zv;
3695 					xv %= 6; if (xv <0) { xv += 6;}
3696 					lng = 0;
3697 					break;
3698 				case 3:
3699 					xv += 14*((zv%6+((zv%6)<0?6:0))/2);
3700 					xv %= 6; if (xv <0) { xv += 6;}
3701 					lng = 6;
3702 					zv &= 0x01;
3703 					break;
3704 				case 4:
3705 				case 8:
3706 					xv += 8*((zv%6+((zv%6)<0?6:0))/2);
3707 					xv %= 6; if (xv <0) { xv += 6;}
3708 					lng = 6;
3709 					zv &= 0x01;
3710 					break;
3711 				case 5:
3712 					xv %= 6; if (xv <0) { xv += 6;}
3713 					lng = 6;
3714 					zv &= 0x01;
3715 					break;
3716 				case 6:
3717 				case 7:
3718 					xv -= ((zv%12+((zv%12)<0?12:0))/3);
3719 					xv &= 3;
3720 					lng = 4;
3721 					zv %= 3; if (zv <0) { zv +=3;}
3722 					break;
3723 			}
3724 			how = trihexagon[TPat->Vals.Pavement.Number-1][xv+zv*lng];
3725 			break;
3726 		case 5:
3727 			switch(TPat->Vals.Pavement.Number-1)
3728 			{
3729 				case 0:
3730 				case 1:
3731 				case 2:
3732 					zv &= 0x01;
3733 					xv += 5*zv;
3734 					xv %= 10; if (xv <0) { xv += 10 ;  }
3735 					zv = 0x00;
3736 					break;
3737 				case 3:
3738 					zv %= 10; if (zv <0) { zv += 10; }
3739 					xv += 3*zv;
3740 					xv %= 10; if (xv <0) { xv += 10 ;  }
3741 					zv = 0x00;
3742 					break;
3743 			}
3744 			how = tripentagon[TPat->Vals.Pavement.Number-1][xv];
3745 			break;
3746 		case 4:
3747 			zv &= 0x03;
3748 			xv += zv;
3749 			xv &= 0x03;
3750 			zv &= 0x01;
3751 			how = tritetragon[TPat->Vals.Pavement.Number-1][xv+zv*4];
3752 			break;
3753 		case 3:
3754 			zv &= 0x01;
3755 			xv += 3*zv;
3756 			xv %= 6; if (xv < 0) { xv += 6; }
3757 			zv = 0x00;
3758 			how = tritrigon[TPat->Vals.Pavement.Number-1][xv];
3759 			break;
3760 		case 2:
3761 			how = 0x166;
3762 			break;
3763 		case 1:
3764 		default:
3765 			how = 0x07;
3766 			break;
3767 	}
3768 
3769 	/*
3770 	 **      / \
3771 	 **     1   \
3772 	 **    /     2
3773 	 **   /       \
3774 	 **  -----3-----
3775 	 ** *3/2
3776 	 */
3777 	if (how & 0x01)
3778 	{
3779 		dist1 = 1.0 - (fabs(SQRT3 * x - z) * SQRT3 );
3780 		return_value = max(return_value,dist1);
3781 	}
3782 	if (how & 0x02)
3783 	{
3784 		dist2 = 1.0 - (fabs(SQRT3 * (1.0-x) - z) * SQRT3  );
3785 		return_value = max(return_value,dist2);
3786 	}
3787 	if (how & 0x04)
3788 	{
3789 		dist3 = 1.0 - (z * 2.0 * SQRT3 );
3790 		return_value = max(return_value,dist3);
3791 	}
3792 	switch(TPat->Vals.Pavement.Interior)
3793 	{
3794 		case 1:
3795 			dist1 = (1.0 - (fabs(SQRT3 * z + x) ));
3796 			dist2 = (1.0 - (fabs(SQRT3 * z - x + 1.0) ));
3797 			dist3 = (1.0 - (x * 2.0 ));
3798 			if (((how & 0x83) == 0x00)&&(dist1<0)&&(dist2<0))
3799 			{
3800 				value1 = (3.0 / 2.0 *(fabs(SQRT3 * z + x) ) - 2.0);
3801 				value2 = (3.0 / 2.0 *(fabs(SQRT3 * z - x + 1.0) ) - 2.0);
3802 				value =  min(value1,value2);
3803 				return_value = max(return_value,value);
3804 			}
3805 			if (((how & 0x85) == 0x00)&&(dist1>0)&&(dist3>0))
3806 			{
3807 				value1 = (1.0 - 3.0 / 2.0 * (fabs(SQRT3 * z + x) ));
3808 				value2 = (1.0 - (x * 3.0 ));
3809 				value =  min(value1,value2);
3810 				return_value = max(return_value,value);
3811 			}
3812 			if (((how & 0x86) == 0x00)&&(dist3<0)&&(dist2>0))
3813 			{
3814 				value1 = (1.0 - 3.0 / 2.0 *(fabs(SQRT3 * z - x + 1.0) ));
3815 				value2 = ((x * 3.0 ) - 2.0);
3816 				value =  min(value1,value2);
3817 				return_value = max(return_value,value);
3818 			}
3819 			break;
3820 		case 2:
3821 			if ((how & 0x83) == 0x00)
3822 			{
3823 				dist1 = x - 0.5;
3824 				dist2 = z - SQRT3_2;
3825 				dist3 = 1.0 - (sqrt((dist1*dist1+dist2*dist2))*3.0 );
3826 				return_value = max(return_value,dist3);
3827 			}
3828 			if ((how & 0x85) == 0x00)
3829 			{
3830 				dist1 = x;
3831 				dist2 = z;
3832 				dist3 = 1.0 - (sqrt((dist1*dist1+dist2*dist2)) *3.0);
3833 				return_value = max(return_value,dist3);
3834 			}
3835 			if ((how & 0x86) == 0x00)
3836 			{
3837 				dist1 = x - 1.0;
3838 				dist2 = z ;
3839 				dist3 = 1.0 - (sqrt((dist1*dist1+dist2*dist2)) *3.0);
3840 				return_value = max(return_value,dist3);
3841 			}
3842 			break;
3843 		case 0:
3844 			if ((how & 0x83) == 0x00)
3845 			{
3846 				dist3 = 1.0 - ((SQRT3_2 - z) * 2.0 * SQRT3  );
3847 				return_value = max(return_value,dist3);
3848 			}
3849 			if ((how & 0x85) == 0x00)
3850 			{
3851 				dist2 = 1.0 - (fabs(SQRT3 * x + z) * SQRT3 );
3852 				return_value = max(return_value,dist2);
3853 			}
3854 			if ((how & 0x86) == 0x00)
3855 			{
3856 				dist1 = 1.0 - (fabs(SQRT3 * (x -1.0) - z) * SQRT3 );
3857 				return_value = max(return_value,dist1);
3858 			}
3859 			break;
3860 	}
3861 	switch(TPat->Vals.Pavement.Exterior)
3862 	{
3863 		case 2:
3864 			dist1 = (1.0 - (fabs(SQRT3 * z + x) ));
3865 			dist2 = (1.0 - (fabs(SQRT3 * z - x + 1.0) ));
3866 			dist3 = (1.0 - (x * 2.0 ));
3867 			if ( (((how & 0x03) == 0x03)&&(dist1<=0.0)&&(dist2<=0.0)) ||
3868 			     (((how & 0x06) == 0x06)&&(dist2>=0.0)&&(dist3<=0.0)) ||
3869 			     (((how & 0x05) == 0x05)&&(dist1>=0.0)&&(dist3>=0.0)) )
3870 			{
3871 				value1 = x - 0.5;
3872 				value2 = z - SQRT3_2/3.0;
3873 				value = 2 * SQRT3 *sqrt(value1*value1+value2*value2);
3874 				return_value = min(1.0,value);
3875 			}
3876 			break;
3877 		case 1:
3878 			/* dist1 = (1.0 - (fabs(SQRT3 * z + x) )); */
3879 			dist1 = (1.0 - (fabs(SQRT3 * x - z)*SQRT3 ));
3880 			/* dist2 = (1.0 - (fabs(SQRT3 * z - x + 1.0) )); */
3881 			dist2 = (1.0 - (fabs(SQRT3 * (1.0 -x ) -z ) *SQRT3));
3882 			/* dist3 = (1.0 - (x * 2.0 )); */
3883 			dist3 = (1.0 - (z * 2.0 * SQRT3));
3884 			value1 = (x - 0.5);
3885 			value2 = (z - SQRT3_2/3.0);
3886 			if  (((how & 0x03) == 0x03)&&(dist1>=0.0)&&(dist2>=0.0))
3887 			{
3888 				value = fabs(value2 * 2.0 * SQRT3 );
3889 				return_value = min(1.0,value);
3890 			}
3891 			if  (((how & 0x06) == 0x06)&&(dist2>=0.0)&&(dist3>=0.0))
3892 			{
3893 				value = fabs(SQRT3 * value1 - value2) * SQRT3 ;
3894 				return_value = min(1.0,value);
3895 			}
3896 			if  (((how & 0x05) == 0x05)&&(dist1>=0.0)&&(dist3>=0.0))
3897 			{
3898 				value = fabs(SQRT3 * value1 + value2) * SQRT3  ;
3899 				return_value = min(1.0,value);
3900 			}
3901 			break;
3902 		case 0:
3903 		default:
3904 			break;
3905 	}
3906 	dist1 = (1.0 - (fabs(SQRT3 * z + x) ));
3907 	dist2 = (1.0 - (fabs(SQRT3 * z - x + 1.0) ));
3908 	dist3 = (1.0 - (x * 2.0 ));
3909 	switch(TPat->Vals.Pavement.Form)
3910 	{
3911 		case 2:
3912 			if (((how & 0x120) == 0x120)&&(dist1<0)&&(dist2<0))
3913 			{
3914 				value1 = x;
3915 				value2 = z;
3916 				value = 2.0*SQRT3*(sqrt(value1*value1+value2*value2 ) - SQRT3/3.0 );
3917 				value = max(value,0.0);
3918 				return_value = min(value,1.0);
3919 				return return_value;
3920 			}
3921 			if (((how & 0x140) == 0x140)&&(dist1>0)&&(dist3>0))
3922 			{
3923 				value1 = x - 0.5;
3924 				value2 = z- SQRT3_2;
3925 				value = 2.0*SQRT3*(sqrt(value1*value1+value2*value2 ) - SQRT3/3.0 );
3926 				value = max(value,0.0);
3927 				return_value = min(value,1.0);
3928 				return return_value;
3929 			}
3930 			if (((how & 0x210) == 0x210)&&(dist1<0)&&(dist2<0))
3931 			{
3932 				value1 = x - 1.0;
3933 				value2 = z;
3934 				value = 2.0*SQRT3*(sqrt(value1*value1+value2*value2 ) - SQRT3/3.0 );
3935 				value = max(value,0.0);
3936 				return_value = min(value,1.0);
3937 				return return_value;
3938 			}
3939 			if (((how & 0x240) == 0x240)&&(dist3<0)&&(dist2>0))
3940 			{
3941 				value1 = x - 0.5;
3942 				value2 = z - SQRT3_2;
3943 				value = 2.0*SQRT3*(sqrt(value1*value1+value2*value2 ) - SQRT3/3.0 );
3944 				value = max(value,0.0);
3945 				return_value = min(value,1.0);
3946 				return return_value;
3947 			}
3948 			if (((how & 0x410) == 0x410)&&(dist1>0)&&(dist3>0))
3949 			{
3950 				value1 = x - 1.0;
3951 				value2 = z;
3952 				value = 2.0*SQRT3*(sqrt(value1*value1+value2*value2 ) - SQRT3/3.0 );
3953 				value = max(value,0.0);
3954 				return_value = min(value,1.0);
3955 				return return_value;
3956 			}
3957 			if (((how & 0x420) == 0x420)&&(dist3<0)&&(dist2>0))
3958 			{
3959 				value1 = x;
3960 				value2 = z;
3961 				value = 2.0*SQRT3*(sqrt(value1*value1+value2*value2 ) - SQRT3/3.0 );
3962 				value = max(value,0.0);
3963 				return_value = min(value,1.0);
3964 				return return_value;
3965 			}
3966 			break;
3967 		case 1:
3968 			if (((how & 0x120) == 0x120)&&(dist1<0)&&(dist2<0))
3969 			{
3970 				value = -dist1 * 2;
3971 				return_value = min(value,1.0);
3972 				return return_value;
3973 			}
3974 			if (((how & 0x140) == 0x140)&&(dist1>0)&&(dist3>0))
3975 			{
3976 				value = dist1 * 2;
3977 				return_value = min(value,1.0);
3978 				return return_value;
3979 			}
3980 			if (((how & 0x210) == 0x210)&&(dist1<0)&&(dist2<0))
3981 			{
3982 				value = -dist2 * 2;
3983 				return_value = min(value,1.0);
3984 				return return_value;
3985 			}
3986 			if (((how & 0x240) == 0x240)&&(dist3<0)&&(dist2>0))
3987 			{
3988 				value = dist2 * 2;
3989 				return_value = min(value,1.0);
3990 				return return_value;
3991 			}
3992 			if (((how & 0x410) == 0x410)&&(dist1>0)&&(dist3>0))
3993 			{
3994 				value = dist3 * 2;
3995 				return_value = min(value,1.0);
3996 				return return_value;
3997 			}
3998 			if (((how & 0x420) == 0x420)&&(dist2>0)&&(dist3<0))
3999 			{
4000 				value = -dist3 * 2;
4001 				return_value = min(value,1.0);
4002 				return return_value;
4003 			}
4004 			if (((how & 0x120) == 0x120)&&(dist1<0)&&(dist2<0))
4005 			{
4006 				value = -dist1 * 2;
4007 				return_value = min(value,1.0);
4008 				return return_value;
4009 			}
4010 			break;
4011 		default:
4012 		case 0:
4013 			break;
4014 	}
4015 	return return_value;
4016 }
4017 
4018 /*
4019 ** open face (3 bits)
4020 ** special (1 bit)
4021 ** nexus vertex/open face (3 bits)
4022 ** unused (1 bits)
4023 ** close face (3 bits)
4024 */
4025 static unsigned short hexmonogon[][6]=
4026 {
4027 	{0x691,0x3C4,0x5A2,0x5A2,0x3C4,0x691}
4028 };
4029 
4030 static unsigned short hexdigon[][12]=
4031 {
4032 	{0x691,0x3C4,0x1A2,0x1A2,0x3C4,0x691,0x5A2,0x1C4,0x6080,0x6080,0x1C4,0x5A2 }
4033 };
4034 
4035 static unsigned short hextrigon[][36]=
4036 {
4037 	{
4038 		0x691,0x3C4,0x5A2,  0x5A2,0x3C4, 0x691,
4039 		0x5A2,0x3C4,0x691,  0x491,0x3080,0x4A2,
4040 		0x491,0x3080,0x4A2, 0x4A2,0x3080,0x491,
4041 		0x4A2,0x3080,0x491, 0x491,0x3080,0x4A2,
4042 		0x491,0x3080,0x4A2, 0x4A2,0x3080,0x491,
4043 		0x4A2,0x3080,0x491, 0x691,0x3C4,0x5A2
4044 	},
4045 
4046 	{
4047 		0x691,0x3C4,0x1A2, 0x1A2,0x3C4,0x691,
4048 		0x5A2,0x1C4,0x4080, 0x2080,0x2080,0x4A2,
4049 		0x691,0x2C4,0x4080, 0x1080,0x1080,0x491,
4050 		0x5A2,0x3C4,0x291, 0x291,0x3C4,0x5A2,
4051 		0x491,0x1080,0x1080, 0x4080,0x2C4,0x691,
4052 		0x4A2,0x2080,0x2080, 0x4080,0x1C4,0x5A2
4053 	},
4054 
4055 	{
4056 		0x691,0x3C4,0x1A2, 0x1A2,0x3C4,0x291, 0x291,0x3C4,0x5A2,
4057 		0x5A2,0x1C4,0x6080,0x6080,0x0C4,0x5080,0x5080,0x2C4,0x691,
4058 		0x5A2,0x1C4,0x6080,0x6080,0x0C4,0x5080,0x5080,0x2C4,0x691,
4059 		0x691,0x3C4,0x1A2, 0x1A2,0x3C4,0x291, 0x291,0x3C4,0x5A2
4060 	}
4061 };
4062 
4063 static unsigned short hextetragon[][48]=
4064 {
4065 	{
4066 		0x691,0x3C4,0x5A2,  0x5A2,0x3C4, 0x691,
4067 		0x5A2,0x3C4,0x691,  0x491,0x3080,0x4A2,
4068 		0x491,0x3080,0x4A2, 0x4A2,0x3080,0x491,
4069 		0x4A2,0x3080,0x491, 0x491,0x3080,0x4A2,
4070 		0x491,0x3080,0x4A2, 0x4A2,0x3080,0x491,
4071 		0x4A2,0x3080,0x491, 0x491,0x3080,0x4A2,
4072 		0x491,0x3080,0x4A2, 0x4A2,0x3080,0x491,
4073 		0x4A2,0x3080,0x491, 0x691,0x3C4,0x5A2
4074 	},
4075 
4076 	{
4077 		0x691,0x2C4,0x4080, 0x1080,0x80,0x2080,
4078 		0x4080,0x2C4,0x691, 0x291,0x3C4,0x1A2,
4079 		0x4080,0x1C4,0x5A2, 0x1A2,0x3C4,0x291,
4080 		0x5A2,0x1C4,0x4080, 0x2080,0x80,0x1080,
4081 		0x691,0x2C4,0x4080, 0x1080,0x80,0x2080,
4082 		0x4080,0x2C4,0x691, 0x291,0x3C4,0x1A2,
4083 		0x4080,0x1C4,0x5A2, 0x1A2,0x3C4,0x291,
4084 		0x5A2,0x1C4,0x4080, 0x2080,0x80,0x1080
4085 	},
4086 
4087 	{
4088 		0x691,0x2C4,0x5080,  0x5080,0x0C4,0x6080,
4089 		0x6080,0x0C4,0x5080, 0x5080,0x2C4,0x691,
4090 		0x5A2,0x3C4,0x291, 0x291,0x3C4,0x1A2,
4091 		0x1A2,0x3C4,0x291, 0x291,0x3C4,0x5A2,
4092 		0x691,0x2C4,0x5080,  0x5080,0x0C4,0x6080,
4093 		0x6080,0x0C4,0x5080, 0x5080,0x2C4,0x691,
4094 		0x5A2,0x3C4,0x291, 0x291,0x3C4,0x1A2,
4095 		0x1A2,0x3C4,0x291, 0x291,0x3C4,0x5A2,
4096 	},
4097 
4098 	{
4099 		0x691,0x3C4,0x5A2,  0x4A2,0x3080,0x491,
4100 		0x1A2,0x3C4,0x691,  0x691,0x3C4,0x5A2,
4101 		0x6080,0x1C4,0x5A2, 0x1A2,0x3C4,0x691,
4102 		0x5A2,0x1C4,0x6080, 0x6080,0x1C4,0x5A2,
4103 		0x491,0x3080,0x0A2, 0x5A2,0x1C4,0x6080,
4104 		0x4A2,0x3080,0x491, 0x491,0x3080,0x0A2,
4105 		0x491,0x3080,0x4A2, 0x4A2,0x3080,0x491,
4106 		0x4A2,0x3080,0x491, 0x491,0x3080,0x4A2
4107 	},
4108 
4109 	{
4110 		0x691,0x3C4,0x1A2,  0x5A2,0x1C4,0x6080,
4111 		0x5080,0x2C4,0x691, 0x491,0x3080,0x0A2,
4112 		0x291,0x3C4,0x5A2,  0x4A2,0x3080,0x091,
4113 		0x5A2,0x3C4,0x291,  0x691,0x2C4,0x5080,
4114 		0x691,0x2C4,0x5080, 0x5080,0x2C4,0x691,
4115 		0x1A2,0x3C4,0x691,  0x091,0x3080,0x4A2,
4116 		0x6080,0x1C4,0x5A2, 0x0A2,0x3080,0x491,
4117 		0x5A2,0x1C4,0x6080, 0x6080,0x1C4,0x5A2
4118 	},
4119 
4120 	{
4121 		0x691,0x3C4,0x5A2,  0x0A2,0x3080,0x491,
4122 		0x5A2,0x1C4,0x4080, 0x2080,0x2080,0x4A2,
4123 		0x691,0x2C4,0x4080, 0x1080,0x1080,0x491,
4124 		0x5A2,0x3C4,0x291,  0x291,0x3C4,0x5A2,
4125 		0x491,0x1080,0x1080,0x4080,0x2C4,0x691,
4126 		0x4A2,0x2080,0x2080,0x4080,0x1C4,0x5A2,
4127 		0x491,0x3080,0x0A2, 0x5A2,0x3C4,0x691,
4128 		0x4A2,0x3080,0x491, 0x491,0x3080,0x4A2
4129 	},
4130 
4131 	{
4132 		0x691,0x3C4,0x5A2,  0x1A2,0x3C4,0x691, 0x091,0x3080,0x0A2, 0x5A2,0x3C4,0x291,
4133 		0x5080,0x0C4,0x6080,0x6080,0x1C4,0x5A2,0x4A2,0x3080,0x491, 0x691,0x2C4,0x5080,
4134 		0x091,0x3080,0x0A2, 0x5A2,0x3C4,0x291, 0x691,0x3C4,0x5A2,  0x1A2,0x3C4,0x691,
4135 		0x4A2,0x3080,0x491, 0x691,0x2C4,0x5080,0x5080,0x0C4,0x6080,0x6080,0x1C4,0x5A2
4136 	}
4137 };
4138 
4139 static unsigned short hexpentagon[][60]=
4140 { /* 0 */
4141 	{
4142 		0x691,0x3C4,0x5A2,  0x5A2,0x3C4, 0x691,
4143 		0x5A2,0x3C4,0x691,  0x491,0x3080,0x4A2,
4144 		0x491,0x3080,0x4A2, 0x4A2,0x3080,0x491,
4145 		0x4A2,0x3080,0x491, 0x491,0x3080,0x4A2,
4146 		0x491,0x3080,0x4A2, 0x4A2,0x3080,0x491,
4147 		0x4A2,0x3080,0x491, 0x491,0x3080,0x4A2,
4148 		0x491,0x3080,0x4A2, 0x4A2,0x3080,0x491,
4149 		0x4A2,0x3080,0x491, 0x491,0x3080,0x4A2,
4150 		0x491,0x3080,0x4A2, 0x4A2,0x3080,0x491,
4151 		0x4A2,0x3080,0x491, 0x691,0x3C4,0x5A2
4152 	},
4153 	/* 1 */
4154 	{
4155 		0x6080,0x1C4,0x5A2, 0x1A2,0x3C4,0x691,
4156 		0x5A2,0x1C4,0x6080, 0x6080,0x1C4,0x5A2 ,
4157 		0x491,0x3080,0x0A2, 0x5A2,0x1C4,0x6080,
4158 		0x4A2,0x3080,0x491, 0x491,0x3080,0x0A2,
4159 		0x491,0x3080,0x4A2, 0x4A2,0x3080,0x491,
4160 		0x4A2,0x3080,0x491, 0x491,0x3080,0x4A2,
4161 		0x491,0x3080,0x4A2, 0x4A2,0x3080,0x491,
4162 		0x4A2,0x3080,0x491, 0x491,0x3080,0x4A2,
4163 		0x691,0x3C4,0x5A2,  0x4A2,0x3080,0x491,
4164 		0x1A2,0x3C4,0x691,  0x691,0x3C4,0x5A2
4165 	},
4166 	/* 2 */
4167 	{
4168 		0x691,0x3C4,0x1A2,  0x1A2,0x3C4, 0x691,
4169 		0x5A2,0x1C4,0x4080, 0x2080,0x2080,0x4A2,
4170 		0x691,0x2C4,0x4080, 0x1080,0x1080,0x491,
4171 		0x5A2,0x3C4,0x691,  0x091,0x3080,0x4A2,
4172 		0x491,0x3080,0x4A2, 0x4A2,0x3080,0x491,
4173 		0x4A2,0x3080,0x491, 0x491,0x3080,0x4A2,
4174 		0x491,0x3080,0x4A2, 0x4A2,0x3080,0x491,
4175 		0x4A2,0x3080,0x091, 0x691,0x3C4,0x5A2,
4176 		0x491,0x1080,0x1080,0x4080,0x2C4,0x691,
4177 		0x4A2,0x2080,0x2080,0x4080,0x1C4,0x5A2
4178 	},
4179 	/* 3 */
4180 	{
4181 		0x691,0x3C4,0x5A2,  0x0A2,0x3080,0x491,
4182 		0x5A2,0x1C4,0x4080, 0x2080,0x2080,0x4A2,
4183 		0x691,0x2C4,0x4080, 0x1080,0x1080,0x491,
4184 		0x5A2,0x3C4,0x691,  0x091,0x3080,0x4A2,
4185 		0x491,0x3080,0x4A2, 0x4A2,0x3080,0x491,
4186 		0x4A2,0x3080,0x091, 0x691,0x3C4,0x5A2,
4187 		0x491,0x1080,0x1080,0x4080,0x2C4,0x691,
4188 		0x4A2,0x2080,0x2080,0x4080,0x1C4,0x5A2,
4189 		0x491,0x3080,0x0A2, 0x5A2,0x3C4, 0x691,
4190 		0x4A2,0x3080,0x491, 0x491,0x3080,0x4A2
4191 	},
4192 	/* 4 */
4193 	{
4194 		0x6080,0x1C4,0x5A2, 0x0A2,0x3080,0x491,
4195 		0x5A2,0x1C4,0x6080, 0x6080,0x1C4,0x5A2,
4196 		0x491,0x3080,0x0A2, 0x5A2,0x1C4,0x6080,
4197 		0x4A2,0x3080,0x491, 0x491,0x3080,0x0A2,
4198 		0x491,0x3080,0x4A2, 0x4A2,0x3080,0x491,
4199 		0x4A2,0x3080,0x491, 0x491,0x3080,0x4A2,
4200 		0x691,0x3C4,0x5A2,  0x4A2,0x3080,0x491,
4201 		0x5A2,0x3C4,0x691,  0x691,0x3C4,0x5A2,
4202 		0x491,0x3080,0x4A2, 0x5A2,0x3C4,0x691,
4203 		0x0A2,0x3080,0x491, 0x491,0x3080,0x4A2,
4204 	},
4205 	/* 5 */
4206 	{
4207 		0x691,0x3C4,0x1A2,  0x1A2,0x3C4, 0x691,
4208 		0x5A2,0x1C4,0x4080, 0x2080,0x2080,0x4A2,
4209 		0x491,0x1080,0x080, 0x080,0x1080,0x491,
4210 		0x4A2,0x2080,0x2080,0x4080,0x1C4,0x5A2,
4211 		0x491,0x3080,0x0A2, 0x5A2,0x3C4,0x691,
4212 		0x4A2,0x3080,0x491, 0x491,0x3080,0x4A2,
4213 		0x691,0x3C4,0x5A2,  0x0A2,0x3080,0x491,
4214 		0x5A2,0x1C4,0x4080, 0x2080,0x2080,0x4A2,
4215 		0x491,0x1080,0x080, 0x080,0x1080,0x491,
4216 		0x4A2,0x2080,0x2080,0x4080,0x1C4,0x5A2
4217 	},
4218 	/* 6 */
4219 	{
4220 		0x691,0x2C4,0x4080, 0x1080,0x1080, 0x491,
4221 		0x5A2,0x3C4,0x291,  0x291,0x3C4,0x5A2,
4222 		0x491,0x1080,0x1080,0x4080,0x2C4,0x691,
4223 		0x4A2,0x2080,0x080, 0x080,0x2080,0x4A2,
4224 		0x491,0x1080,0x080, 0x080,0x1080,0x491,
4225 		0x4A2,0x2080,0x2080,0x4080,0x1C4,0x5A2,
4226 		0x691,0x3C4,0x1A2,  0x1A2,0x3C4,0x691,
4227 		0x5A2,0x1C4,0x4080, 0x2080,0x2080,0x4A2,
4228 		0x491,0x1080,0x080, 0x080,0x1080,0x491,
4229 		0x4A2,0x2080,0x080, 0x080,0x2080,0x4A2
4230 	},
4231 	/* 7 */
4232 	{
4233 		0x6080,0x1C4,0x5A2,
4234 		0x5A2,0x1C4,0x4080,
4235 		0x691,0x2C4,0x4080,
4236 		0x4080,0x2C4,0x691,
4237 		0x4080,0x1C4,0x5A2,
4238 		0x5A2,0x1C4,0x6080,
4239 		0x691,0x3C4,0x1A2,
4240 
4241 		0x5A2,0x1C4,0x6080,
4242 		0x491,0x3080,0x0A2,
4243 
4244 		0x4A2,0x3080,0x091,
4245 		0x491,0x1080,0x1080,
4246 		0x4A2,0x2080,0x2080,
4247 		0x691,0x3C4,0x1A2,
4248 		0x1A2,0x3C4,0x691,
4249 		0x2080,0x2080,0x4A2,
4250 		0x1080,0x1080,0x491,
4251 		0x091,0x3080,0x4A2,
4252 		0x0A2,0x3080,0x491,
4253 		0x6080,0x1C4,0x5A2,
4254 		0x1A2,0x3C4,0x691
4255 	},
4256 	/* 8 */
4257 	{
4258 		0x6080,0x0C4,0x5080, 0x5080,0x2C4, 0x291,
4259 		0x5A2,0x3C4,0x291,  0x291,0x2C4,0x5080,
4260 		0x691,0x2C4,0x5080, 0x5080,0x2C4,0x691,
4261 		0x5080,0x2C4,0x691, 0x091,0x3080,0x4A2,
4262 		0x091,0x3080,0x4A2, 0x4A2,0x3080,0x491,
4263 		0x4A2,0x3080,0x491, 0x491,0x3080,0x4A2,
4264 		0x691,0x3C4,0x5A2, 0x0A2,0x3080,0x491,
4265 		0x5A2,0x1C4,0x6080, 0x6080,0x1C4,0x5A2,
4266 
4267 		0x691,0x3C4,0x1A2, 0x5A2,0x1C4,0x6080,
4268 		0x1A2,0x3C4,0x291, 0x691,0x3C4,0x1A2
4269 	},
4270 	/* 9 */
4271 	{
4272 		0x691,0x3C4,0x1A2,  0x1A2,0x3C4,0x691,
4273 		0x5080,0x0C4,0x6080,0x6080,0x1C4,0x5A2,
4274 		0x291,0x3C4,0x1A2,  0x1A2,0x3C4,0x291,
4275 		0x5A2,0x1C4,0x6080, 0x6080,0x0C4,0x5080,
4276 		0x491,0x3080,0x0A2, 0x5A2,0x3C4,0x691,
4277 		0x6A2,0x3080,0x491, 0x491,0x3080,0x4A2,
4278 		0x691,0x3C4,0x5A2,  0x0A2,0x3080,0x491,
4279 		0x5080,0x0C4,0x6080,0x6080,0x1C4,0x5A2,
4280 		0x291,0x3C4,0x1A2, 0x1A2,0x3C4,0x291,
4281 		0x5A2,0x1C4,0x6080, 0x6080,0x0C4,0x5080,
4282 	},
4283 	/* 10 */
4284 	{
4285 		0x691,0x3C4,0x1A2,  0x1A2,0x3C4,0x691,
4286 		0x5A2,0x1C4,0x4080, 0x2080,0x2080,0x4A2,
4287 		0x491,0x1080,0x80, 0x80,0x1080,0x091,
4288 		0x4A2,0x2080,0x2080, 0x4080,0x0C4,0x5080,
4289 		0x691,0x3C4,0x1A2, 0x5A2,0x3C4,0x291,
4290 		0x5080,0x2C4,0x691, 0x691,0x2C4,0x5080,
4291 		0x291,0x3C4,0x5A2,  0x1A2,0x3C4,0x691,
4292 		0x5080,0x0C4,0x4080, 0x2080,0x2080,0x4A2,
4293 		0x091,0x1080,0x80, 0x80,0x1080,0x491,
4294 		0x4A2,0x2080,0x2080, 0x4080,0x1C4,0x5A2
4295 	},
4296 	/* 11 */
4297 	{
4298 		0x291,0x3C4,0x5A2,  0x1A2,0x3C4,0x691,
4299 		0x4080,0x0C4,0x4080, 0x2080,0x2080,0x4A2,
4300 		0x4080,0x0C4,0x4080, 0x1080,0x1080,0x491,
4301 		0x5A2,0x3C4,0x291,  0x291,0x3C4,0x5A2,
4302 		0x491,0x1080,0x1080,0x4080,0x0C4,0x4080,
4303 		0x4A2,0x2080,0x2080,0x4080,0x0C4,0x4080,
4304 		0x691,0x3C4,0x1A2, 0x5A2,0x3C4,0x291,
4305 		0x1A2,0x3C4,0x691, 0x491,0x1080,0x1080,
4306 		0x2080,0x2080,0x4A2, 0x4A2,0x2080,0x2080,
4307 		0x1080,0x1080,0x491, 0x691,0x3C4,0x1A2
4308 	},
4309 	/* 12 */
4310 	{
4311 		0x691,0x2C4,0x5080, 0x5080,0x2C4,0x691,
4312 		0x5080,0x2C4,0x691, 0x091,0x3080,0x4A2,
4313 		0x291,0x3C4,0x5A2,  0x0A2,0x3080,0x491,
4314 		0x5080,0x0C4,0x6080,0x6080,0x1C4,0x5A2,
4315 		0x291,0x3C4,0x1A2,  0x1A2,0x3C4,0x291,
4316 		0x5A2,0x1C4,0x6080, 0x6080,0x0C4,0x5080,
4317 		0x491,0x3080,0x0A2, 0x5A2,0x3C4,0x291,
4318 		0x4A2,0x3080,0x091, 0x691,0x2C4,0x5080,
4319 		0x691,0x2C4,0x5080, 0x5080,0x2C4,0x691,
4320 		0x5A2,0x3C4,0x291,  0x291,0x3C4,0x5A2
4321 	},
4322 	/* 13 */
4323 	{
4324 		0x691,0x3C4,0x5A2,  0x5A2,0x3C4,0x691,
4325 		0x5A2,0x3C4,0x691,  0x491,0x3080,0x4A2,
4326 		0x491,0x3080,0x4A2, 0x4A2,0x3080,0x091,
4327 		0x4A2,0x3080,0x091, 0x691,0x2C4,0x5080,
4328 		0x691,0x2C4,0x5080, 0x5080,0x2C4,0x291,
4329 		0x5080,0x2C4,0x291, 0x291,0x2C4,0x5080,
4330 		0x291,0x2C4,0x5080, 0x5080,0x2C4,0x691,
4331 		0x5080,0x2C4,0x691, 0x091,0x3080,0x4A2,
4332 		0x091,0x3080,0x4A2, 0x4A2,0x3080,0x491,
4333 		0x4A2,0x3080,0x491, 0x691,0x3C4,0x5A2
4334 	},
4335 	/* 14 */
4336 	{
4337 		0x291,0x3C4,0x5A2, 0x5A2,0x3C4,0x691,
4338 		0x5A2,0x3C4,0x691, 0x491,0x3080,0x4A2,
4339 		0x491,0x3080,0x4A2,0x4A2,0x3080,0x491,
4340 		0x4A2,0x3080,0x491,0x491,0x3080,0x4A2,
4341 		0x491,0x3080,0x4A2,0x4A2,0x3080,0x091,
4342 		0x4A2,0x3080,0x091,0x691,0x2C4,0x5080,
4343 		0x691,0x2C4,0x5080,0x5080,0x2C4,0x291,
4344 		0x5080,0x2C4,0x291,0x291,0x2C4,0x5080,
4345 		0x291,0x2C4,0x5080,0x5080,0x2C4,0x691,
4346 		0x5080,0x2C4,0x691,0x291,0x3C4,0x5A2
4347 	},
4348 	/* 15 */
4349 	{
4350 		0x691,0x2C4,0x5080, 0x5080,0x0C4,0x4080,
4351 		0x1A2,0x3C4,0x691,  0x291,0x2C4,0x4080,
4352 		0x2080,0x2080,0x4A2,0x5A2,0x3C4,0x691,
4353 		0x1080,0x1080,0x491,0x491,0x3080,0x4A2,
4354 		0x091,0x3080,0x4A2, 0x4A2,0x3080,0x091,
4355 		0x4A2,0x3080,0x491, 0x491,0x1080,0x1080,
4356 		0x691,0x3C4,0x5A2,  0x4A2,0x2080,0x2080,
4357 		0x4080,0x2C4,0x291, 0x691,0x3C4,0x1A2,
4358 		0x4080,0x0C4,0x5080,0x5080,0x2C4,0x691,
4359 		0x5A2,0x3C4,0x291,  0x291,0x3C4,0x5A2
4360 	},
4361 	/* 16 */
4362 	{
4363 		0x4080,0x1C4,0x1A2, 0x1A2,0x1C4,0x4080,
4364 		0x5A2,0x1C4,0x6080, 0x6080,0x0C4,0x4080,
4365 		0x691,0x3C4,0x1A2,  0x5A2,0x3C4,0x691,
4366 		0x1A2,0x3C4,0x691,  0x491,0x3080,0x4A2,
4367 		0x2080,0x2080,0x4A2,0x4A2,0x3080,0x091,
4368 		0x1080,0x1080,0x491,0x491,0x1080,0x1080,
4369 		0x091,0x3080,0x4A2, 0x4A2,0x2080,0x2080,
4370 		0x4A2,0x3080,0x491, 0x691,0x3C4,0x1A2,
4371 		0x691,0x3C4,0x5A2,  0x1A2,0x3C4,0x691,
4372 		0x4080,0x0C4,0x6080,0x6080,0x1C4,0x5A2
4373 	},
4374 	/* 17 */
4375 	{
4376 		0x291,0x3C4,0x1A2,  0x1A2,0x3C4,0x291,
4377 		0x5A2,0x1C4,0x6080, 0x6080,0x0C4,0x5080,
4378 		0x691,0x3C4,0x1A2,  0x5A2,0x3C4,0x691,
4379 		0x5080,0x2C4,0x691, 0x491,0x3080,0x4A2,
4380 		0x091,0x3080,0x4A2, 0x4A2,0x3080,0x491,
4381 		0x4A2,0x3080,0x491, 0x491,0x3080,0x4A2,
4382 		0x491,0x3080,0x4A2, 0x4A2,0x3080,0x091,
4383 		0x4A2,0x3080,0x491, 0x691,0x2C4,0x5080,
4384 		0x691,0x3C4,0x5A2,  0x1A2,0x3C4,0x691,
4385 		0x5080,0x0C4,0x6080,0x6080,0x1C4,0x5A2
4386 	},
4387 	/* 18 */
4388 	{
4389 		0x091,0x3080,0x4A2, 0x5A2,0x3C4,0x691,
4390 		0x4A2,0x3080,0x491, 0x491,0x3080,0x4A2,
4391 		0x691,0x3C4,0x5A2,  0x0A2,0x3080,0x091,
4392 		0x5A2,0x1C4,0x6080, 0x6080,0x0C4,0x5080,
4393 		0x691,0x3C4,0x1A2,  0x1A2,0x3C4,0x691,
4394 		0x5080,0x0C4,0x6080,0x6080,0x1C4,0x5A2,
4395 		0x091,0x3080,0x0A2, 0x5A2,0x3C4,0x691,
4396 		0x4A2,0x3080,0x491, 0x491,0x3080,0x4A2,
4397 		0x691,0x3C4,0x5A2,  0x4A2,0x3080,0x091,
4398 		0x5080,0x2C4,0x691, 0x691,0x2C4,0x5080
4399 	},
4400 	/* 19 */
4401 	{
4402 		0x691,0x3C4,0x1A2,  0x1A2,0x3C4,0x691,
4403 		0x5A2,0x1C4,0x4080, 0x2080,0x2080,0x4A2,
4404 		0x691,0x2C4,0x4080, 0x1080,0x1080,0x091,
4405 		0x5080,0x2C4,0x691, 0x291,0x2C4,0x5080,
4406 		0x091,0x3080,0x4A2, 0x5A2,0x3C4,0x691,
4407 
4408 		0x4A2,0x3080,0x491, 0x491,0x3080,0x4A2,
4409 		0x691,0x3C4,0x5A2,  0x4A2,0x3080,0x091,
4410 		0x5080,0x2C4,0x291, 0x691,0x2C4,0x5080,
4411 		0x091,0x1080,0x1080,0x4080,0x2C4,0x691,
4412 		0x4A2,0x2080,0x2080,0x4080,0x1C4,0x5A2
4413 	},
4414 	/* 20 */
4415 	{
4416 		0x291,0x3C4,0x5A2,  0x5A2,0x3C4,0x691,
4417 		0x5A2,0x3C4,0x691,  0x491,0x3080,0x4A2,
4418 		0x491,0x3080,0x4A2, 0x4A2,0x3080,0x091,
4419 		0x4A2,0x3080,0x091, 0x691,0x2C4,0x5080,
4420 		0x691,0x2C4,0x5080, 0x5080,0x2C4,0x691,
4421 		0x5080,0x2C4,0x691, 0x091,0x3080,0x4A2,
4422 		0x091,0x3080,0x4A2, 0x4A2,0x3080,0x091,
4423 		0x4A2,0x3080,0x091, 0x691,0x2C4,0x5080,
4424 		0x691,0x2C4,0x5080, 0x5080,0x2C4,0x691,
4425 		0x5080,0x2C4,0x691, 0x291,0x3C4,0x5A2
4426 	},
4427 	/* 21 */
4428 	{
4429 		0x691,0x3C4,0x1A2,  0x5A2,0x3C4,0x291,
4430 		0x5080,0x2C4,0x691, 0x691,0x2C4,0x5080,
4431 		0x291,0x3C4,0x5A2,  0x1A2,0x3C4,0x691,
4432 		0x5080,0x0C4,0x6080,0x6080,0x1C4,0x5A2,
4433 		0x091,0x3080,0x0A2, 0x5A2,0x3C4,0x691,
4434 		0x4A2,0x3080,0x491, 0x491,0x3080,0x4A2,
4435 		0x491,0x3080,0x4A2, 0x4A2,0x3080,0x491,
4436 		0x4A2,0x3080,0x491, 0x491,0x3080,0x4A2,
4437 		0x691,0x3C4,0x5A2,  0x0A2,0x3080,0x091,
4438 		0x5A2,0x1C4,0x6080, 0x6080,0x0C4,0x5080
4439 	}
4440 };
4441 
hexagonal(const VECTOR EPoint,const TPATTERN * TPat)4442 static DBL hexagonal (const VECTOR EPoint, const TPATTERN *TPat)
4443 {
4444 	unsigned short how;
4445 	long xv,zv;
4446 	DBL return_value=0;
4447 	DBL value;
4448 	DBL value1;
4449 	DBL value2;
4450 	DBL dist1;
4451 	DBL dist2;
4452 	DBL dist3;
4453 	DBL x,z;
4454 	int lng;
4455 
4456 	x=EPoint[X];
4457 	z=EPoint[Z];
4458 
4459 	xv = floor(x);
4460 	zv = floor(z/SQRT3);
4461 	x -= xv;
4462 	z -= SQRT3*zv;
4463 	/* x,z is in { [0.0, 1.0 [, [0.0, SQRT3 [ }
4464 	 ** There is some mirror to reduce the problem
4465 	 */
4466 	zv *= 2;
4467 	xv *= 2;
4468 	if ( z > SQRT3_2 )
4469 	{
4470 		z -= SQRT3_2;
4471 		if (x>0.5)
4472 		{
4473 			x -= 0.5;
4474 			xv++;
4475 		}
4476 		else
4477 		{
4478 			x += 0.5;
4479 			xv--;
4480 		}
4481 		zv++;
4482 	}
4483 	if ((x == 0.0)||(z/x>SQRT3))
4484 	{
4485 		z = SQRT3_2 - z;
4486 		x = 0.5 -x;
4487 		xv--;
4488 	}
4489 	if ((x == 1.0)||(z/(1.0-x)>SQRT3))
4490 	{
4491 		z = SQRT3_2 - z;
4492 		x = 1.5 -x;
4493 		xv++;
4494 	}
4495 	switch(TPat->Vals.Pavement.Tile)
4496 	{
4497 		case 5:
4498 			switch(TPat->Vals.Pavement.Number-1)
4499 			{
4500 				case 0:
4501 				case 2:
4502 				case 3:
4503 				case 5:
4504 				case 6:
4505 				case 19:
4506 					zv %= 10; if (zv < 0) { zv += 10; }
4507 					xv %= 6; if (xv < 0) { xv += 6; }
4508 					xv += 6*zv; /* 60 */
4509 					zv = 0;
4510 					break;
4511 				case 1:
4512 				case 4:
4513 				case 9:
4514 					zv -= 2*(((xv%30+(xv%30<0?30:0))/6));
4515 					zv %= 10; if (zv < 0) { zv += 10; }
4516 					xv %= 6; if (xv < 0) { xv += 6; }
4517 					xv += 6*zv; /* 60 */
4518 					zv = 0;
4519 					break;
4520 				case 7:
4521 					zv -= 7*(((xv%60+(xv%60<0?60:0))/3));
4522 					zv %= 20; if (zv < 0) { zv += 20; }
4523 					xv %= 3; if (xv < 0) { xv += 3; }
4524 					xv += 3*zv; /* 60 */
4525 					zv = 0;
4526 					break;
4527 				case 8:
4528 				case 10:
4529 				case 13:
4530 				case 14:
4531 				case 15:
4532 				case 17:
4533 				case 20:
4534 				case 21:
4535 					zv += 2*(((xv%30+(xv%30<0?30:0))/6));
4536 					zv %= 10; if (zv < 0) { zv += 10; }
4537 					xv %= 6; if (xv < 0) { xv += 6; }
4538 					xv += 6*zv; /* 60 */
4539 					zv = 0;
4540 					break;
4541 				case 11:
4542 				case 16:
4543 					zv -= 6*(((xv%30+(xv%30<0?30:0))/6));
4544 					zv %= 10; if (zv < 0) { zv += 10; }
4545 					xv %= 6; if (xv < 0) { xv += 6; }
4546 					xv += 6*zv; /* 60 */
4547 					zv = 0;
4548 					break;
4549 				case 12:
4550 				case 18:
4551 					zv += 6*(((xv%30+(xv%30<0?30:0))/6));
4552 					zv %= 10; if (zv < 0) { zv += 10; }
4553 					xv %= 6; if (xv < 0) { xv += 6; }
4554 					xv += 6*zv; /* 60 */
4555 					zv = 0;
4556 					break;
4557 			}
4558 			how = hexpentagon[TPat->Vals.Pavement.Number-1][xv];
4559 			break;
4560 		case 4:
4561 			switch(TPat->Vals.Pavement.Number-1)
4562 			{
4563 				case 0:
4564 					zv &= 0x07;
4565 					xv %= 6; if(xv <0) { xv += 6; }
4566 					xv += 6*zv; /* 48 */
4567 					zv = 0;
4568 					break;
4569 				case 3:
4570 					zv -= 2*(((xv%24+(xv%24<0?24:0))/6));
4571 					zv %= 8; if (zv < 0) { zv += 8; }
4572 					xv %= 6; if (xv < 0) { xv += 6; }
4573 					xv += 6*zv; /* 48 */
4574 					zv = 0;
4575 					break;
4576 				case 2:
4577 					zv &= 0x01;
4578 					xv %= 12; if (xv < 0) { xv += 12; }
4579 					xv += 12*zv; /* 24 */
4580 					zv = 0;
4581 					break;
4582 				case 5:
4583 				case 4:
4584 					zv -= 2*(((xv%24+(xv%24<0?24:0))/6));
4585 					zv %= 8; if (zv < 0) { zv += 8; }
4586 					xv %= 6; if (xv < 0) { xv += 6; }
4587 					xv += 6*zv; /* 48 */
4588 					zv = 0;
4589 					break;
4590 				case 1:
4591 					zv += 2*(((xv%12+(xv%12<0?12:0))/6));
4592 					zv %= 8; if (zv < 0) { zv += 8; }
4593 					xv %= 6; if (xv < 0) { xv += 6; }
4594 					xv += 6*zv; /* 48 */
4595 					zv = 0;
4596 					break;
4597 				case 6:
4598 					zv %= 4; if (zv < 0) { zv += 4; }
4599 					xv %= 12; if (xv < 0) { xv += 12; }
4600 					xv += 12*zv; /* 48 */
4601 					zv = 0;
4602 					break;
4603 			}
4604 			how = hextetragon[TPat->Vals.Pavement.Number-1][xv];
4605 			break;
4606 		case 3:
4607 			switch(TPat->Vals.Pavement.Number-1)
4608 			{
4609 				case 0:
4610 					zv %= 6; if(zv <0) { zv += 6; }
4611 					xv %= 6; if(xv <0) { xv += 6; }
4612 					xv += 6*zv;
4613 					zv = 0;
4614 					break;
4615 				case 1:
4616 					zv += 2*(((xv%18+(xv%18<0?18:0))/6));
4617 					zv %= 6; if(zv <0) { zv += 6; }
4618 					xv %= 6; if(xv <0) { xv += 6; }
4619 					xv += 6*zv;
4620 					zv = 0;
4621 					break;
4622 				case 2:
4623 					zv &= 0x01;
4624 					xv %= 18; if (xv < 0) { xv += 18; }
4625 					xv += 18*zv;
4626 					zv = 0x00;
4627 					break;
4628 			}
4629 			how = hextrigon[TPat->Vals.Pavement.Number-1][xv];
4630 			break;
4631 		case 2:
4632 			zv &= 0x01;
4633 			xv %= 6; if (xv < 0) { xv += 6; }
4634 			how = hexdigon[TPat->Vals.Pavement.Number-1][xv+6*zv];
4635 			break;
4636 		case 1:
4637 		default:
4638 			zv &= 0x01;
4639 			xv += 3*zv;
4640 			xv %= 6; if (xv <0) { xv += 6;}
4641 			lng = 0;
4642 			how = hexmonogon[TPat->Vals.Pavement.Number-1][xv];
4643 			break;
4644 	}
4645 
4646 	/*
4647 	 **      / \
4648 	 **     1   \
4649 	 **    /     2
4650 	 **   /       \
4651 	 **  -----3-----
4652 	 ** height = sqrt(3)/2
4653 	 */
4654 	if (how & 0x01)
4655 	{
4656 		dist1 = 1.0 - (fabs(SQRT3 * x - z) * SQRT3 );
4657 		return_value = max(return_value,dist1);
4658 	}
4659 	if (how & 0x02)
4660 	{
4661 		dist2 = 1.0 - (fabs(SQRT3 * (1.0-x) - z) * SQRT3  );
4662 		return_value = max(return_value,dist2);
4663 	}
4664 	if (how & 0x04)
4665 	{
4666 		dist3 = 1.0 - (z * 2.0 * SQRT3 );
4667 		return_value = max(return_value,dist3);
4668 	}
4669 	switch(TPat->Vals.Pavement.Interior)
4670 	{
4671 		case 1:
4672 			dist1 = (1.0 - (fabs(SQRT3 * z + x) ));
4673 			dist2 = (1.0 - (fabs(SQRT3 * z - x + 1.0) ));
4674 			dist3 = (1.0 - (x * 2.0 ));
4675 			if ( (((how & 0x83) == 0x00)||((how & 0x4000) == 0x4000)) &&
4676 			     (dist1<0)&&(dist2<0) )
4677 			{
4678 				value1 = (3.0 / 2.0 *(fabs(SQRT3 * z + x) ) - 2.0);
4679 				value2 = (3.0 / 2.0 *(fabs(SQRT3 * z - x + 1.0) ) - 2.0);
4680 				value =  min(value1,value2);
4681 				return_value = max(return_value,value);
4682 			}
4683 			if ((((how & 0x85) == 0x00)||((how & 0x2000) == 0x2000))
4684 					&&(dist1>0)&&(dist3>0))
4685 			{
4686 				value1 = (1.0 - 3.0 / 2.0 * (fabs(SQRT3 * z + x) ));
4687 				value2 = (1.0 - (x * 3.0 ));
4688 				value =  min(value1,value2);
4689 				return_value = max(return_value,value);
4690 			}
4691 			if ((((how & 0x86) == 0x00)||((how & 0x1000) == 0x1000))
4692 					&&(dist3<0)&&(dist2>0))
4693 			{
4694 				value1 = (1.0 - 3.0 / 2.0 *(fabs(SQRT3 * z - x + 1.0) ));
4695 				value2 = ((x * 3.0 ) - 2.0);
4696 				value =  min(value1,value2);
4697 				return_value = max(return_value,value);
4698 			}
4699 			break;
4700 		case 2:
4701 			if (((how & 0x83) == 0x00)||((how & 0x4000) == 0x4000))
4702 			{
4703 				dist1 = x - 0.5;
4704 				dist2 = z - SQRT3_2;
4705 				dist3 = 1.0 - (sqrt((dist1*dist1+dist2*dist2))*3.0 );
4706 				return_value = max(return_value,dist3);
4707 			}
4708 			if (((how & 0x85) == 0x00)||((how & 0x2000) == 0x2000))
4709 			{
4710 				dist1 = x;
4711 				dist2 = z;
4712 				dist3 = 1.0 - (sqrt((dist1*dist1+dist2*dist2)) *3.0);
4713 				return_value = max(return_value,dist3);
4714 			}
4715 			if (((how & 0x86) == 0x00)||((how & 0x1000) == 0x1000))
4716 			{
4717 				dist1 = x - 1.0;
4718 				dist2 = z ;
4719 				dist3 = 1.0 - (sqrt((dist1*dist1+dist2*dist2)) *3.0);
4720 				return_value = max(return_value,dist3);
4721 			}
4722 			break;
4723 		case 0:
4724 			if (((how & 0x83) == 0x00)||((how & 0x4000) == 0x4000))
4725 			{
4726 				dist3 = 1.0 - ((SQRT3_2 - z) * 2.0 * SQRT3  );
4727 				return_value = max(return_value,dist3);
4728 			}
4729 			if (((how & 0x85) == 0x00)||((how & 0x2000) == 0x2000))
4730 			{
4731 				dist2 = 1.0 - (fabs(SQRT3 * x + z) * SQRT3 );
4732 				return_value = max(return_value,dist2);
4733 			}
4734 			if (((how & 0x86) == 0x00)||((how & 0x1000) == 0x1000))
4735 			{
4736 				dist1 = 1.0 - (fabs(SQRT3 * (x -1.0) - z) * SQRT3 );
4737 				return_value = max(return_value,dist1);
4738 			}
4739 			break;
4740 	}
4741 	dist1 = (1.0 - (fabs(SQRT3 * z + x) ));
4742 	dist2 = (1.0 - (fabs(SQRT3 * z - x + 1.0) ));
4743 	dist3 = (1.0 - (x * 2.0 ));
4744 	switch(TPat->Vals.Pavement.Form)
4745 	{
4746 		case 2:
4747 			if (((how & 0x120) == 0x120)&&(dist1<0)&&(dist2<0))
4748 			{
4749 				value1 = x;
4750 				value2 = z;
4751 				value = 2.0*SQRT3*(sqrt(value1*value1+value2*value2 ) - SQRT3/3.0 );
4752 				value = max(value,0.0);
4753 				return_value = min(value,1.0);
4754 				return return_value;
4755 			}
4756 			if (((how & 0x140) == 0x140)&&(dist1>0)&&(dist3>0))
4757 			{
4758 				value1 = x - 0.5;
4759 				value2 = z- SQRT3_2;
4760 				value = 2.0*SQRT3*(sqrt(value1*value1+value2*value2 ) - SQRT3/3.0 );
4761 				value = max(value,0.0);
4762 				return_value = min(value,1.0);
4763 				return return_value;
4764 			}
4765 			if (((how & 0x210) == 0x210)&&(dist1<0)&&(dist2<0))
4766 			{
4767 				value1 = x - 1.0;
4768 				value2 = z;
4769 				value = 2.0*SQRT3*(sqrt(value1*value1+value2*value2 ) - SQRT3/3.0 );
4770 				value = max(value,0.0);
4771 				return_value = min(value,1.0);
4772 				return return_value;
4773 			}
4774 			if (((how & 0x240) == 0x240)&&(dist3<0)&&(dist2>0))
4775 			{
4776 				value1 = x - 0.5;
4777 				value2 = z - SQRT3_2;
4778 				value = 2.0*SQRT3*(sqrt(value1*value1+value2*value2 ) - SQRT3/3.0 );
4779 				value = max(value,0.0);
4780 				return_value = min(value,1.0);
4781 				return return_value;
4782 			}
4783 			if (((how & 0x410) == 0x410)&&(dist1>0)&&(dist3>0))
4784 			{
4785 				value1 = x - 1.0;
4786 				value2 = z;
4787 				value = 2.0*SQRT3*(sqrt(value1*value1+value2*value2 ) - SQRT3/3.0 );
4788 				value = max(value,0.0);
4789 				return_value = min(value,1.0);
4790 				return return_value;
4791 			}
4792 			if (((how & 0x420) == 0x420)&&(dist3<0)&&(dist2>0))
4793 			{
4794 				value1 = x;
4795 				value2 = z;
4796 				value = 2.0*SQRT3*(sqrt(value1*value1+value2*value2 ) - SQRT3/3.0 );
4797 				value = max(value,0.0);
4798 				return_value = min(value,1.0);
4799 				return return_value;
4800 			}
4801 			break;
4802 		case 1:
4803 			if (((how & 0x120) == 0x120)&&(dist1<0)&&(dist2<0))
4804 			{
4805 				value = -dist1 * 2;
4806 				return_value = min(value,1.0);
4807 				return return_value;
4808 			}
4809 			if (((how & 0x140) == 0x140)&&(dist1>0)&&(dist3>0))
4810 			{
4811 				value = dist1 * 2;
4812 				return_value = min(value,1.0);
4813 				return return_value;
4814 			}
4815 			if (((how & 0x210) == 0x210)&&(dist1<0)&&(dist2<0))
4816 			{
4817 				value = -dist2 * 2;
4818 				return_value = min(value,1.0);
4819 				return return_value;
4820 			}
4821 			if (((how & 0x240) == 0x240)&&(dist3<0)&&(dist2>0))
4822 			{
4823 				value = dist2 * 2;
4824 				return_value = min(value,1.0);
4825 				return return_value;
4826 			}
4827 			if (((how & 0x410) == 0x410)&&(dist1>0)&&(dist3>0))
4828 			{
4829 				value = dist3 * 2;
4830 				return_value = min(value,1.0);
4831 				return return_value;
4832 			}
4833 			if (((how & 0x420) == 0x420)&&(dist2>0)&&(dist3<0))
4834 			{
4835 				value = -dist3 * 2;
4836 				return_value = min(value,1.0);
4837 				return return_value;
4838 			}
4839 			if (((how & 0x120) == 0x120)&&(dist1<0)&&(dist2<0))
4840 			{
4841 				value = -dist1 * 2;
4842 				return_value = min(value,1.0);
4843 				return return_value;
4844 			}
4845 			break;
4846 		default:
4847 		case 0:
4848 			break;
4849 	}
4850 	return return_value;
4851 }
4852 
4853 /*****************************************************************************
4854 *
4855 * FUNCTION
4856 *
4857 *   tiling_pattern
4858 *
4859 * INPUT
4860 *
4861 *   EPoint -- The point in 3d space at which the pattern is evaluated.
4862 *   TPat   -- Texture pattern struct
4863 *
4864 * OUTPUT
4865 *
4866 * RETURNS
4867 *
4868 *   DBL value in the range 0.0 to 1.0
4869 *
4870 * AUTHOR
4871 *
4872 *   J. Grimbert
4873 *
4874 * DESCRIPTION
4875 *
4876 *   Classical tiling patterns
4877 *
4878 * CHANGES
4879 *
4880 *
4881 ******************************************************************************/
tiling_pattern(const VECTOR EPoint,const TPATTERN * TPat)4882 static DBL tiling_pattern (const VECTOR EPoint, const TPATTERN *TPat)
4883 {
4884 	switch(TPat->Vals.Tiling.Pattern)
4885 	{
4886 		case 27: return tiling_penrose(EPoint, true, false);
4887 		case 26: return tiling_penrose(EPoint, false, false);
4888 		case 25: return tiling_penrose1(EPoint, false);
4889 		case 24: return tiling_dodeca_hex_5(EPoint);
4890 		case 23: return tiling_dodeca_hex(EPoint);
4891 		case 22: return tiling_dodeca_tri(EPoint);
4892 		case 21: return tiling_square_tri(EPoint);
4893 		case 20: return tiling_hexa_tri_left(EPoint);
4894 		case 19: return tiling_hexa_tri_right(EPoint);
4895 		case 18: return tiling_rectangle_pair(EPoint);
4896 		case 17: return tiling_hexa_square_triangle_6(EPoint);
4897 		case 16: return tiling_hexa_square_triangle(EPoint);
4898 		case 15: return tiling_square_double(EPoint);
4899 		case 14: return tiling_square_internal_5(EPoint);
4900 		case 13: return tiling_square_internal(EPoint);
4901 		case 12: return tiling_rectangle_square(EPoint);
4902 		case 11: return tiling_square_rectangle(EPoint);
4903 		case 10: return tiling_square_offset(EPoint);
4904 		case 9: return tiling_hexa_triangle(EPoint);
4905 		case 8: return tiling_square_triangle(EPoint);
4906 		case 7: return tiling_octa_square(EPoint);
4907 		case 6: return tiling_rectangle(EPoint);
4908 		case 5: return tiling_rhombus(EPoint);
4909 		case 4: return tiling_lozenge(EPoint);
4910 		case 3: return tiling_triangle(EPoint);
4911 		case 2: return tiling_hexagon(EPoint);
4912 		case 1:
4913 		default:
4914 			return tiling_square(EPoint);
4915 	}
4916 }
4917 
4918 /*****************************************************************************
4919 *
4920 * FUNCTION
4921 *
4922 *   tiling_pattern
4923 *
4924 * INPUT
4925 *
4926 *   EPoint -- The point in 3d space at which the pattern is evaluated.
4927 *   TPat   -- Texture pattern struct
4928 *
4929 * OUTPUT
4930 *
4931 * RETURNS
4932 *
4933 *   DBL value in the range 0.0 to 1.0
4934 *
4935 * AUTHOR
4936 *
4937 *   J. Grimbert
4938 *
4939 * DESCRIPTION
4940 *
4941 *   Classical tiling patterns
4942 *
4943 * CHANGES
4944 *
4945 *
4946 ******************************************************************************/
pavement_pattern(const VECTOR EPoint,const TPATTERN * TPat)4947 static DBL pavement_pattern (const VECTOR EPoint, const TPATTERN *TPat)
4948 {
4949 	switch(TPat->Vals.Pavement.Side)
4950 	{
4951 		case 6:
4952 			return hexagonal(EPoint,TPat);
4953 
4954 		case 4:
4955 			return tetragonal(EPoint,TPat);
4956 
4957 		case 3:
4958 		default:
4959 			return trigonal(EPoint,TPat);
4960 	}
4961 }
4962 
4963 /*****************************************************************************
4964 *
4965 * FUNCTION
4966 *
4967 *   agate_pattern
4968 *
4969 * INPUT
4970 *
4971 *   EPoint -- The point in 3d space at which the pattern is evaluated.
4972 *   TPat   -- Texture pattern struct
4973 *
4974 * OUTPUT
4975 *
4976 * RETURNS
4977 *
4978 *   DBL value in the range 0.0 to 1.0
4979 *
4980 * AUTHOR
4981 *
4982 *   POV-Ray Team
4983 *
4984 * DESCRIPTION
4985 *
4986 * CHANGES
4987 *
4988 *   Oct 1994    : adapted from agate pigment by [CY]
4989 *
4990 ******************************************************************************/
4991 
agate_pattern(const VECTOR EPoint,const TPATTERN * TPat,int noise_generator)4992 static DBL agate_pattern (const VECTOR EPoint, const TPATTERN *TPat, int noise_generator)
4993 {
4994 	DBL noise, turb_val;
4995 	const TURB* Turb;
4996 
4997 	Turb=Search_For_Turb(TPat->Warps);
4998 
4999 	turb_val = TPat->Vals.Agate_Turb_Scale * Turbulence(EPoint,Turb,noise_generator);
5000 
5001 	noise = 0.5 * (cycloidal(1.3 * turb_val + 1.1 * EPoint[Z]) + 1.0);
5002 
5003 	if (noise < 0.0)
5004 	{
5005 		noise = 0.0;
5006 	}
5007 	else
5008 	{
5009 		noise = min(1.0, noise);
5010 		noise = pow(noise, 0.77);
5011 	}
5012 
5013 	return(noise);
5014 }
5015 
5016 
5017 /*****************************************************************************
5018 *
5019 * FUNCTION
5020 *
5021 *   boxed_pattern
5022 *
5023 * INPUT
5024 *
5025 *   EPoint -- The point in 3d space at which the pattern
5026 *   is evaluated.
5027 *
5028 * OUTPUT
5029 *
5030 * RETURNS
5031 *
5032 *   DBL value in the range 0.0 to 1.0
5033 *
5034 * AUTHOR
5035 *
5036 *   -
5037 *
5038 * DESCRIPTION
5039 *
5040 *   -
5041 *
5042 * CHANGES
5043 *
5044 *   -
5045 *
5046 ******************************************************************************/
5047 
boxed_pattern(const VECTOR EPoint)5048 static DBL boxed_pattern (const VECTOR EPoint)
5049 {
5050 	DBL value;
5051 
5052 	value = max(fabs(EPoint[X]), max(fabs(EPoint[Y]), fabs(EPoint[Z])));
5053 	CLIP_DENSITY(value);
5054 
5055 	return(value);
5056 }
5057 
5058 
5059 /*****************************************************************************
5060 *
5061 * FUNCTION
5062 *
5063 *   brick_pattern
5064 *
5065 * INPUT
5066 *
5067 *   EPoint -- The point in 3d space at which the pattern
5068 *   is evaluated.
5069 *   TPat   -- Texture pattern struct
5070 *
5071 * OUTPUT
5072 *
5073 * RETURNS
5074 *
5075 *   DBL value exactly 0.0 or 1.0
5076 *
5077 * AUTHOR
5078 *
5079 *   Dan Farmer
5080 *
5081 * DESCRIPTION
5082 *
5083 * CHANGES
5084 *
5085 *   Oct 1994    : adapted from pigment by [CY]
5086 *
5087 ******************************************************************************/
5088 
brick_pattern(const VECTOR EPoint,const TPATTERN * TPat)5089 static DBL brick_pattern (const VECTOR EPoint, const TPATTERN *TPat)
5090 {
5091 	int ibrickx, ibricky, ibrickz;
5092 	DBL brickheight, brickwidth, brickdepth;
5093 	DBL brickmortar, mortarheight, mortarwidth, mortardepth;
5094 	DBL brickx, bricky, brickz;
5095 	DBL x, y, z, fudgit;
5096 
5097 	fudgit=EPSILON+TPat->Vals.Brick.Mortar;
5098 
5099 	x =  EPoint[X]+fudgit;
5100 	y =  EPoint[Y]+fudgit;
5101 	z =  EPoint[Z]+fudgit;
5102 
5103 	brickwidth  = TPat->Vals.Brick.Size[X];
5104 	brickheight = TPat->Vals.Brick.Size[Y];
5105 	brickdepth  = TPat->Vals.Brick.Size[Z];
5106 	brickmortar = (DBL)TPat->Vals.Brick.Mortar;
5107 
5108 	mortarwidth  = brickmortar / brickwidth;
5109 	mortarheight = brickmortar / brickheight;
5110 	mortardepth  = brickmortar / brickdepth;
5111 
5112 	/* 1) Check mortar layers in the X-Z plane (ie: top view) */
5113 
5114 	bricky = y / brickheight;
5115 	ibricky = (int) bricky;
5116 	bricky -= (DBL) ibricky;
5117 
5118 	if (bricky < 0.0)
5119 	{
5120 		bricky += 1.0;
5121 	}
5122 
5123 	if (bricky <= mortarheight)
5124 	{
5125 		return(0.0);
5126 	}
5127 
5128 	bricky = (y / brickheight) * 0.5;
5129 	ibricky = (int) bricky;
5130 	bricky -= (DBL) ibricky;
5131 
5132 	if (bricky < 0.0)
5133 	{
5134 		bricky += 1.0;
5135 	}
5136 
5137 
5138 	/* 2) Check ODD mortar layers in the Y-Z plane (ends) */
5139 
5140 	brickx = (x / brickwidth);
5141 	ibrickx = (int) brickx;
5142 	brickx -= (DBL) ibrickx;
5143 
5144 	if (brickx < 0.0)
5145 	{
5146 		brickx += 1.0;
5147 	}
5148 
5149 	if ((brickx <= mortarwidth) && (bricky <= 0.5))
5150 	{
5151 		return(0.0);
5152 	}
5153 
5154 	/* 3) Check EVEN mortar layers in the Y-Z plane (ends) */
5155 
5156 	brickx = (x / brickwidth) + 0.5;
5157 	ibrickx = (int) brickx;
5158 	brickx -= (DBL) ibrickx;
5159 
5160 	if (brickx < 0.0)
5161 	{
5162 		brickx += 1.0;
5163 	}
5164 
5165 	if ((brickx <= mortarwidth) && (bricky > 0.5))
5166 	{
5167 		return(0.0);
5168 	}
5169 
5170 	/* 4) Check ODD mortar layers in the Y-X plane (facing) */
5171 
5172 	brickz = (z / brickdepth);
5173 	ibrickz = (int) brickz;
5174 	brickz -= (DBL) ibrickz;
5175 
5176 	if (brickz < 0.0)
5177 	{
5178 		brickz += 1.0;
5179 	}
5180 
5181 	if ((brickz <= mortardepth) && (bricky > 0.5))
5182 	{
5183 		return(0.0);
5184 	}
5185 
5186 	/* 5) Check EVEN mortar layers in the X-Y plane (facing) */
5187 
5188 	brickz = (z / brickdepth) + 0.5;
5189 	ibrickz = (int) brickz;
5190 	brickz -= (DBL) ibrickz;
5191 
5192 	if (brickz < 0.0)
5193 	{
5194 		brickz += 1.0;
5195 	}
5196 
5197 	if ((brickz <= mortardepth) && (bricky <= 0.5))
5198 	{
5199 		return(0.0);
5200 	}
5201 
5202 	/* If we've gotten this far, color me brick. */
5203 
5204 	return(1.0);
5205 }
5206 
5207 
5208 /*****************************************************************************
5209 *
5210 * FUNCTION
5211 *
5212 *   cells_pattern
5213 *
5214 * INPUT
5215 *
5216 *   EPoint -- The point in 3d space at which the pattern
5217 *   is evaluated.
5218 * OUTPUT
5219 *
5220 * RETURNS
5221 *
5222 *   DBL value in the range 0.0 to 1.0
5223 *
5224 * AUTHOR
5225 *
5226 *   John VanSickle
5227 *
5228 * DESCRIPTION
5229 *
5230 *   "cells":
5231 *
5232 *   New colour function by John VanSickle,
5233 *     vansickl@erols.com
5234 *
5235 *   Assigns a pseudorandom value to each unit cube.  The value for the cube in
5236 *   which the evaluted point lies is returned.
5237 *
5238 *   All "cells" specific source code and examples are in the public domain.
5239 *
5240 * CHANGES
5241 *
5242 *   -
5243 *
5244 ******************************************************************************/
5245 
cells_pattern(const VECTOR EPoint)5246 static DBL cells_pattern (const VECTOR EPoint)
5247 {
5248 	/* select a random value based on the cube from which this came. */
5249 
5250 	/* floor the values, instead of just truncating - this eliminates duplicated cells
5251 	around the axes */
5252 
5253 	return min(PatternRands(Hash3d((int)floor(EPoint[X]+EPSILON), (int)floor(EPoint[Y]+EPSILON), (int)floor(EPoint[Z]+EPSILON))), 1.0);
5254 }
5255 
5256 
5257 /*****************************************************************************
5258 *
5259 * FUNCTION
5260 *
5261 *   checker_pattern
5262 *
5263 * INPUT
5264 *
5265 *   EPoint -- The point in 3d space at which the pattern
5266 *   is evaluated.
5267 *
5268 * OUTPUT
5269 *
5270 * RETURNS
5271 *
5272 *   DBL value exactly 0.0 or 1.0
5273 *
5274 * AUTHOR
5275 *
5276 *   POV-Team
5277 *
5278 * DESCRIPTION
5279 *
5280 * CHANGES
5281 *   Oct 1994    : adapted from pigment by [CY]
5282 *
5283 ******************************************************************************/
5284 
checker_pattern(const VECTOR EPoint)5285 static DBL checker_pattern (const VECTOR EPoint)
5286 {
5287 	int value;
5288 
5289 	value = (int)(floor(EPoint[X]+EPSILON) +
5290 	              floor(EPoint[Y]+EPSILON) +
5291 	              floor(EPoint[Z]+EPSILON));
5292 
5293 	if (value & 1)
5294 	{
5295 		return (1.0);
5296 	}
5297 	else
5298 	{
5299 		return (0.0);
5300 	}
5301 }
5302 
5303 
5304 /*****************************************************************************
5305 *
5306 * FUNCTION
5307 *
5308 *   crackle_pattern
5309 *
5310 * INPUT
5311 *
5312 *   EPoint -- The point in 3d space at which the pattern
5313 *   is evaluated.
5314 * OUTPUT
5315 *
5316 * RETURNS
5317 *
5318 *   DBL value in the range 0.0 to 1.0
5319 *
5320 * AUTHOR
5321 *
5322 *   Jim McElhiney
5323 *
5324 * DESCRIPTION
5325 *
5326 *   "crackle":
5327 *
5328 *   New colour function by Jim McElhiney,
5329 *     CompuServe 71201,1326, aka mcelhiney@acm.org
5330 *
5331 *   Large scale, without turbulence, makes a pretty good stone wall.
5332 *   Small scale, without turbulence, makes a pretty good crackle ceramic glaze.
5333 *   Highly turbulent (with moderate displacement) makes a good marble, solving
5334 *   the problem of apparent parallel layers in Perlin's method.
5335 *   2 octaves of full-displacement turbulence make a great "drizzled paint"
5336 *   pattern, like a 1950's counter top.
5337 *   Rule of thumb:  put a single colour transition near 0 in your colour map.
5338 *
5339 *   Mathematically, the set crackle(p)=0 is a 3D Voronoi diagram of a field of
5340 *   semirandom points, and crackle(p)>0 is distance from set along shortest path.
5341 *   (A Voronoi diagram is the locus of points equidistant from their 2 nearest
5342 *   neighbours from a set of disjoint points, like the membranes in suds are
5343 *   to the centres of the bubbles).
5344 *
5345 *   All "crackle" specific source code and examples are in the public domain.
5346 *
5347 * CHANGES
5348 *   Oct 1994    : adapted from pigment by [CY]
5349 *   Other changes: enhanced by Ron Parker, Integer math by Nathan Kopp
5350 *
5351 ******************************************************************************/
5352 static int IntPickInCube(int tvx, int tvy, int tvz, VECTOR  p1);
5353 
crackle_pattern(const VECTOR EPoint,const TPATTERN * TPat,TraceThreadData * Thread)5354 static DBL crackle_pattern (const VECTOR EPoint, const TPATTERN *TPat, TraceThreadData *Thread)
5355 {
5356 	DBL sum, minsum, minsum2, minsum3, tf;
5357 	int minVecIdx = 0;
5358 	VECTOR dv;
5359 
5360 	int flox, floy, floz;
5361 
5362 	DBL Metric = TPat->Vals.Crackle.Metric;
5363 	DBL Offset = TPat->Vals.Crackle.Offset;
5364 
5365 	bool UseSquare = ( Metric == 2);
5366 	bool UseUnity  = ( Metric == 1);
5367 
5368 	/*
5369 	 * This uses floor() not FLOOR, so it will not be a mirror
5370 	 * image about zero in the range -1.0 to 1.0. The viewer
5371 	 * won't see an artefact around the origin.
5372 	 */
5373 
5374 	flox = (int)floor(EPoint[X] - EPSILON);
5375 	floy = (int)floor(EPoint[Y] - EPSILON);
5376 	floz = (int)floor(EPoint[Z] - EPSILON);
5377 
5378 	/*
5379 	 * Check to see if the input point is in the same unit cube as the last
5380 	 * call to this function, to use cache of cubelets for speed.
5381 	 */
5382 
5383 	Crackle_Cell_Coord ccoord(flox, floy, floz);
5384 	Thread->Stats()[CrackleCache_Tests]++;
5385 
5386 	Crackle_Cache_Entry dummy_entry;
5387 	Crackle_Cache_Entry* entry = &dummy_entry;
5388 
5389 	// search for this hash value in the cache
5390 	Crackle_Cache_Type::iterator iter = Thread->Crackle_Cache.find(ccoord);
5391 	if (iter == Thread->Crackle_Cache.end())
5392 	{
5393 		/*
5394 		 * No, not same unit cube.  Calculate the random points for this new
5395 		 * cube and its 80 neighbours which differ in any axis by 1 or 2.
5396 		 * Why distance of 2?  If there is 1 point in each cube, located
5397 		 * randomly, it is possible for the closest random point to be in the
5398 		 * cube 2 over, or the one two over and one up.  It is NOT possible
5399 		 * for it to be two over and two up.  Picture a 3x3x3 cube with 9 more
5400 		 * cubes glued onto each face.
5401 		 */
5402 
5403 		// generate a new cache entry, but only if the size of the cache is reasonable.
5404 		// having to re-calculate entries that would have been cache hits had we not
5405 		// skipped on adding an entry is less expensive than chewing up immense amounts
5406 		// of RAM and finally hitting the swapfile. unfortunately there's no good way
5407 		// to tell how much memory is 'too much' for the cache, so we just use a hard-
5408 		// coded number for now (ideally we should allow the user to configure this).
5409 		// keep in mind that the cache memory usage is per-thread, so the more threads,
5410 		// the more RAM. if we don't do the insert, entry will point at a local variable.
5411 		if (Thread->Crackle_Cache.size() * sizeof(Crackle_Cache_Type::value_type) < 30 * 1024 * 1024)
5412 		{
5413 			iter = Thread->Crackle_Cache.insert(Thread->Crackle_Cache.end(), Crackle_Cache_Type::value_type(ccoord, Crackle_Cache_Entry()));
5414 			entry = &iter->second;
5415 			entry->last_used = Thread->ProgressIndex();
5416 		}
5417 
5418 		// see InitializeCrackleCubes() below.
5419 		int *pc = CrackleCubeTable;
5420 		for (int i = 0; i < 81; i++, pc += 3)
5421 			IntPickInCube(flox + pc[X], floy + pc[Y], floz + pc[Z], entry->data[i]);
5422 	}
5423 	else
5424 	{
5425 		Thread->Stats()[CrackleCache_Tests_Succeeded]++;
5426 		entry = &iter->second;
5427 	}
5428 
5429 	// Find the 3 points with the 3 shortest distances from the input point.
5430 	// Set up the loop so the invariant is true:  minsum <= minsum2 <= minsum3
5431 	VSub(dv, entry->data[0], EPoint);
5432 
5433 	if(UseSquare)
5434 	{
5435 		minsum = VSumSqr(dv);
5436 
5437 		VSub(dv, entry->data[1], EPoint);
5438 		minsum2 = VSumSqr(dv);
5439 
5440 		VSub(dv, entry->data[2], EPoint);
5441 		minsum3  = VSumSqr(dv);
5442 	}
5443 	else if(UseUnity)
5444 	{
5445 		minsum = fabs(dv[X]) + fabs(dv[Y]) + fabs(dv[Z]);
5446 
5447 		VSub(dv, entry->data[1], EPoint);
5448 		minsum2 = fabs(dv[X]) + fabs(dv[Y]) + fabs(dv[Z]);
5449 
5450 		VSub(dv, entry->data[2], EPoint);
5451 		minsum3 = fabs(dv[X]) + fabs(dv[Y]) + fabs(dv[Z]);
5452 	}
5453 	else
5454 	{
5455 		minsum = pow(fabs(dv[X]), Metric) +
5456 		         pow(fabs(dv[Y]), Metric) +
5457 		         pow(fabs(dv[Z]), Metric);
5458 
5459 		VSub(dv, entry->data[1], EPoint);
5460 		minsum2 = pow(fabs(dv[X]), Metric) +
5461 		          pow(fabs(dv[Y]), Metric) +
5462 		          pow(fabs(dv[Z]), Metric);
5463 
5464 		VSub(dv, entry->data[2], EPoint);
5465 		minsum3 = pow(fabs(dv[X]), Metric) +
5466 		          pow(fabs(dv[Y]), Metric) +
5467 		          pow(fabs(dv[Z]), Metric);
5468 	}
5469 
5470 	// sort the 3 computed sums
5471 	if(minsum2 < minsum)
5472 	{
5473 		tf = minsum; minsum = minsum2; minsum2 = tf;
5474 		minVecIdx = 1;
5475 	}
5476 
5477 	if(minsum3 < minsum)
5478 	{
5479 		tf = minsum; minsum = minsum3; minsum3 = tf;
5480 		minVecIdx = 2;
5481 	}
5482 
5483 	if(minsum3 < minsum2)
5484 	{
5485 		tf = minsum2; minsum2 = minsum3; minsum3 = tf;
5486 	}
5487 
5488 	// Loop for the 81 cubelets to find closest and 2nd closest.
5489 	for(int i = 3; i < 81; i++)
5490 	{
5491 		VSub(dv, entry->data[i], EPoint);
5492 
5493 		if(UseSquare)
5494 			sum  = VSumSqr(dv);
5495 		else if(UseUnity)
5496 			sum = fabs(dv[X]) + fabs(dv[Y]) + fabs(dv[Z]);
5497 		else
5498 			sum = pow(fabs(dv[X]), Metric) +
5499 			      pow(fabs(dv[Y]), Metric) +
5500 			      pow(fabs(dv[Z]), Metric);
5501 
5502 		if(sum < minsum)
5503 		{
5504 			minsum3 = minsum2;
5505 			minsum2 = minsum;
5506 			minsum = sum;
5507 			minVecIdx = i;
5508 		}
5509 		else if(sum < minsum2)
5510 		{
5511 			minsum3 = minsum2;
5512 			minsum2 = sum;
5513 		}
5514 		else if( sum < minsum3 )
5515 		{
5516 			minsum3 = sum;
5517 		}
5518 	}
5519 
5520 	if (Offset)
5521 	{
5522 		if(UseSquare)
5523 		{
5524 			minsum += Offset*Offset;
5525 			minsum2 += Offset*Offset;
5526 			minsum3 += Offset*Offset;
5527 		}
5528 		else if (UseUnity)
5529 		{
5530 			minsum += Offset;
5531 			minsum2 += Offset;
5532 			minsum3 += Offset;
5533 		}
5534 		else
5535 		{
5536 			minsum += pow( Offset, Metric );
5537 			minsum2 += pow( Offset, Metric );
5538 			minsum3 += pow( Offset, Metric );
5539 		}
5540 	}
5541 
5542 	if(TPat->Vals.Crackle.IsSolid)
5543 	{
5544 		tf = Noise( entry->data[minVecIdx], GetNoiseGen(TPat, Thread) );
5545 	}
5546 	else if(UseSquare)
5547 	{
5548 		tf = TPat->Vals.Crackle.Form[X]*sqrt(minsum) +
5549 		     TPat->Vals.Crackle.Form[Y]*sqrt(minsum2) +
5550 		     TPat->Vals.Crackle.Form[Z]*sqrt(minsum3);
5551 	}
5552 	else if(UseUnity)
5553 	{
5554 		tf = TPat->Vals.Crackle.Form[X]*minsum +
5555 		     TPat->Vals.Crackle.Form[Y]*minsum2 +
5556 		     TPat->Vals.Crackle.Form[Z]*minsum3;
5557 	}
5558 	else
5559 	{
5560 		tf = TPat->Vals.Crackle.Form[X]*pow(minsum, 1.0/Metric) +
5561 		     TPat->Vals.Crackle.Form[Y]*pow(minsum2, 1.0/Metric) +
5562 		     TPat->Vals.Crackle.Form[Z]*pow(minsum3, 1.0/Metric);
5563 	}
5564 
5565 	return max(min(tf, 1.), 0.);
5566 }
5567 
5568 
5569 /*****************************************************************************
5570 *
5571 * FUNCTION
5572 *
5573 *   cylindrical_pattern
5574 *
5575 * INPUT
5576 *
5577 *   EPoint -- The point in 3d space at which the pattern
5578 *   is evaluated.
5579 *
5580 * OUTPUT
5581 *
5582 * RETURNS
5583 *
5584 *   DBL value in the range 0.0 to 1.0
5585 *
5586 * AUTHOR
5587 *
5588 *   -
5589 *
5590 * DESCRIPTION
5591 *
5592 *   -
5593 *
5594 * CHANGES
5595 *
5596 *   -
5597 *
5598 ******************************************************************************/
5599 
cylindrical_pattern(const VECTOR EPoint)5600 static DBL cylindrical_pattern (const VECTOR EPoint)
5601 {
5602 	DBL value;
5603 
5604 	value = sqrt(Sqr(EPoint[X]) + Sqr(EPoint[Z]));
5605 	CLIP_DENSITY(value);
5606 
5607 	return(value);
5608 }
5609 
5610 
5611 /*****************************************************************************
5612 *
5613 * FUNCTION
5614 *
5615 *   density_pattern
5616 *
5617 * INPUT
5618 *
5619 * OUTPUT
5620 *
5621 * RETURNS
5622 *
5623 * AUTHOR
5624 *
5625 *   Dieter Bayer
5626 *
5627 * DESCRIPTION
5628 *
5629 * CHANGES
5630 *
5631 *   Dec 1996 : Creation.
5632 *
5633 ******************************************************************************/
5634 
intp3(float t,float fa,float fb,float fc,float fd)5635 inline float intp3(float t, float fa, float fb, float fc, float fd)
5636 {
5637 	float b,d,e,f;
5638 
5639 	b = (fc - fa) * 0.5;
5640 	d = (fd - fb) * 0.5;
5641 	e = 2.0 * (fb - fc) + b + d;
5642 	f = -3.0 * (fb - fc) - 2.0 * b - d;
5643 
5644 	return ((e * t + f) * t + b) * t + fb;
5645 }
5646 
intp3_2(float t,float fa,float fb,float fc,float fd)5647 inline float intp3_2(float t, float fa, float fb, float fc, float fd)
5648 {
5649 	float b,e,f;
5650 
5651 	e = fd - fc - fa + fb;
5652 	f = fa - fb - e;
5653 	b = fc - fa;
5654 
5655 	return ((e * t + f) * t + b) * t + fb;
5656 }
5657 
5658 #define zmax(i,imax) (((i)<0)?(imax-1):((i) % (imax)))
5659 
density_pattern(const VECTOR EPoint,const TPATTERN * TPat)5660 static DBL density_pattern(const VECTOR EPoint, const TPATTERN *TPat)
5661 {
5662 	size_t x, y, z;
5663 	size_t x1, y1, z1;
5664 	size_t x2, y2, z2;
5665 	DBL Ex, Ey, Ez;
5666 	DBL xx, yy, zz;
5667 	DBL xi, yi;
5668 	DBL f111, f112, f121, f122, f211, f212, f221, f222;
5669 	float intpd2[4][4];
5670 	DBL density = 0.0;
5671 	DENSITY_FILE_DATA *Data;
5672 	size_t k0, k1, k2, k3, i,j,ii,jj;
5673 
5674 	Ex=EPoint[X];
5675 	Ey=EPoint[Y];
5676 	Ez=EPoint[Z];
5677 
5678 	if((TPat->Vals.Density_File != NULL) && ((Data = TPat->Vals.Density_File->Data) != NULL) &&
5679 	   (Data->Sx) && (Data->Sy) && (Data->Sz))
5680 	{
5681 /*		if(Data->Cyclic == true)
5682 		{
5683 			Ex -= floor(Ex);
5684 			Ey -= floor(Ey);
5685 			Ez -= floor(Ez);
5686 		}
5687 */
5688 		if((Ex >= 0.0) && (Ex < 1.0) && (Ey >= 0.0) && (Ey < 1.0) && (Ez >= 0.0) && (Ez < 1.0))
5689 		{
5690 			switch (TPat->Vals.Density_File->Interpolation % 10)
5691 			{
5692 				case NO_INTERPOLATION:
5693 					x = (size_t)(Ex * (DBL)Data->Sx);
5694 					y = (size_t)(Ey * (DBL)Data->Sy);
5695 					z = (size_t)(Ez * (DBL)Data->Sz);
5696 
5697 					if ((x < 0) || (x >= Data->Sx) || (y < 0) || (y >= Data->Sy) || (z < 0) || (z >= Data->Sz))
5698 						density = 0.0;
5699 					else
5700 					{
5701 						if(Data->Type == 4)
5702 							density = (DBL)Data->Density32[z * Data->Sy * Data->Sx + y * Data->Sx + x] / (DBL)UINT_MAX;
5703 						else if(Data->Type==2)
5704 							density = (DBL)Data->Density16[z * Data->Sy * Data->Sx + y * Data->Sx + x] / (DBL)USHRT_MAX;
5705 						else if(Data->Type == 1)
5706 							density = (DBL)Data->Density8[z * Data->Sy * Data->Sx + y * Data->Sx + x] / (DBL)UCHAR_MAX;
5707 					}
5708 					break;
5709 				case TRILINEAR_INTERPOLATION:
5710 					xx = Ex * (DBL)(Data->Sx );
5711 					yy = Ey * (DBL)(Data->Sy );
5712 					zz = Ez * (DBL)(Data->Sz );
5713 
5714 					x1 = (size_t)xx;
5715 					y1 = (size_t)yy;
5716 					z1 = (size_t)zz;
5717 
5718 					x2 = (x1 + 1) % Data->Sx;
5719 					y2 = (y1 + 1) % Data->Sy;
5720 					z2 = (z1 + 1) % Data->Sz;
5721 
5722 					xx -= floor(xx);
5723 					yy -= floor(yy);
5724 					zz -= floor(zz);
5725 
5726 					xi = 1.0 - xx;
5727 					yi = 1.0 - yy;
5728 
5729 					if(Data->Type == 4)
5730 					{
5731 						f111 = (DBL)Data->Density32[z1 * Data->Sy * Data->Sx + y1 * Data->Sx + x1] / (DBL)UINT_MAX;
5732 						f112 = (DBL)Data->Density32[z1 * Data->Sy * Data->Sx + y1 * Data->Sx + x2] / (DBL)UINT_MAX;
5733 						f121 = (DBL)Data->Density32[z1 * Data->Sy * Data->Sx + y2 * Data->Sx + x1] / (DBL)UINT_MAX;
5734 						f122 = (DBL)Data->Density32[z1 * Data->Sy * Data->Sx + y2 * Data->Sx + x2] / (DBL)UINT_MAX;
5735 						f211 = (DBL)Data->Density32[z2 * Data->Sy * Data->Sx + y1 * Data->Sx + x1] / (DBL)UINT_MAX;
5736 						f212 = (DBL)Data->Density32[z2 * Data->Sy * Data->Sx + y1 * Data->Sx + x2] / (DBL)UINT_MAX;
5737 						f221 = (DBL)Data->Density32[z2 * Data->Sy * Data->Sx + y2 * Data->Sx + x1] / (DBL)UINT_MAX;
5738 						f222 = (DBL)Data->Density32[z2 * Data->Sy * Data->Sx + y2 * Data->Sx + x2] / (DBL)UINT_MAX;
5739 					}
5740 					else if(Data->Type == 2)
5741 					{
5742 						f111 = (DBL)Data->Density16[z1 * Data->Sy * Data->Sx + y1 * Data->Sx + x1] / (DBL)USHRT_MAX;
5743 						f112 = (DBL)Data->Density16[z1 * Data->Sy * Data->Sx + y1 * Data->Sx + x2] / (DBL)USHRT_MAX;
5744 						f121 = (DBL)Data->Density16[z1 * Data->Sy * Data->Sx + y2 * Data->Sx + x1] / (DBL)USHRT_MAX;
5745 						f122 = (DBL)Data->Density16[z1 * Data->Sy * Data->Sx + y2 * Data->Sx + x2] / (DBL)USHRT_MAX;
5746 						f211 = (DBL)Data->Density16[z2 * Data->Sy * Data->Sx + y1 * Data->Sx + x1] / (DBL)USHRT_MAX;
5747 						f212 = (DBL)Data->Density16[z2 * Data->Sy * Data->Sx + y1 * Data->Sx + x2] / (DBL)USHRT_MAX;
5748 						f221 = (DBL)Data->Density16[z2 * Data->Sy * Data->Sx + y2 * Data->Sx + x1] / (DBL)USHRT_MAX;
5749 						f222 = (DBL)Data->Density16[z2 * Data->Sy * Data->Sx + y2 * Data->Sx + x2] / (DBL)USHRT_MAX;
5750 					}
5751 					else if(Data->Type == 1)
5752 					{
5753 						f111 = (DBL)Data->Density8[z1 * Data->Sy * Data->Sx + y1 * Data->Sx + x1] / (DBL)UCHAR_MAX;
5754 						f112 = (DBL)Data->Density8[z1 * Data->Sy * Data->Sx + y1 * Data->Sx + x2] / (DBL)UCHAR_MAX;
5755 						f121 = (DBL)Data->Density8[z1 * Data->Sy * Data->Sx + y2 * Data->Sx + x1] / (DBL)UCHAR_MAX;
5756 						f122 = (DBL)Data->Density8[z1 * Data->Sy * Data->Sx + y2 * Data->Sx + x2] / (DBL)UCHAR_MAX;
5757 						f211 = (DBL)Data->Density8[z2 * Data->Sy * Data->Sx + y1 * Data->Sx + x1] / (DBL)UCHAR_MAX;
5758 						f212 = (DBL)Data->Density8[z2 * Data->Sy * Data->Sx + y1 * Data->Sx + x2] / (DBL)UCHAR_MAX;
5759 						f221 = (DBL)Data->Density8[z2 * Data->Sy * Data->Sx + y2 * Data->Sx + x1] / (DBL)UCHAR_MAX;
5760 						f222 = (DBL)Data->Density8[z2 * Data->Sy * Data->Sx + y2 * Data->Sx + x2] / (DBL)UCHAR_MAX;
5761 					}
5762 
5763 					density = ((f111 * xi + f112 * xx) * yi + (f121 * xi + f122 * xx) * yy) * (1.0 - zz) +
5764 					          ((f211 * xi + f212 * xx) * yi + (f221 * xi + f222 * xx) * yy) * zz;
5765 					break;
5766 				case TRICUBIC_INTERPOLATION:
5767 				default:
5768 					xx = Ex * (DBL)(Data->Sx);
5769 					yy = Ey * (DBL)(Data->Sy);
5770 					zz = Ez * (DBL)(Data->Sz);
5771 
5772 					x1 = (size_t)xx;
5773 					y1 = (size_t)yy;
5774 					z1 = (size_t)zz;
5775 
5776 					xx -= floor(xx);
5777 					yy -= floor(yy);
5778 					zz -= floor(zz);
5779 
5780 					k0 = zmax(-1+z1, Data->Sz );
5781 					k1 = zmax(   z1, Data->Sz );
5782 					k2 = zmax( 1+z1, Data->Sz );
5783 					k3 = zmax( 2+z1, Data->Sz );
5784 
5785 					if(Data->Type == 4)
5786 					{
5787 						for(i = 0; i < 4; i++)
5788 						{
5789 							ii = zmax(i + x1 - 1, Data->Sx);
5790 							for(j = 0; j < 4; j++)
5791 							{
5792 								jj = zmax(j + y1 - 1, Data->Sy);
5793 								intpd2[i][j] = intp3(zz,
5794 								                     Data->Density32[k0 * Data->Sy * Data->Sx + jj * Data->Sx + ii] / (DBL)UINT_MAX,
5795 								                     Data->Density32[k1 * Data->Sy * Data->Sx + jj * Data->Sx + ii] / (DBL)UINT_MAX,
5796 								                     Data->Density32[k2 * Data->Sy * Data->Sx + jj * Data->Sx + ii] / (DBL)UINT_MAX,
5797 								                     Data->Density32[k3 * Data->Sy * Data->Sx + jj * Data->Sx + ii] / (DBL)UINT_MAX);
5798 							}
5799 						}
5800 					}
5801 					else if(Data->Type == 2)
5802 					{
5803 						for(i = 0; i < 4; i++)
5804 						{
5805 							ii = zmax(i + x1 - 1, Data->Sx);
5806 							for(j = 0; j < 4; j++)
5807 							{
5808 								jj = zmax(j + y1 - 1, Data->Sy);
5809 								intpd2[i][j] = intp3(zz,
5810 								                     Data->Density16[k0 * Data->Sy * Data->Sx + jj * Data->Sx + ii] / (DBL)USHRT_MAX,
5811 								                     Data->Density16[k1 * Data->Sy * Data->Sx + jj * Data->Sx + ii] / (DBL)USHRT_MAX,
5812 								                     Data->Density16[k2 * Data->Sy * Data->Sx + jj * Data->Sx + ii] / (DBL)USHRT_MAX,
5813 								                     Data->Density16[k3 * Data->Sy * Data->Sx + jj * Data->Sx + ii] / (DBL)USHRT_MAX);
5814 							}
5815 						}
5816 					}
5817 					else if(Data->Type == 1)
5818 					{
5819 						for(i = 0; i < 4; i++)
5820 						{
5821 							ii = zmax(i + x1 - 1, Data->Sx);
5822 							for(j = 0; j < 4; j++)
5823 							{
5824 								jj = zmax(j + y1 - 1, Data->Sy);
5825 								intpd2[i][j] = intp3(zz,
5826 								                     Data->Density8[k0 * Data->Sy * Data->Sx + jj * Data->Sx + ii] / (DBL)UCHAR_MAX,
5827 								                     Data->Density8[k1 * Data->Sy * Data->Sx + jj * Data->Sx + ii] / (DBL)UCHAR_MAX,
5828 								                     Data->Density8[k2 * Data->Sy * Data->Sx + jj * Data->Sx + ii] / (DBL)UCHAR_MAX,
5829 								                     Data->Density8[k3 * Data->Sy * Data->Sx + jj * Data->Sx + ii] / (DBL)UCHAR_MAX);
5830 							}
5831 						}
5832 					}
5833 
5834 					for(i = 0; i < 4; i++)
5835 						intpd2[0][i] = intp3(yy, intpd2[i][0], intpd2[i][1],  intpd2[i][2], intpd2[i][3]);
5836 
5837 					density = intp3(xx, intpd2[0][0], intpd2[0][1], intpd2[0][2], intpd2[0][3]);
5838 					break;
5839 			}
5840 		}
5841 		else
5842 			density = 0.0;
5843 	}
5844 
5845 	if (density < 0.0)
5846 		density = 0.0;
5847 	return density;
5848 }
5849 
5850 
5851 /*****************************************************************************
5852 *
5853 * FUNCTION
5854 *
5855 *   dents_pattern
5856 *
5857 * INPUT
5858 *
5859 *   EPoint -- The point in 3d space at which the pattern
5860 *   is evaluated.
5861 *
5862 * OUTPUT
5863 *
5864 * RETURNS
5865 *
5866 *   DBL value in the range 0.0 to 1.0
5867 *
5868 * AUTHOR
5869 *
5870 *   POV-Ray Team
5871 *
5872 * DESCRIPTION   : Note this pattern is only used for pigments and textures.
5873 *                 Normals have a specialized pattern for this.
5874 *
5875 * CHANGES
5876 *   Nov 1994 : adapted from normal by [CY]
5877 *
5878 ******************************************************************************/
5879 
dents_pattern(const VECTOR EPoint,int noise_generator)5880 static DBL dents_pattern (const VECTOR EPoint, int noise_generator)
5881 {
5882 	DBL noise;
5883 
5884 	noise = Noise (EPoint, noise_generator);
5885 
5886 	return(noise * noise * noise);
5887 }
5888 
5889 
5890 /*****************************************************************************
5891 *
5892 * FUNCTION
5893 *
5894 *   function_pattern
5895 *
5896 * INPUT
5897 *
5898 *   EPoint -- The point in 3d space at which the pattern
5899 *   is evaluated.
5900 *
5901 * OUTPUT
5902 *
5903 * RETURNS
5904 *
5905 *   DBL value in the range 0.0 to 1.0
5906 *
5907 * AUTHOR
5908 *
5909 *   POV-Ray Team
5910 *
5911 * DESCRIPTION
5912 *
5913 * CHANGES
5914 *
5915 ******************************************************************************/
5916 
function_pattern(const VECTOR EPoint,const TPATTERN * TPat,TraceThreadData * Thread)5917 static DBL function_pattern (const VECTOR EPoint, const TPATTERN *TPat, TraceThreadData *Thread)
5918 {
5919 	DBL value;
5920 
5921 	if(Thread->functionPatternContext[TPat->Vals.Function.Data] == NULL)
5922 		Thread->functionPatternContext[TPat->Vals.Function.Data] = Thread->functionContext->functionvm->NewContext(const_cast<TraceThreadData *>(Thread));
5923 
5924 	FPUContext *ctx = Thread->functionPatternContext[TPat->Vals.Function.Data];
5925 
5926 	ctx->SetLocal(X, EPoint[X]);
5927 	ctx->SetLocal(Y, EPoint[Y]);
5928 	ctx->SetLocal(Z, EPoint[Z]);
5929 
5930 	value = POVFPU_Run(ctx, *(reinterpret_cast<const FUNCTION*>(TPat->Vals.Function.Fn)));
5931 
5932 	return ((value > 1.0) ? fmod(value, 1.0) : value);
5933 }
5934 
5935 
5936 /*****************************************************************************
5937 *
5938 * FUNCTION
5939 *
5940 *   gradient_pattern
5941 *
5942 * INPUT
5943 *
5944 *   EPoint -- The point in 3d space at which the pattern
5945 *   is evaluated.
5946 *
5947 * OUTPUT
5948 *
5949 * RETURNS
5950 *
5951 *   DBL value in the range 0.0 to 1.0
5952 *
5953 * AUTHOR
5954 *
5955 *   POV-Ray Team
5956 *
5957 * DESCRIPTION
5958 *
5959 *   Gradient Pattern - gradient based on the fractional values of
5960 *   x, y or z, based on whether or not the given directional vector is
5961 *   a 1.0 or a 0.0.
5962 *   The basic concept of this is from DBW Render, but Dave Wecker's
5963 *   only supports simple Y axis gradients.
5964 *
5965 * CHANGES
5966 *
5967 *   Oct 1994    : adapted from pigment by [CY]
5968 *
5969 ******************************************************************************/
5970 
gradient_pattern(const VECTOR EPoint,const TPATTERN * TPat)5971 static DBL gradient_pattern (const VECTOR EPoint, const TPATTERN *TPat)
5972 {
5973 	DBL Result;
5974 	VDot( Result, EPoint, TPat->Vals.Gradient );
5975 
5976 	/* Mod to keep within [0.0,1.0] range */
5977 	return ((Result > 1.0) ? fmod(Result, 1.0) : Result);
5978 }
5979 
5980 
5981 /*****************************************************************************
5982 *
5983 * FUNCTION
5984 *
5985 *   granite_pattern
5986 *
5987 * INPUT
5988 *
5989 *   EPoint -- The point in 3d space at which the pattern
5990 *   is evaluated.
5991 *
5992 * OUTPUT
5993 *
5994 * RETURNS
5995 *
5996 *   DBL value in the range 0.0 to 1.0
5997 *
5998 * AUTHOR
5999 *
6000 *   POV-Ray Team
6001 *
6002 * DESCRIPTION
6003 *
6004 *   Granite - kind of a union of the "spotted" and the "dented" textures,
6005 *   using a 1/f fractal noise function for color values. Typically used
6006 *   with small scaling values. Should work with colour maps for pink granite.
6007 *
6008 * CHANGES
6009 *
6010 *   Oct 1994    : adapted from pigment by [CY]
6011 *
6012 ******************************************************************************/
6013 
granite_pattern(const VECTOR EPoint,int noise_generator)6014 static DBL granite_pattern (const VECTOR EPoint, int noise_generator)
6015 {
6016 	int i;
6017 	DBL temp, noise = 0.0, freq = 1.0;
6018 	VECTOR tv1,tv2;
6019 
6020 	VScale(tv1,EPoint,4.0);
6021 
6022 	for (i = 0; i < 6 ; freq *= 2.0, i++)
6023 	{
6024 		VScale(tv2,tv1,freq);
6025 		if(noise_generator==1)
6026 		{
6027 			temp = 0.5 - Noise (tv2, noise_generator);
6028 			temp = fabs(temp);
6029 		}
6030 		else
6031 		{
6032 			temp = 1.0 - 2.0 * Noise (tv2, noise_generator);
6033 			temp = fabs(temp);
6034 			if (temp>0.5) temp=0.5;
6035 		}
6036 
6037 		noise += temp / freq;
6038 	}
6039 
6040 	return(noise);
6041 }
6042 
6043 
6044 /*****************************************************************************
6045 *
6046 * FUNCTION
6047 *
6048 *   hexagon_pattern
6049 *
6050 * INPUT
6051 *
6052 *   EPoint -- The point in 3d space at which the pattern
6053 *   is evaluated.
6054 *
6055 * OUTPUT
6056 *
6057 * RETURNS
6058 *
6059 *   DBL value exactly 0.0, 1.0 or 2.0
6060 *
6061 * AUTHOR
6062 *
6063 *   Ernest MacDougal Campbell III
6064 *
6065 * DESCRIPTION
6066 *
6067 *   TriHex pattern -- Ernest MacDougal Campbell III (EMC3) 11/23/92
6068 *
6069 *   Creates a hexagon pattern in the XZ plane.
6070 *
6071 *   This algorithm is hard to explain.  First it scales the point to make
6072 *   a few of the later calculations easier, then maps some points to be
6073 *   closer to the Origin.  A small area in the first quadrant is subdivided
6074 *   into a 6 x 6 grid.  The position of the point mapped into that grid
6075 *   determines its color.  For some points, just the grid location is enough,
6076 *   but for others, we have to calculate which half of the block it's in
6077 *   (this is where the atan2() function comes in handy).
6078 *
6079 * CHANGES
6080 *
6081 *   Nov 1992 : Creation.
6082 *   Oct 1994 : adapted from pigment by [CY]
6083 *
6084 ******************************************************************************/
6085 
6086 const DBL xfactor = 0.5;         /* each triangle is split in half for the grid */
6087 const DBL zfactor = 0.866025404; /* sqrt(3)/2 -- Height of an equilateral triangle */
6088 
hexagon_pattern(const VECTOR EPoint)6089 static DBL hexagon_pattern (const VECTOR EPoint)
6090 {
6091 	int xm, zm;
6092 	int brkindx;
6093 	DBL xs, zs, xl, zl, value = 0.0;
6094 	DBL x=EPoint[X];
6095 	DBL z=EPoint[Z];
6096 
6097 
6098 	/* Keep all numbers positive.  Also, if z is negative, map it in such a
6099 	 * way as to avoid mirroring across the x-axis.  The value 5.196152424
6100 	 * is (sqrt(3)/2) * 6 (because the grid is 6 blocks high)
6101 	 */
6102 
6103 	x = fabs(x);
6104 
6105 	/* Avoid mirroring across x-axis. */
6106 
6107 	z = z < 0.0 ? 5.196152424 - fabs(z) : z;
6108 
6109 	/* Scale point to make calcs easier. */
6110 
6111 	xs = x/xfactor;
6112 	zs = z/zfactor;
6113 
6114 	/* Map points into the 6 x 6 grid where the basic formula works. */
6115 
6116 	xs -= floor(xs/6.0) * 6.0;
6117 	zs -= floor(zs/6.0) * 6.0;
6118 
6119 	/* Get a block in the 6 x 6 grid. */
6120 
6121 	xm = (int) FLOOR(xs) % 6;
6122 	zm = (int) FLOOR(zs) % 6;
6123 
6124 	switch (xm)
6125 	{
6126 		/* These are easy cases: Color depends only on xm and zm. */
6127 
6128 		case 0:
6129 		case 5:
6130 
6131 			switch (zm)
6132 			{
6133 				case 0:
6134 				case 5: value = 0; break;
6135 
6136 				case 1:
6137 				case 2: value = 1; break;
6138 
6139 				case 3:
6140 				case 4: value = 2; break;
6141 			}
6142 
6143 			break;
6144 
6145 		case 2:
6146 		case 3:
6147 
6148 			switch (zm)
6149 			{
6150 				case 0:
6151 				case 1: value = 2; break;
6152 
6153 				case 2:
6154 				case 3: value = 0; break;
6155 
6156 				case 4:
6157 				case 5: value = 1; break;
6158 			}
6159 
6160 			break;
6161 
6162 		/* These cases are harder.  These blocks are divided diagonally
6163 		 * by the angled edges of the hexagons.  Some slope positive, and
6164 		 * others negative.  We flip the x value of the negatively sloped
6165 		 * pieces.  Then we check to see if the point in question falls
6166 		 * in the upper or lower half of the block.  That info, plus the
6167 		 * z status of the block determines the color.
6168 		 */
6169 
6170 		case 1:
6171 		case 4:
6172 
6173 			/* Map the point into the block at the origin. */
6174 
6175 			xl = xs-xm;
6176 			zl = zs-zm;
6177 
6178 			/* These blocks have negative slopes so we flip it horizontally. */
6179 
6180 			if (((xm + zm) % 2) == 1)
6181 			{
6182 				xl = 1.0 - xl;
6183 			}
6184 
6185 			/* Avoid a divide-by-zero error. */
6186 
6187 			if (xl == 0.0)
6188 			{
6189 				xl = 0.0001; // TODO FIXME - magic number! Should be SOME_EPSILON I guess, or use nextafter()
6190 			}
6191 
6192 			/* Is the angle less-than or greater-than 45 degrees? */
6193 
6194 			brkindx = (zl / xl) < 1.0;
6195 
6196 			/* was...
6197 			 * brkindx = (atan2(zl,xl) < (45 * M_PI_180));
6198 			 * ...but because of the mapping, it's easier and cheaper,
6199 			 * CPU-wise, to just use a good ol' slope.
6200 			 */
6201 
6202 			switch (brkindx)
6203 			{
6204 				case true:
6205 
6206 					switch (zm)
6207 					{
6208 						case 0:
6209 						case 3: value = 0; break;
6210 
6211 						case 2:
6212 						case 5: value = 1; break;
6213 
6214 						case 1:
6215 						case 4: value = 2; break;
6216 					}
6217 
6218 					break;
6219 
6220 				case false:
6221 
6222 					switch (zm)
6223 					{
6224 						case 0:
6225 						case 3: value = 2; break;
6226 
6227 						case 2:
6228 						case 5: value = 0; break;
6229 
6230 						case 1:
6231 						case 4: value = 1; break;
6232 					}
6233 
6234 					break;
6235 			}
6236 	}
6237 
6238 	value = fmod(value, 3.0);
6239 
6240 	return(value);
6241 }
6242 
6243 
6244 /*****************************************************************************
6245 *
6246 * FUNCTION
6247 *
6248 *   cubic_pattern
6249 *
6250 * INPUT
6251 *
6252 *   EPoint -- The point in 3d space at which the pattern
6253 *   is evaluated.
6254 *
6255 * OUTPUT
6256 *
6257 * RETURNS
6258 *
6259 *   DBL value exactly 0.0, 1.0, 2.0, 3.0, 4.0 or 5.0
6260 *
6261 * AUTHOR
6262 *
6263 *   Nieminen Juha
6264 *
6265 * DESCRIPTION
6266 *
6267 *   Creates a cubic pattern. The six texture elements are mapped to the six
6268 *   pyramids centered on the six axes.
6269 *
6270 * CHANGES
6271 *
6272 *   Nov 2007 : Creation.
6273 *
6274 ******************************************************************************/
6275 
cubic_pattern(const VECTOR EPoint)6276 static DBL cubic_pattern (const VECTOR EPoint)
6277 {
6278 	const DBL x = EPoint[X], y = EPoint[Y], z = EPoint[Z];
6279 	const DBL ax = fabs(x), ay = fabs(y), az = fabs(z);
6280 
6281 	if(x >= 0 && x >= ay && x >= az) return 0.0;
6282 	if(y >= 0 && y >= ax && y >= az) return 1.0;
6283 	if(z >= 0 && z >= ax && z >= ay) return 2.0;
6284 	if(x < 0 && x <= -ay && x <= -az) return 3.0;
6285 	if(y < 0 && y <= -ax && y <= -az) return 4.0;
6286 	return 5.0;
6287 }
6288 
6289 /*****************************************************************************
6290 *
6291 * FUNCTION
6292 *
6293 *   square_pattern
6294 *
6295 * INPUT
6296 *
6297 *   EPoint -- The point in 3d space at which the pattern
6298 *   is evaluated.
6299 *
6300 * OUTPUT
6301 *
6302 * RETURNS
6303 *
6304 *   DBL value exactly 0.0, 1.0, 2.0 or 3.0
6305 *
6306 * AUTHOR
6307 *
6308 *   J. Grimbert
6309 *
6310 * DESCRIPTION
6311 *   Paving the XZ plan with 4 'colours', in square
6312 *
6313 * CHANGES
6314 *
6315 ******************************************************************************/
6316 
square_pattern(const VECTOR EPoint)6317 static DBL square_pattern (const VECTOR EPoint)
6318 {
6319 	int valueX,valueZ;
6320 
6321 	valueX = (int)(floor(EPoint[X]));
6322 	valueZ = (int)(floor(EPoint[Z]));
6323 
6324 	if (valueX & 1)
6325 	{
6326 		if (valueZ & 1)
6327 		{
6328 			return (2.0);
6329 		}
6330 		else
6331 		{
6332 			return (3.0);
6333 		}
6334 	}
6335 	else
6336 	{
6337 		if (valueZ & 1)
6338 		{
6339 			return (1.0);
6340 		}
6341 		else
6342 		{
6343 			return (0.0);
6344 		}
6345 	}
6346 }
6347 
6348 /*****************************************************************************
6349 *
6350 * FUNCTION
6351 *
6352 *   triangular_pattern
6353 *
6354 * INPUT
6355 *
6356 *   EPoint -- The point in 3d space at which the pattern
6357 *   is evaluated.
6358 *
6359 * OUTPUT
6360 *
6361 * RETURNS
6362 *
6363 *   DBL value exactly 0.0, 1.0, 2.0, 3.0, 4.0 or 5.0
6364 *
6365 * AUTHOR
6366 *
6367 *   J. Grimbert
6368 *
6369 * DESCRIPTION
6370 *   Paving the XZ plan with 6 'colours', in triangle around the origin
6371 *
6372 * CHANGES
6373 *
6374 ******************************************************************************/
6375 
triangular_pattern(const VECTOR EPoint)6376 static DBL triangular_pattern (const VECTOR EPoint)
6377 {
6378 	DBL answer;
6379 	DBL x,z;
6380 	DBL xs,zs;
6381 	int a,b;
6382 	DBL k,slop1,slop2;
6383 	int mask;
6384 
6385 	x=EPoint[X];
6386 	z=EPoint[Z];
6387   /* Fold the space to a basic rectangle */
6388 	xs = x-3.0*floor(x/3.0);
6389 	zs = z-SQRT3*floor(z/SQRT3);
6390 
6391 	/* xs,zs is in { [0.0, 3.0 [, [0.0, SQRT3 [ }
6392 	 ** but there is some symmetry to simplify the testing
6393 	 */
6394 
6395 	a = (int)floor(xs);
6396 	xs -= a;
6397 	b = (zs <SQRT3_2 ? 0: 1);
6398 	if (b)
6399 	{
6400 		zs = SQRT3 - zs; /* mirror */
6401 	}
6402 
6403 	k = 1.0 - xs;
6404 	if ((xs != 0.0)&&( k != 0.0 )) /* second condition should never occurs */
6405 	{
6406 		slop1 = zs/xs;
6407 		slop2 = zs/k; /* just in case */
6408 		switch( (slop1<SQRT3?1:0)+(slop2<SQRT3?2:0))
6409 		{
6410 			case 3:
6411 				answer = 0.0;
6412 				break;
6413 			case 2:
6414 				answer = 1.0;
6415 				break;
6416 			case 1:
6417 				answer = 3.0;
6418 				break;
6419 		}
6420 	}
6421 	else
6422 	{
6423 		answer = 1.0;
6424 	}
6425 	mask = (int) answer;
6426 	answer = (mask & 1) ? fmod(answer+2.0*a,6.0): fmod(6.0+answer-2.0*a,6.0);
6427 	if (b)
6428 	{
6429 		answer = 5.0 - answer;
6430 	}
6431 
6432 	return answer;
6433 }
6434 
6435 
6436 
6437 
6438 /*****************************************************************************
6439 *
6440 * FUNCTION
6441 *
6442 *   julia_pattern
6443 *
6444 * INPUT
6445 *
6446 *   EPoint -- The point in 3d space at which the pattern
6447 *   is evaluated.
6448 *
6449 * OUTPUT
6450 *
6451 * RETURNS
6452 *
6453 *   DBL value in the range 0.0 to 1.0
6454 *
6455 * AUTHOR
6456 *
6457 *   Nieminen Juha
6458 *
6459 * DESCRIPTION
6460 *
6461 *   -
6462 *
6463 * CHANGES
6464 *
6465 *   -
6466 *
6467 ******************************************************************************/
6468 
julia_pattern(const VECTOR EPoint,const TPATTERN * TPat)6469 static DBL julia_pattern (const VECTOR EPoint, const TPATTERN *TPat)
6470 {
6471 	int it_max, col;
6472 	DBL a, b, cf, a2, b2, dist2, mindist2,
6473 	    cr = TPat->Vals.Fractal.Coord[U], ci = TPat->Vals.Fractal.Coord[V];
6474 
6475 	a = EPoint[X]; a2 = Sqr(a);
6476 	b = EPoint[Y]; b2 = Sqr(b);
6477 	mindist2 = a2+b2;
6478 
6479 	it_max = TPat->Vals.Fractal.Iterations;
6480 
6481 	for (col = 0; col < it_max; col++)
6482 	{
6483 		b  = 2.0 * a * b + ci;
6484 		a  = a2 - b2 + cr;
6485 
6486 		a2 = Sqr(a);
6487 		b2 = Sqr(b);
6488 		dist2 = a2+b2;
6489 
6490 		if(dist2 < mindist2) mindist2 = dist2;
6491 		if(dist2 > 4.0)
6492 		{
6493 			cf = fractal_exterior_color(TPat, col, a, b);
6494 			break;
6495 		}
6496 	}
6497 
6498 	if(col == it_max)
6499 		cf = fractal_interior_color(TPat, col, a, b, mindist2);
6500 
6501 	return(cf);
6502 }
6503 
6504 
6505 /*****************************************************************************
6506 *
6507 * FUNCTION
6508 *
6509 *   julia3_pattern
6510 *
6511 * INPUT
6512 *
6513 *   EPoint -- The point in 3d space at which the pattern
6514 *   is evaluated.
6515 *
6516 * OUTPUT
6517 *
6518 * RETURNS
6519 *
6520 *   DBL value in the range 0.0 to 1.0
6521 *
6522 * AUTHOR
6523 *
6524 *   Nieminen Juha
6525 *
6526 * DESCRIPTION
6527 *
6528 *   -
6529 *
6530 * CHANGES
6531 *
6532 *   -
6533 *
6534 ******************************************************************************/
6535 
julia3_pattern(const VECTOR EPoint,const TPATTERN * TPat)6536 static DBL julia3_pattern (const VECTOR EPoint, const TPATTERN *TPat)
6537 {
6538 	int it_max, col;
6539 	DBL a, b, cf, a2, b2, dist2, mindist2,
6540 	    cr = TPat->Vals.Fractal.Coord[U], ci = TPat->Vals.Fractal.Coord[V];
6541 
6542 	a = EPoint[X]; a2 = Sqr(a);
6543 	b = EPoint[Y]; b2 = Sqr(b);
6544 	mindist2 = a2+b2;
6545 
6546 	it_max = TPat->Vals.Fractal.Iterations;
6547 
6548 	for (col = 0; col < it_max; col++)
6549 	{
6550 		b = 3.0*a2*b - b2*b + ci;
6551 		a = a2*a - 3.0*a*b2 + cr;
6552 
6553 		a2 = Sqr(a);
6554 		b2 = Sqr(b);
6555 		dist2 = a2+b2;
6556 
6557 		if(dist2 < mindist2) mindist2 = dist2;
6558 		if(dist2 > 4.0)
6559 		{
6560 			cf = fractal_exterior_color(TPat, col, a, b);
6561 			break;
6562 		}
6563 	}
6564 
6565 	if(col == it_max)
6566 		cf = fractal_interior_color(TPat, col, a, b, mindist2);
6567 
6568 	return(cf);
6569 }
6570 
6571 
6572 /*****************************************************************************
6573 *
6574 * FUNCTION
6575 *
6576 *   julia4_pattern
6577 *
6578 * INPUT
6579 *
6580 *   EPoint -- The point in 3d space at which the pattern
6581 *   is evaluated.
6582 *
6583 * OUTPUT
6584 *
6585 * RETURNS
6586 *
6587 *   DBL value in the range 0.0 to 1.0
6588 *
6589 * AUTHOR
6590 *
6591 *   Nieminen Juha
6592 *
6593 * DESCRIPTION
6594 *
6595 *   -
6596 *
6597 * CHANGES
6598 *
6599 *   -
6600 *
6601 ******************************************************************************/
6602 
julia4_pattern(const VECTOR EPoint,const TPATTERN * TPat)6603 static DBL julia4_pattern (const VECTOR EPoint, const TPATTERN *TPat)
6604 {
6605 	int it_max, col;
6606 	DBL a, b, cf, a2, b2, dist2, mindist2,
6607 	    cr = TPat->Vals.Fractal.Coord[U], ci = TPat->Vals.Fractal.Coord[V];
6608 
6609 	a = EPoint[X]; a2 = Sqr(a);
6610 	b = EPoint[Y]; b2 = Sqr(b);
6611 	mindist2 = a2+b2;
6612 
6613 	it_max = TPat->Vals.Fractal.Iterations;
6614 
6615 	for (col = 0; col < it_max; col++)
6616 	{
6617 		b = 4.0 * (a2*a*b - a*b2*b) + ci;
6618 		a = a2*a2 - 6.0*a2*b2 + b2*b2 + cr;
6619 
6620 		a2 = Sqr(a);
6621 		b2 = Sqr(b);
6622 		dist2 = a2+b2;
6623 
6624 		if(dist2 < mindist2) mindist2 = dist2;
6625 		if(dist2 > 4.0)
6626 		{
6627 			cf = fractal_exterior_color(TPat, col, a, b);
6628 			break;
6629 		}
6630 	}
6631 
6632 	if(col == it_max)
6633 		cf = fractal_interior_color(TPat, col, a, b, mindist2);
6634 
6635 	return(cf);
6636 }
6637 
6638 
6639 /*****************************************************************************
6640 *
6641 * FUNCTION
6642 *
6643 *   juliax_pattern
6644 *
6645 * INPUT
6646 *
6647 *   EPoint -- The point in 3d space at which the pattern
6648 *   is evaluated.
6649 *
6650 * OUTPUT
6651 *
6652 * RETURNS
6653 *
6654 *   DBL value in the range 0.0 to 1.0
6655 *
6656 * AUTHOR
6657 *
6658 *   Nieminen Juha
6659 *
6660 * DESCRIPTION
6661 *
6662 *   -
6663 *
6664 * CHANGES
6665 *
6666 *   -
6667 *
6668 ******************************************************************************/
6669 
juliax_pattern(const VECTOR EPoint,const TPATTERN * TPat)6670 static DBL juliax_pattern (const VECTOR EPoint, const TPATTERN *TPat)
6671 {
6672 	int it_max, col, exponent;
6673 	DBL a, b, cf=0, x, y, dist2, mindist2,
6674 	    cr = TPat->Vals.Fractal.Coord[U], ci = TPat->Vals.Fractal.Coord[V];
6675 	int* binomial_coeff;
6676 
6677 	a = x = EPoint[X];
6678 	b = y = EPoint[Y];
6679 	mindist2 = a*a+b*b;
6680 
6681 	it_max = TPat->Vals.Fractal.Iterations;
6682 	exponent = TPat->Vals.Fractal.Exponent;
6683 
6684 	binomial_coeff = &BinomialCoefficients[(exponent+1)*exponent/2];
6685 
6686 	for (col = 0; col < it_max; col++)
6687 	{
6688 		// Calculate (a+bi)^exponent
6689 		DBL new_a = pow(a, exponent);
6690 		for(int k=2; k<=exponent; k+=2)
6691 		{
6692 			new_a += binomial_coeff[k]*pow(a, exponent-k)*pow(b, k);
6693 		}
6694 		DBL new_b = 0;
6695 		for(int l=1; l<=exponent; l+=2)
6696 		{
6697 			new_b += binomial_coeff[l]*pow(a, exponent-l)*pow(b, l);
6698 		}
6699 
6700 		a = new_a + cr;
6701 		b = new_b + ci;
6702 
6703 		dist2 = a*a+b*b;
6704 
6705 		if(dist2 < mindist2) mindist2 = dist2;
6706 		if(dist2 > 4.0)
6707 		{
6708 			cf = fractal_exterior_color(TPat, col, a, b);
6709 			break;
6710 		}
6711 	}
6712 
6713 	if(col == it_max)
6714 		cf = fractal_interior_color(TPat, col, a, b, mindist2);
6715 
6716 	return(cf);
6717 }
6718 
6719 
6720 /*****************************************************************************
6721 *
6722 * FUNCTION
6723 *
6724 *   leopard_pattern
6725 *
6726 * INPUT
6727 *
6728 *   EPoint -- The point in 3d space at which the pattern
6729 *   is evaluated.
6730 *
6731 * OUTPUT
6732 *
6733 * RETURNS
6734 *
6735 *   DBL value in the range 0.0 to 1.0
6736 *
6737 * AUTHOR
6738 *
6739 *   Scott Taylor
6740 *
6741 * DESCRIPTION
6742 *
6743 * CHANGES
6744 *
6745 *   Jul 1991 : Creation.
6746 *   Oct 1994 : adapted from pigment by [CY]
6747 *
6748 ******************************************************************************/
6749 
leopard_pattern(const VECTOR EPoint)6750 static DBL leopard_pattern (const VECTOR EPoint)
6751 {
6752 	DBL value, temp1, temp2, temp3;
6753 
6754 	/* This form didn't work with Zortech 386 compiler */
6755 	/* value = Sqr((sin(x)+sin(y)+sin(z))/3); */
6756 	/* So we break it down. */
6757 
6758 	temp1 = sin(EPoint[X]);
6759 	temp2 = sin(EPoint[Y]);
6760 	temp3 = sin(EPoint[Z]);
6761 
6762 	value = Sqr((temp1 + temp2 + temp3) / 3.0);
6763 
6764 	return(value);
6765 }
6766 
6767 
6768 /*****************************************************************************
6769 *
6770 * FUNCTION
6771 *
6772 *   magnet1m_pattern
6773 *
6774 * INPUT
6775 *
6776 *   EPoint -- The point in 3d space at which the pattern
6777 *   is evaluated.
6778 *
6779 * OUTPUT
6780 *
6781 * RETURNS
6782 *
6783 *   DBL value in the range 0.0 to 1.0
6784 *
6785 * AUTHOR
6786 *
6787 *   Nieminen Juha
6788 *
6789 * DESCRIPTION
6790 *
6791 *   -
6792 *
6793 * CHANGES
6794 *
6795 *   -
6796 *
6797 ******************************************************************************/
6798 
magnet1m_pattern(const VECTOR EPoint,const TPATTERN * TPat)6799 static DBL magnet1m_pattern (const VECTOR EPoint, const TPATTERN *TPat)
6800 {
6801 	int it_max, col;
6802 	DBL a, b, cf, a2, b2, x, y, tmp, tmp1r, tmp1i, tmp2r, tmp2i, dist2, mindist2;
6803 
6804 	x = EPoint[X];
6805 	y = EPoint[Y];
6806 	a = a2 = 0;
6807 	b = b2 = 0;
6808 	mindist2 = 10000;
6809 
6810 	it_max = TPat->Vals.Fractal.Iterations;
6811 
6812 	for (col = 0; col < it_max; col++)
6813 	{
6814 		tmp1r = a2-b2 + x-1;
6815 		tmp1i = 2*a*b + y;
6816 		tmp2r = 2*a + x-2;
6817 		tmp2i = 2*b + y;
6818 		tmp = tmp2r*tmp2r + tmp2i*tmp2i;
6819 		a = (tmp1r*tmp2r + tmp1i*tmp2i) / tmp;
6820 		b = (tmp1i*tmp2r - tmp1r*tmp2i) / tmp;
6821 		b2 = b*b;
6822 		b = 2*a*b;
6823 		a = a*a-b2;
6824 
6825 		a2 = Sqr(a);
6826 		b2 = Sqr(b);
6827 		dist2 = a2+b2;
6828 
6829 		if(dist2 < mindist2) mindist2 = dist2;
6830 		tmp1r = a-1;
6831 		if(dist2 > 10000.0 || tmp1r*tmp1r+b2 < 1/10000.0)
6832 		{
6833 			cf = fractal_exterior_color(TPat, col, a, b);
6834 			break;
6835 		}
6836 	}
6837 
6838 	if(col == it_max)
6839 		cf = fractal_interior_color(TPat, col, a, b, mindist2);
6840 
6841 	return(cf);
6842 }
6843 
6844 
6845 /*****************************************************************************
6846 *
6847 * FUNCTION
6848 *
6849 *   magnet1j_pattern
6850 *
6851 * INPUT
6852 *
6853 *   EPoint -- The point in 3d space at which the pattern
6854 *   is evaluated.
6855 *
6856 * OUTPUT
6857 *
6858 * RETURNS
6859 *
6860 *   DBL value in the range 0.0 to 1.0
6861 *
6862 * AUTHOR
6863 *
6864 *   Nieminen Juha
6865 *
6866 * DESCRIPTION
6867 *
6868 *   -
6869 *
6870 * CHANGES
6871 *
6872 *   -
6873 *
6874 ******************************************************************************/
6875 
magnet1j_pattern(const VECTOR EPoint,const TPATTERN * TPat)6876 static DBL magnet1j_pattern (const VECTOR EPoint, const TPATTERN *TPat)
6877 {
6878 	int it_max, col;
6879 	DBL a, b, cf, a2, b2, tmp, tmp1r, tmp1i, tmp2r, tmp2i, dist2, mindist2,
6880 	    cr = TPat->Vals.Fractal.Coord[U], ci = TPat->Vals.Fractal.Coord[V];
6881 
6882 	a = EPoint[X]; a2 = Sqr(a);
6883 	b = EPoint[Y]; b2 = Sqr(b);
6884 	mindist2 = a2+b2;
6885 
6886 	it_max = TPat->Vals.Fractal.Iterations;
6887 
6888 	for (col = 0; col < it_max; col++)
6889 	{
6890 		tmp1r = a2-b2 + cr-1;
6891 		tmp1i = 2*a*b + ci;
6892 		tmp2r = 2*a + cr-2;
6893 		tmp2i = 2*b + ci;
6894 		tmp = tmp2r*tmp2r + tmp2i*tmp2i;
6895 		a = (tmp1r*tmp2r + tmp1i*tmp2i) / tmp;
6896 		b = (tmp1i*tmp2r - tmp1r*tmp2i) / tmp;
6897 		b2 = b*b;
6898 		b = 2*a*b;
6899 		a = a*a-b2;
6900 
6901 		a2 = Sqr(a);
6902 		b2 = Sqr(b);
6903 		dist2 = a2+b2;
6904 
6905 		if(dist2 < mindist2) mindist2 = dist2;
6906 		tmp1r = a-1;
6907 		if(dist2 > 10000.0 || tmp1r*tmp1r+b2 < 1/10000.0)
6908 		{
6909 			cf = fractal_exterior_color(TPat, col, a, b);
6910 			break;
6911 		}
6912 	}
6913 
6914 	if(col == it_max)
6915 		cf = fractal_interior_color(TPat, col, a, b, mindist2);
6916 
6917 	return(cf);
6918 }
6919 
6920 
6921 /*****************************************************************************
6922 *
6923 * FUNCTION
6924 *
6925 *   magnet2m_pattern
6926 *
6927 * INPUT
6928 *
6929 *   EPoint -- The point in 3d space at which the pattern
6930 *   is evaluated.
6931 *
6932 * OUTPUT
6933 *
6934 * RETURNS
6935 *
6936 *   DBL value in the range 0.0 to 1.0
6937 *
6938 * AUTHOR
6939 *
6940 *   Nieminen Juha
6941 *
6942 * DESCRIPTION
6943 *
6944 *   -
6945 *
6946 * CHANGES
6947 *
6948 *   -
6949 *
6950 ******************************************************************************/
6951 
magnet2m_pattern(const VECTOR EPoint,const TPATTERN * TPat)6952 static DBL magnet2m_pattern (const VECTOR EPoint, const TPATTERN *TPat)
6953 {
6954 	int it_max, col;
6955 	DBL a, b, cf, a2, b2, x, y, tmp, tmp1r, tmp1i, tmp2r, tmp2i,
6956 	    c1r, c2r, c1c2r, c1c2i, dist2, mindist2;
6957 
6958 	x = EPoint[X];
6959 	y = EPoint[Y];
6960 	a = a2 = 0;
6961 	b = b2 = 0;
6962 	mindist2 = 10000;
6963 
6964 	c1r = x-1; c2r = x-2;
6965 	c1c2r = c1r*c2r-y*y;
6966 	c1c2i = (c1r+c2r)*y;
6967 
6968 	it_max = TPat->Vals.Fractal.Iterations;
6969 
6970 	for (col = 0; col < it_max; col++)
6971 	{
6972 		tmp1r = a2*a-3*a*b2 + 3*(a*c1r-b*y) + c1c2r;
6973 		tmp1i = 3*a2*b-b2*b + 3*(a*y+b*c1r) + c1c2i;
6974 		tmp2r = 3*(a2-b2) + 3*(a*c2r-b*y) + c1c2r + 1;
6975 		tmp2i = 6*a*b + 3*(a*y+b*c2r) + c1c2i;
6976 		tmp = tmp2r*tmp2r + tmp2i*tmp2i;
6977 		a = (tmp1r*tmp2r + tmp1i*tmp2i) / tmp;
6978 		b = (tmp1i*tmp2r - tmp1r*tmp2i) / tmp;
6979 		b2 = b*b;
6980 		b = 2*a*b;
6981 		a = a*a-b2;
6982 
6983 		a2 = Sqr(a);
6984 		b2 = Sqr(b);
6985 		dist2 = a2+b2;
6986 
6987 		if(dist2 < mindist2) mindist2 = dist2;
6988 		tmp1r = a-1;
6989 		if(dist2 > 10000.0 || tmp1r*tmp1r+b2 < 1/10000.0)
6990 		{
6991 			cf = fractal_exterior_color(TPat, col, a, b);
6992 			break;
6993 		}
6994 	}
6995 
6996 	if(col == it_max)
6997 		cf = fractal_interior_color(TPat, col, a, b, mindist2);
6998 
6999 	return(cf);
7000 }
7001 
7002 
7003 /*****************************************************************************
7004 *
7005 * FUNCTION
7006 *
7007 *   magnet2j_pattern
7008 *
7009 * INPUT
7010 *
7011 *   EPoint -- The point in 3d space at which the pattern
7012 *   is evaluated.
7013 *
7014 * OUTPUT
7015 *
7016 * RETURNS
7017 *
7018 *   DBL value in the range 0.0 to 1.0
7019 *
7020 * AUTHOR
7021 *
7022 *   Nieminen Juha
7023 *
7024 * DESCRIPTION
7025 *
7026 *   -
7027 *
7028 * CHANGES
7029 *
7030 *   -
7031 *
7032 ******************************************************************************/
7033 
magnet2j_pattern(const VECTOR EPoint,const TPATTERN * TPat)7034 static DBL magnet2j_pattern (const VECTOR EPoint, const TPATTERN *TPat)
7035 {
7036 	int it_max, col;
7037 	DBL a, b, cf, a2, b2, tmp, tmp1r, tmp1i, tmp2r, tmp2i, c1r,c2r,c1c2r,c1c2i,
7038 	    cr = TPat->Vals.Fractal.Coord[U], ci = TPat->Vals.Fractal.Coord[V],
7039 	    dist2, mindist2;
7040 
7041 	a = EPoint[X]; a2 = Sqr(a);
7042 	b = EPoint[Y]; b2 = Sqr(b);
7043 	mindist2 = a2+b2;
7044 
7045 	c1r = cr-1, c2r = cr-2;
7046 	c1c2r = c1r*c2r-ci*ci;
7047 	c1c2i = (c1r+c2r)*ci;
7048 
7049 	it_max = TPat->Vals.Fractal.Iterations;
7050 
7051 	for (col = 0; col < it_max; col++)
7052 	{
7053 		tmp1r = a2*a-3*a*b2 + 3*(a*c1r-b*ci) + c1c2r;
7054 		tmp1i = 3*a2*b-b2*b + 3*(a*ci+b*c1r) + c1c2i;
7055 		tmp2r = 3*(a2-b2) + 3*(a*c2r-b*ci) + c1c2r + 1;
7056 		tmp2i = 6*a*b + 3*(a*ci+b*c2r) + c1c2i;
7057 		tmp = tmp2r*tmp2r + tmp2i*tmp2i;
7058 		a = (tmp1r*tmp2r + tmp1i*tmp2i) / tmp;
7059 		b = (tmp1i*tmp2r - tmp1r*tmp2i) / tmp;
7060 		b2 = b*b;
7061 		b = 2*a*b;
7062 		a = a*a-b2;
7063 
7064 		a2 = Sqr(a);
7065 		b2 = Sqr(b);
7066 		dist2 = a2+b2;
7067 
7068 		if(dist2 < mindist2) mindist2 = dist2;
7069 		tmp1r = a-1;
7070 		if(dist2 > 10000.0 || tmp1r*tmp1r+b2 < 1/10000.0)
7071 		{
7072 			cf = fractal_exterior_color(TPat, col, a, b);
7073 			break;
7074 		}
7075 	}
7076 
7077 	if(col == it_max)
7078 		cf = fractal_interior_color(TPat, col, a, b, mindist2);
7079 
7080 	return(cf);
7081 }
7082 
7083 
7084 /*****************************************************************************
7085 *
7086 * FUNCTION
7087 *
7088 *   mandel_pattern
7089 *
7090 * INPUT
7091 *
7092 *   EPoint -- The point in 3d space at which the pattern
7093 *   is evaluated.
7094 *
7095 * OUTPUT
7096 *
7097 * RETURNS
7098 *
7099 *   DBL value in the range 0.0 to 1.0
7100 *
7101 * AUTHOR
7102 *
7103 *   submitted by user, name lost (sorry)
7104 *
7105 * DESCRIPTION
7106 *
7107 *   The mandel pattern computes the standard Mandelbrot fractal pattern and
7108 *   projects it onto the X-Y plane.  It uses the X and Y coordinates to compute
7109 *   the Mandelbrot set.
7110 *
7111 * CHANGES
7112 *
7113 *   Oct 1994 : adapted from pigment by [CY]
7114 *   May 2001 : updated with code from Warp [trf]
7115 *
7116 ******************************************************************************/
7117 
mandel_pattern(const VECTOR EPoint,const TPATTERN * TPat)7118 static DBL mandel_pattern (const VECTOR EPoint, const TPATTERN *TPat)
7119 {
7120 	int it_max, col;
7121 	DBL a, b, cf, a2, b2, x, y, dist2, mindist2;
7122 
7123 	a = x = EPoint[X]; a2 = Sqr(a);
7124 	b = y = EPoint[Y]; b2 = Sqr(b);
7125 	mindist2 = a2+b2;
7126 
7127 	it_max = TPat->Vals.Fractal.Iterations;
7128 
7129 	for (col = 0; col < it_max; col++)
7130 	{
7131 		b  = 2.0 * a * b + y;
7132 		a  = a2 - b2 + x;
7133 
7134 		a2 = Sqr(a);
7135 		b2 = Sqr(b);
7136 		dist2 = a2+b2;
7137 
7138 		if(dist2 < mindist2) mindist2 = dist2;
7139 		if(dist2 > 4.0)
7140 		{
7141 			cf = fractal_exterior_color(TPat, col, a, b);
7142 			break;
7143 		}
7144 	}
7145 
7146 	if(col == it_max)
7147 		cf = fractal_interior_color(TPat, col, a, b, mindist2);
7148 
7149 	return(cf);
7150 }
7151 
7152 
7153 /*****************************************************************************
7154 *
7155 * FUNCTION
7156 *
7157 *   mandel3_pattern
7158 *
7159 * INPUT
7160 *
7161 *   EPoint -- The point in 3d space at which the pattern
7162 *   is evaluated.
7163 *
7164 * OUTPUT
7165 *
7166 * RETURNS
7167 *
7168 *   DBL value in the range 0.0 to 1.0
7169 *
7170 * AUTHOR
7171 *
7172 *   Nieminen Juha
7173 *
7174 * DESCRIPTION
7175 *
7176 *   -
7177 *
7178 * CHANGES
7179 *
7180 *   -
7181 *
7182 ******************************************************************************/
7183 
mandel3_pattern(const VECTOR EPoint,const TPATTERN * TPat)7184 static DBL mandel3_pattern (const VECTOR EPoint, const TPATTERN *TPat)
7185 {
7186 	int it_max, col;
7187 	DBL a, b, cf, a2, b2, x, y, dist2, mindist2;
7188 
7189 	a = x = EPoint[X]; a2 = Sqr(a);
7190 	b = y = EPoint[Y]; b2 = Sqr(b);
7191 	mindist2 = a2+b2;
7192 
7193 	it_max = TPat->Vals.Fractal.Iterations;
7194 
7195 	for (col = 0; col < it_max; col++)
7196 	{
7197 		b = 3.0*a2*b - b2*b + y;
7198 		a = a2*a - 3.0*a*b2 + x;
7199 
7200 		a2 = Sqr(a);
7201 		b2 = Sqr(b);
7202 		dist2 = a2+b2;
7203 
7204 		if(dist2 < mindist2) mindist2 = dist2;
7205 		if(dist2 > 4.0)
7206 		{
7207 			cf = fractal_exterior_color(TPat, col, a, b);
7208 			break;
7209 		}
7210 	}
7211 
7212 	if(col == it_max)
7213 		cf = fractal_interior_color(TPat, col, a, b, mindist2);
7214 
7215 	return(cf);
7216 }
7217 
7218 
7219 /*****************************************************************************
7220 *
7221 * FUNCTION
7222 *
7223 *   mandel4_pattern
7224 *
7225 * INPUT
7226 *
7227 *   EPoint -- The point in 3d space at which the pattern
7228 *   is evaluated.
7229 *
7230 * OUTPUT
7231 *
7232 * RETURNS
7233 *
7234 *   DBL value in the range 0.0 to 1.0
7235 *
7236 * AUTHOR
7237 *
7238 *   Nieminen Juha
7239 *
7240 * DESCRIPTION
7241 *
7242 *   -
7243 *
7244 * CHANGES
7245 *
7246 *   -
7247 *
7248 ******************************************************************************/
7249 
mandel4_pattern(const VECTOR EPoint,const TPATTERN * TPat)7250 static DBL mandel4_pattern (const VECTOR EPoint, const TPATTERN *TPat)
7251 {
7252 	int it_max, col;
7253 	DBL a, b, cf, a2, b2, x, y, dist2, mindist2;
7254 
7255 	a = x = EPoint[X]; a2 = Sqr(a);
7256 	b = y = EPoint[Y]; b2 = Sqr(b);
7257 	mindist2 = a2+b2;
7258 
7259 	it_max = TPat->Vals.Fractal.Iterations;
7260 
7261 	for (col = 0; col < it_max; col++)
7262 	{
7263 		b = 4.0 * (a2*a*b - a*b2*b) + y;
7264 		a = a2*a2 - 6.0*a2*b2 + b2*b2 + x;
7265 
7266 		a2 = Sqr(a);
7267 		b2 = Sqr(b);
7268 		dist2 = a2+b2;
7269 
7270 		if(dist2 < mindist2) mindist2 = dist2;
7271 		if(dist2 > 4.0)
7272 		{
7273 			cf = fractal_exterior_color(TPat, col, a, b);
7274 			break;
7275 		}
7276 	}
7277 
7278 	if(col == it_max)
7279 		cf = fractal_interior_color(TPat, col, a, b, mindist2);
7280 
7281 	return(cf);
7282 }
7283 
7284 
7285 /*****************************************************************************
7286 *
7287 * FUNCTION
7288 *
7289 *   mandelx_pattern
7290 *
7291 * INPUT
7292 *
7293 *   EPoint -- The point in 3d space at which the pattern
7294 *   is evaluated.
7295 *
7296 * OUTPUT
7297 *
7298 * RETURNS
7299 *
7300 *   DBL value in the range 0.0 to 1.0
7301 *
7302 * AUTHOR
7303 *
7304 *   Nieminen Juha
7305 *
7306 * DESCRIPTION
7307 *
7308 *   -
7309 *
7310 * CHANGES
7311 *
7312 *   -
7313 *
7314 ******************************************************************************/
7315 
mandelx_pattern(const VECTOR EPoint,const TPATTERN * TPat)7316 static DBL mandelx_pattern (const VECTOR EPoint, const TPATTERN *TPat)
7317 {
7318 	int it_max, col, exponent;
7319 	DBL a, b, cf=0, x, y, dist2, mindist2;
7320 	int* binomial_coeff;
7321 
7322 	a = x = EPoint[X];
7323 	b = y = EPoint[Y];
7324 	mindist2 = a*a+b*b;
7325 
7326 	it_max = TPat->Vals.Fractal.Iterations;
7327 	exponent = TPat->Vals.Fractal.Exponent;
7328 
7329 	binomial_coeff = &BinomialCoefficients[(exponent+1)*exponent/2];
7330 
7331 	for (col = 0; col < it_max; col++)
7332 	{
7333 		// Calculate (a+bi)^exponent
7334 		DBL new_a = pow(a, exponent);
7335 		for(int k=2; k<=exponent; k+=2)
7336 		{
7337 			new_a += binomial_coeff[k]*pow(a, exponent-k)*pow(b, k);
7338 		}
7339 		DBL new_b = 0;
7340 		for(int l=1; l<=exponent; l+=2)
7341 		{
7342 			new_b += binomial_coeff[l]*pow(a, exponent-l)*pow(b, l);
7343 		}
7344 
7345 		a = new_a + x;
7346 		b = new_b + y;
7347 
7348 		dist2 = a*a+b*b;
7349 
7350 		if(dist2 < mindist2) mindist2 = dist2;
7351 		if(dist2 > 4.0)
7352 		{
7353 			cf = fractal_exterior_color(TPat, col, a, b);
7354 			break;
7355 		}
7356 	}
7357 
7358 	if(col == it_max)
7359 		cf = fractal_interior_color(TPat, col, a, b, mindist2);
7360 
7361 	return(cf);
7362 }
7363 
7364 
7365 /*****************************************************************************
7366 *
7367 * FUNCTION
7368 *
7369 *   marble_pattern
7370 *
7371 * INPUT
7372 *
7373 *   EPoint -- The point in 3d space at which the pattern
7374 *   is evaluated.
7375 *   TPat   -- Texture pattern struct
7376 *
7377 * OUTPUT
7378 *
7379 * RETURNS
7380 *
7381 *   DBL value in the range 0.0 to 1.0
7382 *
7383 * AUTHOR
7384 *
7385 *   POV-Ray Team
7386 *
7387 * DESCRIPTION
7388 *
7389 * CHANGES
7390 *
7391 *   Oct 1994 : adapted from pigment by [CY]
7392 *
7393 ******************************************************************************/
7394 
marble_pattern(const VECTOR EPoint,const TPATTERN * TPat,int noise_generator)7395 static DBL marble_pattern (const VECTOR EPoint, const TPATTERN *TPat, int noise_generator)
7396 {
7397 	DBL turb_val;
7398 	const TURB *Turb;
7399 
7400 	if ((Turb=Search_For_Turb(TPat->Warps)) != NULL)
7401 	{
7402 		turb_val = Turb->Turbulence[X] * Turbulence(EPoint,Turb,noise_generator);
7403 	}
7404 	else
7405 	{
7406 		turb_val = 0.0;
7407 	}
7408 
7409 	return(EPoint[X] + turb_val);
7410 }
7411 
7412 
7413 /*****************************************************************************
7414 *
7415 * FUNCTION
7416 *
7417 *   object_pattern
7418 *
7419 * INPUT
7420 *
7421 *   EPoint -- The point in 3d space at which the pattern
7422 *   is evaluated.
7423 *   TPat   -- Texture pattern struct
7424 *
7425 * OUTPUT
7426 *
7427 * RETURNS
7428 *
7429 *   DBL value in the range 0.0 to 1.0
7430 *
7431 * AUTHOR
7432 *
7433 * DESCRIPTION
7434 *
7435 * CHANGES
7436 *
7437 ******************************************************************************/
7438 
object_pattern(const VECTOR EPoint,const TPATTERN * TPat,TraceThreadData * Thread)7439 static DBL object_pattern (const VECTOR EPoint, const TPATTERN *TPat, TraceThreadData *Thread)
7440 {
7441 	if(TPat->Vals.Object != NULL)
7442 	{
7443 		if(Inside_Object(EPoint, TPat->Vals.Object, Thread))
7444 			return 1.0;
7445 		else
7446 			return 0.0;
7447 	}
7448 
7449 	return 0.0;
7450 }
7451 
7452 /*****************************************************************************
7453 *
7454 * FUNCTION
7455 *
7456 *   onion_pattern
7457 *
7458 * INPUT
7459 *
7460 *   EPoint -- The point in 3d space at which the pattern
7461 *   is evaluated.
7462 *
7463 * OUTPUT
7464 *
7465 * RETURNS
7466 *
7467 *   DBL value in the range 0.0 to 1.0
7468 *
7469 * AUTHOR
7470 *
7471 *   Scott Taylor
7472 *
7473 * DESCRIPTION
7474 *
7475 * CHANGES
7476 *
7477 *   Jul 1991 : Creation.
7478 *   Oct 1994 : adapted from pigment by [CY]
7479 *
7480 ******************************************************************************/
7481 
onion_pattern(const VECTOR EPoint)7482 static DBL onion_pattern (const VECTOR EPoint)
7483 {
7484 	/* The variable noise is not used as noise in this function */
7485 
7486 	DBL noise;
7487 
7488 /*
7489 	 This ramp goes 0-1,1-0,0-1,1-0...
7490 
7491 	 noise = (fmod(sqrt(Sqr(x)+Sqr(y)+Sqr(z)),2.0)-1.0);
7492 
7493 	 if (noise<0.0) {noise = 0.0-noise;}
7494 */
7495 
7496 	/* This ramp goes 0-1, 0-1, 0-1, 0-1 ... */
7497 
7498 	noise = (fmod(sqrt(Sqr(EPoint[X])+Sqr(EPoint[Y])+Sqr(EPoint[Z])), 1.0));
7499 
7500 	return(noise);
7501 }
7502 
7503 
7504 /*****************************************************************************
7505 *
7506 * FUNCTION
7507 *
7508 * INPUT
7509 *
7510 * OUTPUT
7511 *
7512 * RETURNS
7513 *
7514 * AUTHOR
7515 *
7516 * DESCRIPTION
7517 *
7518 * CHANGES
7519 *
7520 ******************************************************************************/
7521 
pigment_pattern(const VECTOR EPoint,const TPATTERN * TPat,const Intersection * isect,const Ray * ray,TraceThreadData * Thread)7522 static DBL pigment_pattern (const VECTOR EPoint, const TPATTERN *TPat, const Intersection *isect, const Ray *ray, TraceThreadData *Thread)
7523 {
7524 	DBL value;
7525 	Colour Col;
7526 	int colour_found=false;
7527 
7528 	if (TPat->Vals.Pigment)
7529 		// TODO ALPHA - we're discarding transparency information, so maybe we want to pre-multiply if there's alpha in there?
7530 		colour_found = Compute_Pigment(Col, TPat->Vals.Pigment, EPoint, isect, ray, Thread);
7531 
7532 	if(!colour_found)
7533 		value = 0.0;
7534 	else
7535 		value = Col.greyscale();
7536 
7537 	return value ;
7538 }
7539 
7540 
7541 /*****************************************************************************
7542 *
7543 * FUNCTION
7544 *
7545 *   planar_pattern
7546 *
7547 * INPUT
7548 *
7549 *   EPoint -- The point in 3d space at which the pattern
7550 *   is evaluated.
7551 *
7552 * OUTPUT
7553 *
7554 * RETURNS
7555 *
7556 *   DBL value in the range 0.0 to 1.0
7557 *
7558 * AUTHOR
7559 *
7560 *   -
7561 *
7562 * DESCRIPTION
7563 *
7564 *   -
7565 *
7566 * CHANGES
7567 *
7568 *   -
7569 *
7570 ******************************************************************************/
7571 
planar_pattern(const VECTOR EPoint)7572 static DBL planar_pattern (const VECTOR EPoint)
7573 {
7574 	DBL value = fabs(EPoint[Y]);
7575 
7576 	CLIP_DENSITY(value);
7577 
7578 	return value;
7579 }
7580 
7581 
7582 /*****************************************************************************
7583 *
7584 * FUNCTION
7585 *
7586 *   quilted_pattern
7587 *
7588 * INPUT
7589 *
7590 * OUTPUT
7591 *
7592 * RETURNS
7593 *
7594 * AUTHOR
7595 *
7596 *   Dan Farmer & Chris Young
7597 *
7598 * DESCRIPTION
7599 *
7600 * CHANGES
7601 *
7602 ******************************************************************************/
7603 
quilted_pattern(const VECTOR EPoint,const TPATTERN * TPat)7604 static DBL quilted_pattern (const VECTOR EPoint, const TPATTERN *TPat)
7605 {
7606 	VECTOR value;
7607 	DBL t;
7608 
7609 	value[X] = EPoint[X]-FLOOR(EPoint[X])-0.5;
7610 	value[Y] = EPoint[Y]-FLOOR(EPoint[Y])-0.5;
7611 	value[Z] = EPoint[Z]-FLOOR(EPoint[Z])-0.5;
7612 
7613 	t = sqrt(value[X]*value[X]+value[Y]*value[Y]+value[Z]*value[Z]);
7614 
7615 	t = quilt_cubic(t, TPat->Vals.Quilted.Control0, TPat->Vals.Quilted.Control1);
7616 
7617 	value[X] *= t;
7618 	value[Y] *= t;
7619 	value[Z] *= t;
7620 
7621 	return((fabs(value[X])+fabs(value[Y])+fabs(value[Z]))/3.0);
7622 }
7623 
7624 
7625 /*****************************************************************************
7626 *
7627 * FUNCTION
7628 *
7629 *   radial_pattern
7630 *
7631 * INPUT
7632 *
7633 *   EPoint -- The point in 3d space at which the pattern
7634 *   is evaluated.
7635 *
7636 * OUTPUT
7637 *
7638 * RETURNS
7639 *
7640 *   DBL value in the range 0.0 to 1.0
7641 *
7642 * AUTHOR
7643 *
7644 *   Chris Young -- new in vers 2.0
7645 *
7646 * DESCRIPTION
7647 *
7648 * CHANGES
7649 *
7650 *   Oct 1994 : adapted from pigment by [CY]
7651 *
7652 ******************************************************************************/
7653 
radial_pattern(const VECTOR EPoint)7654 static DBL radial_pattern (const VECTOR EPoint)
7655 {
7656 	DBL value;
7657 
7658 	if ((fabs(EPoint[X])<0.001) && (fabs(EPoint[Z])<0.001))
7659 	{
7660 		value = 0.25;
7661 	}
7662 	else
7663 	{
7664 		value = 0.25 + (atan2(EPoint[X],EPoint[Z]) + M_PI) / TWO_M_PI;
7665 	}
7666 
7667 	return(value);
7668 }
7669 
7670 
7671 /*****************************************************************************
7672 *
7673 * FUNCTION
7674 *
7675 *   ripples_pattern
7676 *
7677 * INPUT
7678 *
7679 *   EPoint -- The point in 3d space at which the pattern
7680 *   is evaluated.
7681 *   TPat   -- Texture pattern struct
7682 *
7683 * OUTPUT
7684 *
7685 * RETURNS
7686 *
7687 *   DBL value in the range 0.0 to 1.0
7688 *
7689 * AUTHOR
7690 *
7691 *   POV-Ray Team
7692 *
7693 * DESCRIPTION   : Note this pattern is only used for pigments and textures.
7694 *                 Normals have a specialized pattern for this.
7695 *
7696 * CHANGES
7697 *
7698 *   Nov 1994 : adapted from normal by [CY]
7699 *
7700 ******************************************************************************/
7701 
ripples_pattern(const VECTOR EPoint,const TPATTERN * TPat,const TraceThreadData * Thread)7702 static DBL ripples_pattern (const VECTOR EPoint, const TPATTERN *TPat, const TraceThreadData *Thread)
7703 {
7704 	unsigned int i;
7705 	DBL length, index;
7706 	DBL scalar =0.0;
7707 	VECTOR point;
7708 
7709 	for (i = 0 ; i < Thread->numberOfWaves ; i++)
7710 	{
7711 		VSub (point, EPoint, *Thread->waveSources[i]);
7712 		VLength (length, point);
7713 
7714 		if (length == 0.0)
7715 			length = 1.0;
7716 
7717 		index = length * TPat->Frequency + TPat->Phase;
7718 
7719 		scalar += cycloidal(index);
7720 	}
7721 
7722 	scalar = 0.5*(1.0+(scalar / (DBL)Thread->numberOfWaves));
7723 
7724 	return(scalar);
7725 }
7726 
7727 
7728 /*****************************************************************************
7729 *
7730 * FUNCTION
7731 *
7732 *   slope_pattern
7733 *
7734 * INPUT
7735 *
7736 *   EPoint -- The point in 3d space at which the pattern
7737 *             is evaluated.
7738 *   TPat   -- Texture pattern struct
7739 *   Intersection - intersection struct
7740 *
7741 * OUTPUT
7742 *
7743 * RETURNS
7744 *
7745 *   DBL value in the range 0.0 to 1.0, 0.0 if normal is NULL
7746 *
7747 * AUTHOR
7748 *
7749 *   -hdf-
7750 *
7751 * DESCRIPTION   :
7752 *
7753 *   calculates the surface slope from surface normal vector
7754 *
7755 * CHANGES
7756 *
7757 *   Apr 1998 : written by H.-D. Fink
7758 *   May 1998 : modified by M.C. Andrews - now combines slope and 'gradient'.
7759 *
7760 ******************************************************************************/
7761 
slope_pattern(const VECTOR EPoint,const TPATTERN * TPat,const Intersection * Isection)7762 static DBL slope_pattern (const VECTOR EPoint, const TPATTERN *TPat, const Intersection *Isection)
7763 {
7764 	DBL value, value1, value2;
7765 
7766 	if (Isection == NULL) return 0.0; /* just in case ... */
7767 
7768 	if (TPat->Vals.Slope.Point_At)
7769 	{
7770 		VECTOR vect;
7771 		VSub(vect,TPat->Vals.Slope.Slope_Vector,Isection->IPoint);
7772 		VNormalizeEq(vect);
7773 		VDot(value1, Isection->PNormal, vect);
7774 	}
7775 	else
7776 	{
7777 		if (TPat->Vals.Slope.Slope_Base > 0)
7778 			/* short case 1: slope vector in x, y or z direction */
7779 			value1 = Isection->PNormal[TPat->Vals.Slope.Slope_Base - 1];
7780 		else if (TPat->Vals.Slope.Slope_Base < 0)
7781 			/* short case 2: slope vector in negative x, y or z direction */
7782 			value1 = -Isection->PNormal[-TPat->Vals.Slope.Slope_Base - 1];
7783 		else
7784 			/* projection slope onto normal vector */
7785 			VDot(value1, Isection->PNormal, TPat->Vals.Slope.Slope_Vector);
7786 	}
7787 
7788 	/* Clamp to 1.0. */
7789 	/* should never be necessary since both vectors are normalized */
7790 	if      (value1 >  1.0) value1 =  1.0;
7791 	else if (value1 < -1.0) value1 = -1.0;
7792 
7793 	value1 = asin(value1) / M_PI * 2;
7794 	value1 = (value1 + 1.0) * 0.5;        /* normalize to [0..1] interval */
7795 
7796 	/* If set, use offset and scalings for slope and altitude. */
7797 	if (0.0 != TPat->Vals.Slope.Slope_Mod[V])
7798 	{
7799 		value1 = (value1 - TPat->Vals.Slope.Slope_Mod[U]) / TPat->Vals.Slope.Slope_Mod[V];
7800 	}
7801 
7802 	if (!TPat->Vals.Slope.Altit_Len)
7803 	{
7804 		/* Clamp to 1.0. */
7805 		if ( value1 == 1.0 )
7806 		{
7807 			value1= value1- EPSILON;
7808 		}
7809 		else
7810 		{
7811 			value1 = (value1 < 0.0) ? 1.0 + fmod(value1, 1.0) : fmod(value1, 1.0);
7812 		}
7813 		return value1; /* no altitude defined */
7814 	}
7815 
7816 	/* Calculate projection of Epoint along altitude vector */
7817 	if (TPat->Vals.Slope.Altit_Base > 0)
7818 		/* short case 1: altitude vector in x, y or z direction */
7819 		value2 = EPoint[TPat->Vals.Slope.Altit_Base - 1];
7820 	else if (TPat->Vals.Slope.Altit_Base < 0)
7821 		/* short case 2: altitude vector in negative x, y or z direction */
7822 		value2 = -EPoint[-TPat->Vals.Slope.Altit_Base - 1];
7823 	else
7824 		/* projection of Epoint along altitude vector */
7825 		VDot(value2, EPoint, TPat->Vals.Slope.Altit_Vector);
7826 
7827 	if (0.0 != TPat->Vals.Slope.Altit_Mod[V])
7828 	{
7829 		value2 = (value2 - TPat->Vals.Slope.Altit_Mod[U]) / TPat->Vals.Slope.Altit_Mod[V];
7830 	}
7831 
7832 	value = TPat->Vals.Slope.Slope_Len * value1 + TPat->Vals.Slope.Altit_Len * value2;
7833 
7834 	/* Clamp to 1.0. */
7835 	if ( value - 1.0 < EPSILON && value >= 1.0 )
7836 	{
7837 		/* 1.0 is a very common value to get *exactly*.  We don't want to wrap
7838 		   it to the bottom end of the map. */
7839 		value = value - EPSILON;
7840 	}
7841 	else
7842 	{
7843 		value = (value < 0.0) ? 1.0 + fmod(value, 1.0) : fmod(value, 1.0);
7844 	}
7845 	return value;
7846 
7847 }
7848 
7849 
7850 /*****************************************************************************
7851 *
7852 * FUNCTION
7853 *
7854 *   aoi_pattern
7855 *
7856 * INPUT
7857 *
7858 *   Intersection - intersection struct
7859 *   Ray          - Ray information
7860 *
7861 * OUTPUT
7862 *
7863 * RETURNS
7864 *
7865 *   DBL value in the range 0.0 to 1.0
7866 *
7867 * AUTHOR
7868 *
7869 *   J. Grimbert
7870 *
7871 * DESCRIPTION
7872 *
7873 *  Return a value related to angle of incidence
7874 *   (angle between the normal at the intersection and the ray)
7875 *
7876 * CHANGES
7877 *
7878 *   Mar 2010 : modified by [CLi]
7879 *
7880 ******************************************************************************/
7881 
aoi_pattern(const Intersection * Isection,const Ray * ray)7882 static DBL aoi_pattern (const Intersection *Isection, const Ray *ray)
7883 {
7884 	VECTOR    a, b;
7885 	DBL       cosAngle, angle;
7886 
7887 	if ((Isection == NULL) || (ray == NULL))
7888 		return 0.0;
7889 
7890 	VNormalize(a, Isection->PNormal);
7891 	VNormalize(b, ray->Direction);
7892 	VDot(cosAngle, a, b);
7893 
7894 	// clip to [-1.0; 1.0], just to be sure
7895 	// (should never be necessary since both vectors are normalized)
7896 	cosAngle = clip(cosAngle, -1.0, 1.0);
7897 	angle = acos(cosAngle) / M_PI;
7898 
7899 	return angle;
7900 }
7901 
7902 
7903 /*****************************************************************************
7904 *
7905 * FUNCTION
7906 *
7907 *   spiral1_pattern
7908 *
7909 * INPUT
7910 *
7911 *   EPoint -- The point in 3d space at which the pattern
7912 *   is evaluated.
7913 *   TPat   -- Texture pattern struct
7914 *
7915 * OUTPUT
7916 *
7917 * RETURNS
7918 *
7919 *   DBL value in the range 0.0 to 1.0
7920 *
7921 * AUTHOR
7922 *
7923 *   Dieter Bayer
7924 *
7925 * DESCRIPTION
7926 *   Spiral whirles around z-axis.
7927 *   The number of "arms" is defined in the TPat.
7928 *
7929 * CHANGES
7930 *
7931 *   Aug 1994 : Creation.
7932 *   Oct 1994 : adapted from pigment by [CY]
7933 *
7934 ******************************************************************************/
7935 
spiral1_pattern(const VECTOR EPoint,const TPATTERN * TPat,int noise_generator)7936 static DBL spiral1_pattern (const VECTOR EPoint, const TPATTERN *TPat, int noise_generator)
7937 {
7938 	DBL rad, phi, turb_val;
7939 	DBL x = EPoint[X];
7940 	DBL y = EPoint[Y];
7941 	DBL z = EPoint[Z];
7942 	const TURB *Turb;
7943 
7944 	if ((Turb=Search_For_Turb(TPat->Warps)) != NULL)
7945 	{
7946 		turb_val = Turb->Turbulence[X] * Turbulence(EPoint,Turb,noise_generator);
7947 	}
7948 	else
7949 	{
7950 		turb_val = 0.0;
7951 	}
7952 
7953 	/* Get distance from z-axis. */
7954 
7955 	rad = sqrt(x * x + y * y);
7956 
7957 	/* Get angle in x,y-plane (0...2 PI). */
7958 
7959 	if (rad == 0.0)
7960 	{
7961 		phi = 0.0;
7962 	}
7963 	else
7964 	{
7965 		if (x < 0.0)
7966 		{
7967 			phi = 3.0 * M_PI_2 - asin(y / rad);
7968 		}
7969 		else
7970 		{
7971 			phi = M_PI_2 + asin(y / rad);
7972 		}
7973 	}
7974 
7975 	return(z + rad + (DBL)TPat->Vals.Arms * phi / TWO_M_PI + turb_val);
7976 }
7977 
7978 
7979 /*****************************************************************************
7980 *
7981 * FUNCTION
7982 *
7983 *   spiral2_pattern
7984 *
7985 * INPUT
7986 *
7987 *   EPoint -- The point in 3d space at which the pattern
7988 *   is evaluated.
7989 *   TPat   -- Texture pattern struct
7990 *
7991 * OUTPUT
7992 *
7993 * RETURNS
7994 *
7995 *   DBL value in the range 0.0 to 1.0
7996 *
7997 * AUTHOR
7998 *
7999 *   Dieter Bayer
8000 *
8001 * DESCRIPTION
8002 *   Spiral whirles around z-axis.
8003 *   The number of "arms" is defined in the TPat.
8004 *
8005 * CHANGES
8006 *
8007 *   Aug 1994 : Creation.
8008 *   Oct 1994 : adapted from pigment by [CY]
8009 *
8010 ******************************************************************************/
8011 
spiral2_pattern(const VECTOR EPoint,const TPATTERN * TPat,int noise_generator)8012 static DBL spiral2_pattern (const VECTOR EPoint, const TPATTERN *TPat, int noise_generator)
8013 {
8014 	DBL rad, phi, turb_val;
8015 	DBL x = EPoint[X];
8016 	DBL y = EPoint[Y];
8017 	DBL z = EPoint[Z];
8018 	const TURB *Turb;
8019 
8020 	if ((Turb=Search_For_Turb(TPat->Warps)) != NULL)
8021 	{
8022 		turb_val = Turb->Turbulence[X] * Turbulence(EPoint,Turb,noise_generator);
8023 	}
8024 	else
8025 	{
8026 		turb_val = 0.0;
8027 	}
8028 
8029 	/* Get distance from z-axis. */
8030 
8031 	rad = sqrt(x * x + y * y);
8032 
8033 	/* Get angle in x,y-plane (0...2 PI) */
8034 
8035 	if (rad == 0.0)
8036 	{
8037 		phi = 0.0;
8038 	}
8039 	else
8040 	{
8041 		if (x < 0.0)
8042 		{
8043 			phi = 3.0 * M_PI_2 - asin(y / rad);
8044 		}
8045 		else
8046 		{
8047 			phi = M_PI_2 + asin(y / rad);
8048 		}
8049 	}
8050 
8051 	turb_val = Triangle_Wave(z + rad + (DBL)TPat->Vals.Arms * phi / TWO_M_PI +
8052 	                         turb_val);
8053 
8054 	return(Triangle_Wave(rad) + turb_val);
8055 }
8056 
8057 
8058 /*****************************************************************************
8059 *
8060 * FUNCTION
8061 *
8062 *   spherical_pattern
8063 *
8064 * INPUT
8065 *
8066 *   EPoint -- The point in 3d space at which the pattern
8067 *   is evaluated.
8068 *
8069 * OUTPUT
8070 *
8071 * RETURNS
8072 *
8073 *   DBL value in the range 0.0 to 1.0
8074 *
8075 * AUTHOR
8076 *
8077 *   -
8078 *
8079 * DESCRIPTION
8080 *
8081 *   -
8082 *
8083 * CHANGES
8084 *
8085 *   -
8086 *
8087 ******************************************************************************/
8088 
spherical_pattern(const VECTOR EPoint)8089 static DBL spherical_pattern (const VECTOR EPoint)
8090 {
8091 	DBL value;
8092 
8093 	VLength(value, EPoint);
8094 	CLIP_DENSITY(value);
8095 
8096 	return(value);
8097 }
8098 
8099 
8100 /*****************************************************************************
8101 *
8102 * FUNCTION
8103 *
8104 *   waves_pattern
8105 *
8106 * INPUT
8107 *
8108 *   EPoint -- The point in 3d space at which the pattern
8109 *   is evaluated.
8110 *   TPat   -- Texture pattern struct
8111 *
8112 * OUTPUT
8113 *
8114 * RETURNS
8115 *
8116 *   DBL value in the range 0.0 to 1.0
8117 *
8118 * AUTHOR
8119 *
8120 *   POV-Ray Team
8121 *
8122 * DESCRIPTION   : Note this pattern is only used for pigments and textures.
8123 *                 Normals have a specialized pattern for this.
8124 *
8125 * CHANGES
8126 *
8127 *   Nov 1994 : adapted from normal by [CY]
8128 *
8129 ******************************************************************************/
8130 
waves_pattern(const VECTOR EPoint,const TPATTERN * TPat,const TraceThreadData * Thread)8131 static DBL waves_pattern (const VECTOR EPoint, const TPATTERN *TPat, const TraceThreadData *Thread)
8132 {
8133 	unsigned int i;
8134 	DBL length, index;
8135 	DBL scalar = 0.0;
8136 	VECTOR point;
8137 
8138 	for (i = 0 ; i < Thread->numberOfWaves ; i++)
8139 	{
8140 		VSub (point, EPoint, *Thread->waveSources[i]);
8141 		VLength (length, point);
8142 
8143 		if (length == 0.0)
8144 		{
8145 			length = 1.0;
8146 		}
8147 
8148 		index = length * TPat->Frequency * Thread->waveFrequencies[i] + TPat->Phase;
8149 
8150 		scalar += cycloidal(index)/Thread->waveFrequencies[i];
8151 	}
8152 
8153 	scalar = 0.2*(2.5+(scalar / (DBL)Thread->numberOfWaves));
8154 
8155 	return(scalar);
8156 }
8157 
8158 
8159 /*****************************************************************************
8160 *
8161 * FUNCTION
8162 *
8163 *   wood_pattern
8164 *
8165 * INPUT
8166 *
8167 *   EPoint -- The point in 3d space at which the pattern
8168 *   is evaluated.
8169 *   TPat   -- Texture pattern struct
8170 *
8171 * OUTPUT
8172 *
8173 * RETURNS
8174 *
8175 *   DBL value in the range 0.0 to 1.0
8176 *
8177 * AUTHOR
8178 *
8179 *   POV-Ray Team
8180 *
8181 * DESCRIPTION
8182 *
8183 * CHANGES
8184 *
8185 *   Oct 1994 : adapted from pigment by [CY]
8186 *
8187 ******************************************************************************/
8188 
wood_pattern(const VECTOR EPoint,const TPATTERN * TPat)8189 static DBL wood_pattern (const VECTOR EPoint, const TPATTERN *TPat)
8190 {
8191 	DBL length;
8192 	VECTOR WoodTurbulence;
8193 	VECTOR point;
8194 	DBL x=EPoint[X];
8195 	DBL y=EPoint[Y];
8196 	const TURB *Turb;
8197 
8198 	if ((Turb=Search_For_Turb(TPat->Warps)) != NULL)
8199 	{
8200 		DTurbulence (WoodTurbulence, EPoint,Turb);
8201 		point[X] = cycloidal((x + WoodTurbulence[X]) * Turb->Turbulence[X]);
8202 		point[Y] = cycloidal((y + WoodTurbulence[Y]) * Turb->Turbulence[Y]);
8203 	}
8204 	else
8205 	{
8206 		point[X] = 0.0;
8207 		point[Y] = 0.0;
8208 	}
8209 	point[Z] = 0.0;
8210 
8211 	point[X] += x;
8212 	point[Y] += y;
8213 
8214 	/* point[Z] += z; Deleted per David Buck --  BP 7/91 */
8215 
8216 	VLength (length, point);
8217 
8218 	return(length);
8219 }
8220 
8221 
8222 /*****************************************************************************
8223 *
8224 * FUNCTION
8225 *
8226 *   wrinkles_pattern
8227 *
8228 * INPUT
8229 *
8230 *   EPoint -- The point in 3d space at which the pattern
8231 *   is evaluated.
8232 *
8233 * OUTPUT
8234 *
8235 * RETURNS
8236 *
8237 *   DBL value in the range 0.0 to 1.0
8238 *
8239 * AUTHOR
8240 *
8241 *   POV-Ray Team
8242 *
8243 * DESCRIPTION   : Note this pattern is only used for pigments and textures.
8244 *                 Normals have a specialized pattern for this.
8245 *
8246 * CHANGES
8247 *
8248 *   Nov 1994 : adapted from normal by [CY]
8249 *
8250 ******************************************************************************/
8251 
wrinkles_pattern(const VECTOR EPoint,int noise_generator)8252 static DBL wrinkles_pattern (const VECTOR EPoint, int noise_generator)
8253 {
8254 	int i;
8255 	DBL lambda = 2.0;
8256 	DBL omega = 0.5;
8257 	DBL value;
8258 	VECTOR temp;
8259 	DBL noise;
8260 
8261 	if(noise_generator>1)
8262 	{
8263 		noise = Noise(EPoint, noise_generator)*2.0-0.5;
8264 		value = min(max(noise,0.0),1.0);
8265 	}
8266 	else
8267 	{
8268 		value = Noise(EPoint, noise_generator);
8269 	}
8270 
8271 	for (i = 1; i < 10; i++)
8272 	{
8273 		VScale(temp,EPoint,lambda);
8274 
8275 		if(noise_generator>1)
8276 		{
8277 			noise = Noise(temp, noise_generator)*2.0-0.5;
8278 			value += omega * min(max(noise,0.0),1.0);
8279 		}
8280 		else
8281 		{
8282 			value += omega * Noise(temp, noise_generator);
8283 		}
8284 
8285 		lambda *= 2.0;
8286 
8287 		omega *= 0.5;
8288 	}
8289 
8290 	return(value/2.0);
8291 }
8292 
8293 
8294 /*****************************************************************************
8295 *
8296 * FUNCTION
8297 *
8298 *   IntPickInCube(tvx,tvy,tvz, p1)
8299 *    a version of PickInCube that takes integers for input
8300 *
8301 * INPUT
8302 *
8303 *   ?
8304 *
8305 * OUTPUT
8306 *
8307 * RETURNS
8308 *
8309 *   long integer hash function used, to speed up cacheing.
8310 *
8311 * AUTHOR
8312 *
8313 *   original PickInCube by Jim McElhiney
8314 *   this integer one modified by Nathan Kopp
8315 *
8316 * DESCRIPTION
8317 *
8318 *   A subroutine to go with crackle.
8319 *
8320 *   Pick a random point in the same unit-sized cube as tv, in a
8321 *   predictable way, so that when called again with another point in
8322 *   the same unit cube, p1 is picked to be the same.
8323 *
8324 * CHANGES
8325 *
8326 ******************************************************************************/
8327 
IntPickInCube(int tvx,int tvy,int tvz,VECTOR p1)8328 static int IntPickInCube(int tvx, int tvy, int tvz, VECTOR  p1)
8329 {
8330 	size_t seed;
8331 
8332 	seed = size_t(Hash3d(tvx&0xFFF,tvy&0xFFF,tvz&0xFFF));
8333 
8334 	p1[X] = tvx + PatternRands(seed);
8335 	p1[Y] = tvy + PatternRands(seed + 1);
8336 	p1[Z] = tvz + PatternRands(seed + 2);
8337 
8338 	return (int)seed;
8339 }
8340 
8341 
8342 /*****************************************************************************
8343 *
8344 * FUNCTION
8345 *
8346 *   PickInCube(tv, p1)
8347 *
8348 * INPUT
8349 *
8350 *   ?
8351 *
8352 * OUTPUT
8353 *
8354 * RETURNS
8355 *
8356 *   long integer hash function used, to speed up cacheing.
8357 *
8358 * AUTHOR
8359 *
8360 *   Jim McElhiney
8361 *
8362 * DESCRIPTION
8363 *
8364 *   A subroutine to go with crackle.
8365 *
8366 *   Pick a random point in the same unit-sized cube as tv, in a
8367 *   predictable way, so that when called again with another point in
8368 *   the same unit cube, p1 is picked to be the same.
8369 *
8370 * CHANGES
8371 *
8372 ******************************************************************************/
8373 
PickInCube(const VECTOR tv,VECTOR p1)8374 int PickInCube(const VECTOR tv, VECTOR  p1)
8375 {
8376 	size_t seed;
8377 	VECTOR flo;
8378 
8379 	/*
8380 	 * This uses floor() not FLOOR, so it will not be a mirror
8381 	 * image about zero in the range -1.0 to 1.0. The viewer
8382 	 * won't see an artefact around the origin.
8383 	 */
8384 
8385 	flo[X] = floor(tv[X] - EPSILON);
8386 	flo[Y] = floor(tv[Y] - EPSILON);
8387 	flo[Z] = floor(tv[Z] - EPSILON);
8388 
8389 	seed = size_t(Hash3d((int)flo[X], (int)flo[Y], (int)flo[Z]));
8390 
8391 	p1[X] = flo[X] + PatternRands(seed);
8392 	p1[Y] = flo[Y] + PatternRands(seed + 1);
8393 	p1[Z] = flo[Z] + PatternRands(seed + 2);
8394 
8395 	return (int)seed;
8396 }
8397 
8398 /*****************************************************************************
8399 *
8400 * FUNCTION
8401 *
8402 *   NewHash(tvx, tvy, tvz)
8403 *
8404 * INPUT
8405 *
8406 *   3D integer coordinates of the cell
8407 *
8408 * OUTPUT
8409 *
8410 * RETURNS
8411 *
8412 *   long integer hash value
8413 *
8414 * AUTHOR
8415 *
8416 *   Christoph Hormann based on MechSim Hash function by Daniel Jungmann
8417 *
8418 * DESCRIPTION
8419 *
8420 *   New Hash function for the crackle pattern.
8421 *
8422 * CHANGES
8423 *
8424 *   -- Aug 2005 : Creation
8425 *
8426 ******************************************************************************/
8427 
8428 #ifndef HAVE_BOOST_HASH
NewHash(long int tvx,long int tvy,long int tvz)8429 unsigned long int NewHash(long int tvx, long int tvy, long int tvz)
8430 {
8431 	unsigned long int seed;
8432 	long int r;
8433 
8434 	tvx *= 73856093L;
8435 	tvy *= 19349663L;
8436 	tvz *= 83492791L;
8437 
8438 	r = tvx ^ tvy ^ tvz;
8439 	seed = std::abs(r);
8440 	if (tvx<0) seed += LONG_MAX/2;
8441 	if (tvy<0) seed += LONG_MAX/4;
8442 	if (tvz<0) seed += LONG_MAX/8;
8443 
8444 	return (seed);
8445 }
8446 #endif
8447 
8448 
8449 /*****************************************************************************
8450 *
8451 * FUNCTION
8452 *
8453 * INPUT
8454 *
8455 * OUTPUT
8456 *
8457 * RETURNS
8458 *
8459 * AUTHOR
8460 *
8461 * DESCRIPTION
8462 *
8463 * CHANGES
8464 *
8465 ******************************************************************************/
8466 
8467 const DBL INV_SQRT_3_4 = 1.154700538;
quilt_cubic(DBL t,DBL p1,DBL p2)8468 DBL quilt_cubic(DBL t, DBL p1, DBL p2)
8469 {
8470 	DBL it=(1-t);
8471 	DBL itsqrd=it*it;
8472 	/* DBL itcubed=it*itsqrd; */
8473 	DBL tsqrd=t*t;
8474 	DBL tcubed=t*tsqrd;
8475 	DBL val;
8476 
8477 	/* Originally coded as...
8478 
8479 	val= (DBL)(itcubed*n1+(tcubed)*n2+3*t*(itsqrd)*p1+3*(tsqrd)*(it)*p2);
8480 
8481 	re-written by CEY to optimise because n1=0 n2=1 always.
8482 
8483 	*/
8484 
8485 	val = (tcubed + 3.0*t*itsqrd*p1 + 3.0*tsqrd*it*p2) * INV_SQRT_3_4;
8486 
8487 	return(val);
8488 }
8489 
8490 
8491 /*****************************************************************************
8492 *
8493 * FUNCTION
8494 *
8495 * INPUT
8496 *
8497 * OUTPUT
8498 *
8499 * RETURNS
8500 *
8501 * AUTHOR
8502 *
8503 * DESCRIPTION
8504 *
8505 * CHANGES
8506 *
8507 ******************************************************************************/
8508 
fractal_exterior_color(const TPATTERN * TPat,int iters,DBL a,DBL b)8509 static DBL fractal_exterior_color(const TPATTERN *TPat, int iters, DBL a, DBL b)
8510 {
8511 	switch(TPat->Vals.Fractal.exterior_type)
8512 	{
8513 		case 0:
8514 			return  (DBL)TPat->Vals.Fractal.efactor;
8515 		case 1:
8516 			return (DBL)iters / (DBL)TPat->Vals.Fractal.Iterations;
8517 		case 2:
8518 			return a * (DBL)TPat->Vals.Fractal.efactor;
8519 		case 3:
8520 			return b * (DBL)TPat->Vals.Fractal.efactor;
8521 		case 4:
8522 			return a*a * (DBL)TPat->Vals.Fractal.efactor;
8523 		case 5:
8524 			return b*b * (DBL)TPat->Vals.Fractal.efactor;
8525 		case 6:
8526 			return sqrt(a*a+b*b) * (DBL)TPat->Vals.Fractal.efactor;
8527 		case 7: // range 0.. (n-1)/n
8528 			return  (DBL)( iters % (unsigned int)TPat->Vals.Fractal.efactor )/(DBL)TPat->Vals.Fractal.efactor;
8529 		case 8: // range 0.. 1
8530 			return  (DBL)( iters % (unsigned int)(1+TPat->Vals.Fractal.efactor) )/(DBL)TPat->Vals.Fractal.efactor;
8531 	}
8532 	return 0;
8533 }
8534 
8535 
8536 /*****************************************************************************
8537 *
8538 * FUNCTION
8539 *
8540 * INPUT
8541 *
8542 * OUTPUT
8543 *
8544 * RETURNS
8545 *
8546 * AUTHOR
8547 *
8548 * DESCRIPTION
8549 *
8550 * CHANGES
8551 *
8552 ******************************************************************************/
8553 
fractal_interior_color(const TPATTERN * TPat,int,DBL a,DBL b,DBL mindist2)8554 static DBL fractal_interior_color(const TPATTERN *TPat, int /*iters*/, DBL a, DBL b, DBL mindist2)
8555 {
8556 	switch(TPat->Vals.Fractal.interior_type)
8557 	{
8558 		case 0:
8559 			return  (DBL)TPat->Vals.Fractal.ifactor;
8560 		case 1:
8561 			return sqrt(mindist2) * (DBL)TPat->Vals.Fractal.ifactor;
8562 		case 2:
8563 			return a * (DBL)TPat->Vals.Fractal.ifactor;
8564 		case 3:
8565 			return b * (DBL)TPat->Vals.Fractal.ifactor;
8566 		case 4:
8567 			return a*a * (DBL)TPat->Vals.Fractal.ifactor;
8568 		case 5:
8569 			return b*b * (DBL)TPat->Vals.Fractal.ifactor;
8570 		case 6:
8571 			return a*a+b*b * (DBL)TPat->Vals.Fractal.ifactor;
8572 	}
8573 	return 0;
8574 }
8575 
8576 
8577 /*****************************************************************************
8578 *
8579 * FUNCTION
8580 *
8581 *   Create_Density_File
8582 *
8583 * INPUT
8584 *
8585 * OUTPUT
8586 *
8587 * RETURNS
8588 *
8589 * AUTHOR
8590 *
8591 *   Dieter Bayer
8592 *
8593 * DESCRIPTION
8594 *
8595 *   Create a density file structure.
8596 *
8597 * CHANGES
8598 *
8599 *   Dec 1996 : Creation.
8600 *
8601 ******************************************************************************/
8602 
Create_Density_File()8603 DENSITY_FILE *Create_Density_File()
8604 {
8605 	DENSITY_FILE *New;
8606 
8607 	New = reinterpret_cast<DENSITY_FILE *>(POV_MALLOC(sizeof(DENSITY_FILE), "density file"));
8608 
8609 	New->Interpolation = NO_INTERPOLATION;
8610 
8611 	New->Data = reinterpret_cast<DENSITY_FILE_DATA *>(POV_MALLOC(sizeof(DENSITY_FILE_DATA), "density file data"));
8612 
8613 	New->Data->References = 1;
8614 
8615 	New->Data->Name = NULL;
8616 
8617 	New->Data->Sx =
8618 	New->Data->Sy =
8619 	New->Data->Sz = 0;
8620 
8621 	New->Data->Type = 0;
8622 
8623 	New->Data->Density32 = NULL;
8624 	New->Data->Density16 = NULL;
8625 	New->Data->Density8 = NULL;
8626 
8627 	return (New);
8628 }
8629 
8630 
8631 /*****************************************************************************
8632 *
8633 * FUNCTION
8634 *
8635 *   Copy_Density_File
8636 *
8637 * INPUT
8638 *
8639 * OUTPUT
8640 *
8641 * RETURNS
8642 *
8643 * AUTHOR
8644 *
8645 *   Dieter Bayer
8646 *
8647 * DESCRIPTION
8648 *
8649 *   Copy a density file structure.
8650 *
8651 * CHANGES
8652 *
8653 *   Dec 1996 : Creation.
8654 *
8655 ******************************************************************************/
8656 
Copy_Density_File(DENSITY_FILE * Old)8657 DENSITY_FILE *Copy_Density_File(DENSITY_FILE *Old)
8658 {
8659 	DENSITY_FILE *New;
8660 
8661 	if (Old != NULL)
8662 	{
8663 		New = reinterpret_cast<DENSITY_FILE *>(POV_MALLOC(sizeof(DENSITY_FILE), "density file"));
8664 
8665 		*New = *Old;
8666 
8667 		New->Data->References++;
8668 	}
8669 	else
8670 	{
8671 		New=NULL;
8672 	}
8673 
8674 	return(New);
8675 }
8676 
8677 
8678 /*****************************************************************************
8679 *
8680 * FUNCTION
8681 *
8682 *   Destroy_Density_File
8683 *
8684 * INPUT
8685 *
8686 * OUTPUT
8687 *
8688 * RETURNS
8689 *
8690 * AUTHOR
8691 *
8692 *   Dieter Bayer
8693 *
8694 * DESCRIPTION
8695 *
8696 *   Destroy a density file structure.
8697 *
8698 * CHANGES
8699 *
8700 *   Dec 1996 : Creation.
8701 *
8702 ******************************************************************************/
8703 
Destroy_Density_File(DENSITY_FILE * Density_File)8704 void Destroy_Density_File(DENSITY_FILE *Density_File)
8705 {
8706 	if(Density_File != NULL)
8707 	{
8708 		if((--(Density_File->Data->References)) == 0)
8709 		{
8710 			POV_FREE(Density_File->Data->Name);
8711 
8712 			if(Density_File->Data->Type == 4)
8713 			{
8714 				POV_FREE(Density_File->Data->Density32);
8715 			}
8716 			else if(Density_File->Data->Type == 2)
8717 			{
8718 				POV_FREE(Density_File->Data->Density16);
8719 			}
8720 			else if(Density_File->Data->Type == 1)
8721 			{
8722 				POV_FREE(Density_File->Data->Density8);
8723 			}
8724 
8725 			POV_FREE(Density_File->Data);
8726 		}
8727 
8728 		POV_FREE(Density_File);
8729 	}
8730 }
8731 
Read_Density_File(IStream * file,DENSITY_FILE * df)8732 void Read_Density_File(IStream *file, DENSITY_FILE *df)
8733 {
8734 	size_t x, y, z, sx, sy, sz, len;
8735 
8736 	if (df == NULL)
8737 		return;
8738 
8739 	/* Allocate and read density file. */
8740 
8741 	if((df != NULL) && (df->Data->Name != NULL))
8742 	{
8743 		sx = df->Data->Sx = readushort(file);
8744 		sy = df->Data->Sy = readushort(file);
8745 		sz = df->Data->Sz = readushort(file);
8746 
8747 		file->seekg(0, IOBase::seek_end);
8748 		len = file->tellg() - 6;
8749 		file->seekg(6);
8750 
8751 		// figure out the data size
8752 		if((sx * sy * sz * 4) == len)
8753 		{
8754 			df->Data->Type = 4;
8755 
8756 			unsigned int *map = reinterpret_cast<unsigned int *>(POV_MALLOC(sx * sy * sz * sizeof(unsigned int), "media density file data 32 bit"));
8757 
8758 			for (z = 0; z < sz; z++)
8759 			{
8760 				for (y = 0; y < sy; y++)
8761 				{
8762 					for (x = 0; x < sx; x++)
8763 						map[z * sy * sx + y * sx + x] = readuint(file);
8764 				}
8765 			}
8766 
8767 			df->Data->Density32 = map;
8768 		}
8769 		else if((sx * sy * sz * 2) == len)
8770 		{
8771 			df->Data->Type = 2;
8772 
8773 			unsigned short *map = reinterpret_cast<unsigned short *>(POV_MALLOC(sx * sy * sz * sizeof(unsigned short), "media density file data 16 bit"));
8774 
8775 			for (z = 0; z < sz; z++)
8776 			{
8777 				for (y = 0; y < sy; y++)
8778 				{
8779 					for (x = 0; x < sx; x++)
8780 						map[z * sy * sx + y * sx + x] = readushort(file);
8781 				}
8782 			}
8783 
8784 			df->Data->Density16 = map;
8785 		}
8786 		else if((sx * sy * sz) == len)
8787 		{
8788 			df->Data->Type = 1;
8789 
8790 			unsigned char *map = reinterpret_cast<unsigned char *>(POV_MALLOC(sx * sy * sz * sizeof(unsigned char), "media density file data 8 bit"));
8791 
8792 			for (z = 0; z < sz; z++)
8793 			{
8794 				for (y = 0; y < sy; y++)
8795 					file->read(&(map[z * sy * sx + y * sx]), sizeof(unsigned char) * sx);
8796 			}
8797 
8798 			df->Data->Density8 = map;
8799 		}
8800 		else
8801 			throw POV_EXCEPTION_STRING("Invalid density file size");
8802 
8803 		if (file != NULL)
8804 		{
8805 			delete file;
8806 		}
8807 	}
8808 }
8809 
readushort(IStream * infile)8810 static unsigned short readushort(IStream *infile)
8811 {
8812 	short i0 = 0, i1 = 0;
8813 
8814 	if ((i0 = infile->Read_Byte ()) == EOF || (i1 = infile->Read_Byte ()) == EOF)
8815 	{
8816 		throw POV_EXCEPTION_STRING("Error reading density_file");
8817 	}
8818 
8819 	return (((unsigned short)i0 << 8) | (unsigned short)i1);
8820 }
8821 
readuint(IStream * infile)8822 static unsigned int readuint(IStream *infile)
8823 {
8824 	int i0 = 0, i1 = 0, i2 = 0, i3 = 0;
8825 
8826 	if ((i0 = infile->Read_Byte ()) == EOF || (i1 = infile->Read_Byte ()) == EOF ||
8827 	    (i2 = infile->Read_Byte ()) == EOF || (i3 = infile->Read_Byte ()) == EOF)
8828 	{
8829 		throw POV_EXCEPTION_STRING("Error reading density_file");
8830 	}
8831 
8832 	return (((unsigned int)i0 << 24) | ((unsigned int)i1 << 16) | ((unsigned int)i2 << 8) | (unsigned int)i3);
8833 }
8834 
InitializeBinomialCoefficients(void)8835 static void InitializeBinomialCoefficients(void)
8836 {
8837 	int* ptr = BinomialCoefficients;
8838 	*ptr = 1; ++ptr;
8839 
8840 	for(unsigned n=1; n<=FRACTAL_MAX_EXPONENT; ++n)
8841 	{
8842 		*ptr = 1; ++ptr;
8843 		for(unsigned k=1; k<n; ++k)
8844 		{
8845 			*ptr = *(ptr-(n+1)) + *(ptr-n); ++ptr;
8846 		}
8847 		*ptr = 1; ++ptr;
8848 	}
8849 	ptr = BinomialCoefficients+1;
8850 	for(unsigned m=1; m<=FRACTAL_MAX_EXPONENT; ++m)
8851 	{
8852 		++ptr;
8853 		for(unsigned k=1; k<m; ++k)
8854 		{
8855 			if((k&2)!=0) *ptr = -(*ptr);
8856 			++ptr;
8857 		}
8858 		if((m&2)!=0) *ptr = -(*ptr);
8859 		++ptr;
8860 	}
8861 }
8862 
InitialiseCrackleCubeTable(void)8863 static void InitialiseCrackleCubeTable(void)
8864 {
8865 	int     *p = CrackleCubeTable;
8866 
8867 	// the crackle cube table is a list of offsets in the range -2 ... 2 which
8868 	// are applied to the EPoint while evaluating the Crackle pattern, in order
8869 	// to look up points in close-by cubes. consider the EPoint to be in a cube
8870 	// at the center of a 3x3 grid of cubes; candidate cubes are that are within
8871 	// a "3d knight move" away (i.e. not more than 2 units). we use a lookup table
8872 	// to speed up iteration of the cube list by avoiding branch tests.
8873 	for(int addx = -2; addx <= 2; addx++)
8874 	{
8875 		for(int addy = -2; addy <= 2; addy++)
8876 		{
8877 			for(int addz = -2; addz <= 2; addz++)
8878 			{
8879 				if((abs(addx) == 2) + (abs(addy) == 2) + (abs(addz) == 2) <= 1)
8880 				{
8881 					*p++ = addx;
8882 					*p++ = addy;
8883 					*p++ = addz;
8884 				}
8885 			}
8886 		}
8887 	}
8888 }
8889 
8890 // This should be called once, at povray start
InitializePatternGenerators(void)8891 void InitializePatternGenerators(void)
8892 {
8893 	InitializeBinomialCoefficients();
8894 	InitialiseCrackleCubeTable();
8895 }
8896 
8897 }
8898