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