1 # SPDX-License-Identifier: GPL-2.0-or-later
3 """Use Blender procedural textures exported to POV patterns."""
8 def export_pattern(texture
):
9 """Translate Blender procedural textures to POV patterns and write to pov file.
11 Function Patterns can be used to better access sub components of a pattern like
12 grey values for influence mapping
14 from .render
import string_strip_hyphen
18 pat_name
= "PAT_%s" % string_strip_hyphen(bpy
.path
.clean_name(tex
.name
))
19 mapping_dif
= "translate <%.4g,%.4g,%.4g> scale <%.4g,%.4g,%.4g>" % (
23 1.0 / pat
.tex_scale_x
,
24 1.0 / pat
.tex_scale_y
,
25 1.0 / pat
.tex_scale_z
,
29 def export_color_ramp(texture
):
32 col_ramp_strg
= "color_map {\n"
33 for num_color
, el
in enumerate(tex
.color_ramp
.elements
, start
=1):
36 col_r
, col_g
, col_b
, col_a
= col
[0], col
[1], col
[2], 1 - col
[3]
37 if pat
.tex_pattern_type
not in {
44 col_ramp_strg
+= "[%.4g color rgbf<%.4g,%.4g,%.4g,%.4g>] \n" % (
51 if pat
.tex_pattern_type
in {"brick", "checker"} and num_color
< 3:
52 col_ramp_strg
+= "color rgbf<%.4g,%.4g,%.4g,%.4g> \n" % (
58 if pat
.tex_pattern_type
== "hexagon" and num_color
< 4:
59 col_ramp_strg
+= "color rgbf<%.4g,%.4g,%.4g,%.4g> \n" % (
65 if pat
.tex_pattern_type
== "square" and num_color
< 5:
66 col_ramp_strg
+= "color rgbf<%.4g,%.4g,%.4g,%.4g> \n" % (
72 if pat
.tex_pattern_type
== "triangular" and num_color
< 7:
73 col_ramp_strg
+= "color rgbf<%.4g,%.4g,%.4g,%.4g> \n" % (
80 col_ramp_strg
+= "} \n"
84 # much work to be done here only defaults translated for now:
85 # pov noise_generator 3 means perlin noise
86 if tex
.type not in {"NONE", "IMAGE"} and pat
.tex_pattern_type
== "emulator":
87 text_strg
+= "pigment {\n"
88 # ------------------------- EMULATE BLENDER VORONOI TEXTURE ------------------------- #
89 if tex
.type == "VORONOI":
90 text_strg
+= "crackle\n"
91 text_strg
+= " offset %.4g\n" % tex
.nabla
92 text_strg
+= " form <%.4g,%.4g,%.4g>\n" % (
97 if tex
.distance_metric
== "DISTANCE":
98 text_strg
+= " metric 2.5\n"
99 if tex
.distance_metric
== "DISTANCE_SQUARED":
100 text_strg
+= " metric 2.5\n"
101 text_strg
+= " poly_wave 2\n"
102 if tex
.distance_metric
== "MINKOVSKY":
103 text_strg
+= " metric %s\n" % tex
.minkovsky_exponent
104 if tex
.distance_metric
== "MINKOVSKY_FOUR":
105 text_strg
+= " metric 4\n"
106 if tex
.distance_metric
== "MINKOVSKY_HALF":
107 text_strg
+= " metric 0.5\n"
108 if tex
.distance_metric
== "CHEBYCHEV":
109 text_strg
+= " metric 10\n"
110 if tex
.distance_metric
== "MANHATTAN":
111 text_strg
+= " metric 1\n"
113 if tex
.color_mode
== "POSITION":
114 text_strg
+= "solid\n"
115 text_strg
+= "scale 0.25\n"
116 if tex
.use_color_ramp
:
117 text_strg
+= export_color_ramp(tex
)
119 text_strg
+= "color_map {\n"
120 text_strg
+= "[0 color rgbt<0,0,0,1>]\n"
121 text_strg
+= "[1 color rgbt<1,1,1,0>]\n"
124 # ------------------------- EMULATE BLENDER CLOUDS TEXTURE ------------------------- #
125 if tex
.type == "CLOUDS":
126 if tex
.noise_type
== "SOFT_NOISE":
127 text_strg
+= "wrinkles\n"
128 text_strg
+= "scale 0.25\n"
130 text_strg
+= "granite\n"
131 if tex
.use_color_ramp
:
132 text_strg
+= export_color_ramp(tex
)
134 text_strg
+= "color_map {\n"
135 text_strg
+= "[0 color rgbt<0,0,0,1>]\n"
136 text_strg
+= "[1 color rgbt<1,1,1,0>]\n"
139 # ------------------------- EMULATE BLENDER WOOD TEXTURE ------------------------- #
140 if tex
.type == "WOOD":
141 if tex
.wood_type
== "RINGS":
142 text_strg
+= "wood\n"
143 text_strg
+= "scale 0.25\n"
144 if tex
.wood_type
== "RINGNOISE":
145 text_strg
+= "wood\n"
146 text_strg
+= "scale 0.25\n"
147 text_strg
+= "turbulence %.4g\n" % (tex
.turbulence
/ 100)
148 if tex
.wood_type
== "BANDS":
149 text_strg
+= "marble\n"
150 text_strg
+= "scale 0.25\n"
151 text_strg
+= "rotate <45,-45,45>\n"
152 if tex
.wood_type
== "BANDNOISE":
153 text_strg
+= "marble\n"
154 text_strg
+= "scale 0.25\n"
155 text_strg
+= "rotate <45,-45,45>\n"
156 text_strg
+= "turbulence %.4g\n" % (tex
.turbulence
/ 10)
158 if tex
.noise_basis_2
== "SIN":
159 text_strg
+= "sine_wave\n"
160 if tex
.noise_basis_2
== "TRI":
161 text_strg
+= "triangle_wave\n"
162 if tex
.noise_basis_2
== "SAW":
163 text_strg
+= "ramp_wave\n"
164 if tex
.use_color_ramp
:
165 text_strg
+= export_color_ramp(tex
)
167 text_strg
+= "color_map {\n"
168 text_strg
+= "[0 color rgbt<0,0,0,0>]\n"
169 text_strg
+= "[1 color rgbt<1,1,1,0>]\n"
172 # ------------------------- EMULATE BLENDER STUCCI TEXTURE ------------------------- #
173 if tex
.type == "STUCCI":
174 text_strg
+= "bozo\n"
175 text_strg
+= "scale 0.25\n"
176 if tex
.noise_type
== "HARD_NOISE":
177 text_strg
+= "triangle_wave\n"
178 if tex
.use_color_ramp
:
179 text_strg
+= export_color_ramp(tex
)
181 text_strg
+= "color_map {\n"
182 text_strg
+= "[0 color rgbf<1,1,1,0>]\n"
183 text_strg
+= "[1 color rgbt<0,0,0,1>]\n"
186 if tex
.use_color_ramp
:
187 text_strg
+= export_color_ramp(tex
)
189 text_strg
+= "color_map {\n"
190 text_strg
+= "[0 color rgbf<0,0,0,1>]\n"
191 text_strg
+= "[1 color rgbt<1,1,1,0>]\n"
194 # ------------------------- EMULATE BLENDER MAGIC TEXTURE ------------------------- #
195 if tex
.type == "MAGIC":
196 text_strg
+= "leopard\n"
197 if tex
.use_color_ramp
:
198 text_strg
+= export_color_ramp(tex
)
200 text_strg
+= "color_map {\n"
201 text_strg
+= "[0 color rgbt<1,1,1,0.5>]\n"
202 text_strg
+= "[0.25 color rgbf<0,1,0,0.75>]\n"
203 text_strg
+= "[0.5 color rgbf<0,0,1,0.75>]\n"
204 text_strg
+= "[0.75 color rgbf<1,0,1,0.75>]\n"
205 text_strg
+= "[1 color rgbf<0,1,0,0.75>]\n"
207 text_strg
+= "scale 0.1\n"
209 # ------------------------- EMULATE BLENDER MARBLE TEXTURE ------------------------- #
210 if tex
.type == "MARBLE":
211 text_strg
+= "marble\n"
212 text_strg
+= "turbulence 0.5\n"
213 text_strg
+= "noise_generator 3\n"
214 text_strg
+= "scale 0.75\n"
215 text_strg
+= "rotate <45,-45,45>\n"
216 if tex
.use_color_ramp
:
217 text_strg
+= export_color_ramp(tex
)
219 if tex
.marble_type
== "SOFT":
220 text_strg
+= "color_map {\n"
221 text_strg
+= "[0 color rgbt<0,0,0,0>]\n"
222 text_strg
+= "[0.05 color rgbt<0,0,0,0>]\n"
223 text_strg
+= "[1 color rgbt<0.9,0.9,0.9,0>]\n"
225 elif tex
.marble_type
== "SHARP":
226 text_strg
+= "color_map {\n"
227 text_strg
+= "[0 color rgbt<0,0,0,0>]\n"
228 text_strg
+= "[0.025 color rgbt<0,0,0,0>]\n"
229 text_strg
+= "[1 color rgbt<0.9,0.9,0.9,0>]\n"
232 text_strg
+= "[0 color rgbt<0,0,0,0>]\n"
233 text_strg
+= "[1 color rgbt<1,1,1,0>]\n"
235 if tex
.noise_basis_2
== "SIN":
236 text_strg
+= "sine_wave\n"
237 if tex
.noise_basis_2
== "TRI":
238 text_strg
+= "triangle_wave\n"
239 if tex
.noise_basis_2
== "SAW":
240 text_strg
+= "ramp_wave\n"
242 # ------------------------- EMULATE BLENDER BLEND TEXTURE ------------------------- #
243 if tex
.type == "BLEND":
244 if tex
.progression
== "RADIAL":
245 text_strg
+= "radial\n"
246 if tex
.use_flip_axis
== "HORIZONTAL":
247 text_strg
+= "rotate x*90\n"
249 text_strg
+= "rotate <-90,0,90>\n"
250 text_strg
+= "ramp_wave\n"
251 elif tex
.progression
== "SPHERICAL":
252 text_strg
+= "spherical\n"
253 text_strg
+= "scale 3\n"
254 text_strg
+= "poly_wave 1\n"
255 elif tex
.progression
== "QUADRATIC_SPHERE":
256 text_strg
+= "spherical\n"
257 text_strg
+= "scale 3\n"
258 text_strg
+= " poly_wave 2\n"
259 elif tex
.progression
== "DIAGONAL":
260 text_strg
+= "gradient <1,1,0>\n"
261 text_strg
+= "scale 3\n"
262 elif tex
.use_flip_axis
== "HORIZONTAL":
263 text_strg
+= "gradient x\n"
264 text_strg
+= "scale 2.01\n"
265 elif tex
.use_flip_axis
== "VERTICAL":
266 text_strg
+= "gradient y\n"
267 text_strg
+= "scale 2.01\n"
268 # text_strg+="ramp_wave\n"
269 # text_strg+="frequency 0.5\n"
270 text_strg
+= "phase 0.5\n"
271 if tex
.use_color_ramp
:
272 text_strg
+= export_color_ramp(tex
)
274 text_strg
+= "color_map {\n"
275 text_strg
+= "[0 color rgbt<1,1,1,0>]\n"
276 text_strg
+= "[1 color rgbf<0,0,0,1>]\n"
278 if tex
.progression
== "LINEAR":
279 text_strg
+= " poly_wave 1\n"
280 if tex
.progression
== "QUADRATIC":
281 text_strg
+= " poly_wave 2\n"
282 if tex
.progression
== "EASING":
283 text_strg
+= " poly_wave 1.5\n"
285 # ------------------------- EMULATE BLENDER MUSGRAVE TEXTURE ------------------------- #
286 # if tex.type == 'MUSGRAVE':
287 # text_strg+="function{ f_ridged_mf( x, y, 0, 1, 2, 9, -0.5, 3,3 )*0.5}\n"
288 # text_strg+="color_map {\n"
289 # text_strg+="[0 color rgbf<0,0,0,1>]\n"
290 # text_strg+="[1 color rgbf<1,1,1,0>]\n"
292 # simplified for now:
294 if tex
.type == "MUSGRAVE":
295 text_strg
+= "bozo scale 0.25 \n"
296 if tex
.use_color_ramp
:
297 text_strg
+= export_color_ramp(tex
)
300 "color_map {[0.5 color rgbf<0,0,0,1>][1 color rgbt<1,1,1,0>]}ramp_wave \n"
303 # ------------------------- EMULATE BLENDER DISTORTED NOISE TEXTURE ------------------------- #
304 if tex
.type == "DISTORTED_NOISE":
305 text_strg
+= "average\n"
306 text_strg
+= " pigment_map {\n"
307 text_strg
+= " [1 bozo scale 0.25 turbulence %.4g\n" % tex
.distortion
308 if tex
.use_color_ramp
:
309 text_strg
+= export_color_ramp(tex
)
311 text_strg
+= "color_map {\n"
312 text_strg
+= "[0 color rgbt<1,1,1,0>]\n"
313 text_strg
+= "[1 color rgbf<0,0,0,1>]\n"
317 if tex
.noise_distortion
== "CELL_NOISE":
318 text_strg
+= " [1 cells scale 0.1\n"
319 if tex
.use_color_ramp
:
320 text_strg
+= export_color_ramp(tex
)
322 text_strg
+= "color_map {\n"
323 text_strg
+= "[0 color rgbt<1,1,1,0>]\n"
324 text_strg
+= "[1 color rgbf<0,0,0,1>]\n"
327 if tex
.noise_distortion
== "VORONOI_CRACKLE":
328 text_strg
+= " [1 crackle scale 0.25\n"
329 if tex
.use_color_ramp
:
330 text_strg
+= export_color_ramp(tex
)
332 text_strg
+= "color_map {\n"
333 text_strg
+= "[0 color rgbt<1,1,1,0>]\n"
334 text_strg
+= "[1 color rgbf<0,0,0,1>]\n"
337 if tex
.noise_distortion
in [
344 text_strg
+= " [1 crackle metric 2.5 scale 0.25 turbulence %.4g\n" % (
347 if tex
.use_color_ramp
:
348 text_strg
+= export_color_ramp(tex
)
350 text_strg
+= "color_map {\n"
351 text_strg
+= "[0 color rgbt<1,1,1,0>]\n"
352 text_strg
+= "[1 color rgbf<0,0,0,1>]\n"
356 text_strg
+= " [1 wrinkles scale 0.25\n"
357 if tex
.use_color_ramp
:
358 text_strg
+= export_color_ramp(tex
)
360 text_strg
+= "color_map {\n"
361 text_strg
+= "[0 color rgbt<1,1,1,0>]\n"
362 text_strg
+= "[1 color rgbf<0,0,0,1>]\n"
367 # ------------------------- EMULATE BLENDER NOISE TEXTURE ------------------------- #
368 if tex
.type == "NOISE":
369 text_strg
+= "cells\n"
370 text_strg
+= "turbulence 3\n"
371 text_strg
+= "omega 3\n"
372 if tex
.use_color_ramp
:
373 text_strg
+= export_color_ramp(tex
)
375 text_strg
+= "color_map {\n"
376 text_strg
+= "[0.75 color rgb<0,0,0,>]\n"
377 text_strg
+= "[1 color rgb<1,1,1,>]\n"
380 # ------------------------- IGNORE OTHER BLENDER TEXTURE ------------------------- #
381 else: # non translated textures
385 text_strg
+= "#declare f%s=\n" % pat_name
386 text_strg
+= "function{pigment{%s}}\n" % pat_name
389 elif pat
.tex_pattern_type
!= "emulator":
390 text_strg
+= "pigment {\n"
391 text_strg
+= "%s\n" % pat
.tex_pattern_type
392 if pat
.tex_pattern_type
== "agate":
393 text_strg
+= "agate_turb %.4g\n" % pat
.modifier_turbulence
394 if pat
.tex_pattern_type
in {"spiral1", "spiral2", "tiling"}:
395 text_strg
+= "%s\n" % pat
.modifier_numbers
396 if pat
.tex_pattern_type
== "quilted":
397 text_strg
+= "control0 %s control1 %s\n" % (
398 pat
.modifier_control0
,
399 pat
.modifier_control1
,
401 if pat
.tex_pattern_type
== "mandel":
402 text_strg
+= "%s exponent %s \n" % (pat
.f_iter
, pat
.f_exponent
)
403 if pat
.tex_pattern_type
== "julia":
404 text_strg
+= "<%.4g, %.4g> %s exponent %s \n" % (
410 if pat
.tex_pattern_type
== "magnet" and pat
.magnet_style
== "mandel":
411 text_strg
+= "%s mandel %s \n" % (pat
.magnet_type
, pat
.f_iter
)
412 if pat
.tex_pattern_type
== "magnet" and pat
.magnet_style
== "julia":
413 text_strg
+= "%s julia <%.4g, %.4g> %s\n" % (
419 if pat
.tex_pattern_type
in {"mandel", "julia", "magnet"}:
420 text_strg
+= "interior %s, %.4g\n" % (pat
.f_ior
, pat
.f_ior_fac
)
421 text_strg
+= "exterior %s, %.4g\n" % (pat
.f_eor
, pat
.f_eor_fac
)
422 if pat
.tex_pattern_type
== "gradient":
423 text_strg
+= "<%s, %s, %s> \n" % (
428 if pat
.tex_pattern_type
== "pavement":
429 num_tiles
= pat
.pave_tiles
431 if pat
.pave_sides
== "4" and pat
.pave_tiles
== 3:
432 num_pattern
= pat
.pave_pat_2
433 if pat
.pave_sides
== "6" and pat
.pave_tiles
== 3:
434 num_pattern
= pat
.pave_pat_3
435 if pat
.pave_sides
== "3" and pat
.pave_tiles
== 4:
436 num_pattern
= pat
.pave_pat_3
437 if pat
.pave_sides
== "3" and pat
.pave_tiles
== 5:
438 num_pattern
= pat
.pave_pat_4
439 if pat
.pave_sides
== "4" and pat
.pave_tiles
== 4:
440 num_pattern
= pat
.pave_pat_5
441 if pat
.pave_sides
== "6" and pat
.pave_tiles
== 4:
442 num_pattern
= pat
.pave_pat_7
443 if pat
.pave_sides
== "4" and pat
.pave_tiles
== 5:
444 num_pattern
= pat
.pave_pat_12
445 if pat
.pave_sides
== "3" and pat
.pave_tiles
== 6:
446 num_pattern
= pat
.pave_pat_12
447 if pat
.pave_sides
== "6" and pat
.pave_tiles
== 5:
448 num_pattern
= pat
.pave_pat_22
449 if pat
.pave_sides
== "4" and pat
.pave_tiles
== 6:
450 num_pattern
= pat
.pave_pat_35
451 if pat
.pave_sides
== "6" and pat
.pave_tiles
== 6:
453 text_strg
+= "number_of_sides %s number_of_tiles %s pattern %s form %s \n" % (
459 # ------------------------- functions ------------------------- #
460 if pat
.tex_pattern_type
== "function":
461 text_strg
+= "{ %s" % pat
.func_list
463 if pat
.func_plus_x
!= "NONE":
464 if pat
.func_plus_x
== "increase":
466 if pat
.func_plus_x
== "plus":
468 text_strg
+= "%.4g" % pat
.func_x
470 if pat
.func_plus_y
!= "NONE":
471 if pat
.func_plus_y
== "increase":
473 if pat
.func_plus_y
== "plus":
475 text_strg
+= "%.4g" % pat
.func_y
477 if pat
.func_plus_z
!= "NONE":
478 if pat
.func_plus_z
== "increase":
480 if pat
.func_plus_z
== "plus":
482 text_strg
+= "%.4g" % pat
.func_z
484 if pat
.func_list
in {
497 "f_kummer_surface_v1",
498 "f_lemniscate_of_gerono",
507 "f_quartic_paraboloid",
515 if pat
.func_list
in {
523 if pat
.func_list
in {
526 "f_hyperbolic_torus",
527 "f_kampyle_of_eudoxus",
529 "f_quartic_cylinder",
533 if pat
.func_list
in {
535 "f_cross_ellipsoids",
537 "f_isect_ellipsoids",
538 "f_kummer_surface_v2",
539 "f_ovals_of_cassini",
545 if pat
.func_list
in {
556 if pat
.func_list
in {
559 "f_folium_surface_2d",
561 "f_kampyle_of_eudoxus_2d",
562 "f_lemniscate_of_gerono_2d",
570 if pat
.func_list
in {
577 if pat
.func_list
== "f_helical_torus":
580 text_strg
+= ",%.4g" % pat
.func_P0
582 text_strg
+= ",%.4g" % pat
.func_P1
584 text_strg
+= ",%.4g" % pat
.func_P2
586 text_strg
+= ",%.4g" % pat
.func_P3
588 text_strg
+= ",%.4g" % pat
.func_P4
590 text_strg
+= ",%.4g" % pat
.func_P5
592 text_strg
+= ",%.4g" % pat
.func_P6
594 text_strg
+= ",%.4g" % pat
.func_P7
595 text_strg
+= ",%.4g" % pat
.func_P8
596 text_strg
+= ",%.4g" % pat
.func_P9
598 # ------------------------- end functions ------------------------- #
599 if pat
.tex_pattern_type
not in {
606 text_strg
+= "color_map {\n"
607 if tex
.use_color_ramp
:
608 for num_color
, el
in enumerate(tex
.color_ramp
.elements
, start
=1):
611 col_r
, col_g
, col_b
, col_a
= col
[0], col
[1], col
[2], 1 - col
[3]
612 if pat
.tex_pattern_type
not in {
619 text_strg
+= "[%.4g color rgbf<%.4g,%.4g,%.4g,%.4g>] \n" % (
626 if pat
.tex_pattern_type
in {"brick", "checker"} and num_color
< 3:
627 text_strg
+= "color rgbf<%.4g,%.4g,%.4g,%.4g> \n" % (
633 if pat
.tex_pattern_type
== "hexagon" and num_color
< 4:
634 text_strg
+= "color rgbf<%.4g,%.4g,%.4g,%.4g> \n" % (
640 if pat
.tex_pattern_type
== "square" and num_color
< 5:
641 text_strg
+= "color rgbf<%.4g,%.4g,%.4g,%.4g> \n" % (
647 if pat
.tex_pattern_type
== "triangular" and num_color
< 7:
648 text_strg
+= "color rgbf<%.4g,%.4g,%.4g,%.4g> \n" % (
655 text_strg
+= "[0 color rgbf<0,0,0,1>]\n"
656 text_strg
+= "[1 color rgbf<1,1,1,0>]\n"
657 if pat
.tex_pattern_type
not in {
665 if pat
.tex_pattern_type
== "brick":
666 text_strg
+= "brick_size <%.4g, %.4g, %.4g> mortar %.4g \n" % (
672 text_strg
+= "%s \n" % mapping_dif
673 text_strg
+= "rotate <%.4g,%.4g,%.4g> \n" % (
678 text_strg
+= "turbulence <%.4g,%.4g,%.4g> \n" % (
679 pat
.warp_turbulence_x
,
680 pat
.warp_turbulence_y
,
681 pat
.warp_turbulence_z
,
683 text_strg
+= "octaves %s \n" % pat
.modifier_octaves
684 text_strg
+= "lambda %.4g \n" % pat
.modifier_lambda
685 text_strg
+= "omega %.4g \n" % pat
.modifier_omega
686 text_strg
+= "frequency %.4g \n" % pat
.modifier_frequency
687 text_strg
+= "phase %.4g \n" % pat
.modifier_phase
689 text_strg
+= "#declare f%s=\n" % pat_name
690 text_strg
+= "function{pigment{%s}}\n" % pat_name