1 # SPDX-FileCopyrightText: 2022 Blender Foundation
3 # SPDX-License-Identifier: GPL-2.0-or-later
5 """Use Blender procedural textures exported to POV patterns."""
10 def export_pattern(texture
):
11 """Translate Blender procedural textures to POV patterns and write to pov file.
13 Function Patterns can be used to better access sub components of a pattern like
14 grey values for influence mapping
16 from .render
import string_strip_hyphen
20 pat_name
= "PAT_%s" % string_strip_hyphen(bpy
.path
.clean_name(tex
.name
))
21 mapping_dif
= "translate <%.4g,%.4g,%.4g> scale <%.4g,%.4g,%.4g>" % (
25 1.0 / pat
.tex_scale_x
,
26 1.0 / pat
.tex_scale_y
,
27 1.0 / pat
.tex_scale_z
,
31 def export_color_ramp(texture
):
34 col_ramp_strg
= "color_map {\n"
35 for num_color
, el
in enumerate(tex
.color_ramp
.elements
, start
=1):
38 col_r
, col_g
, col_b
, col_a
= col
[0], col
[1], col
[2], 1 - col
[3]
39 if pat
.tex_pattern_type
not in {
46 col_ramp_strg
+= "[%.4g color rgbf<%.4g,%.4g,%.4g,%.4g>] \n" % (
53 if pat
.tex_pattern_type
in {"brick", "checker"} and num_color
< 3:
54 col_ramp_strg
+= "color rgbf<%.4g,%.4g,%.4g,%.4g> \n" % (
60 if pat
.tex_pattern_type
== "hexagon" and num_color
< 4:
61 col_ramp_strg
+= "color rgbf<%.4g,%.4g,%.4g,%.4g> \n" % (
67 if pat
.tex_pattern_type
== "square" and num_color
< 5:
68 col_ramp_strg
+= "color rgbf<%.4g,%.4g,%.4g,%.4g> \n" % (
74 if pat
.tex_pattern_type
== "triangular" and num_color
< 7:
75 col_ramp_strg
+= "color rgbf<%.4g,%.4g,%.4g,%.4g> \n" % (
82 col_ramp_strg
+= "} \n"
86 # much work to be done here only defaults translated for now:
87 # pov noise_generator 3 means perlin noise
88 if tex
.type not in {"NONE", "IMAGE"} and pat
.tex_pattern_type
== "emulator":
89 text_strg
+= "pigment {\n"
90 # ------------------------- EMULATE BLENDER VORONOI TEXTURE ------------------------- #
91 if tex
.type == "VORONOI":
92 text_strg
+= "crackle\n"
93 text_strg
+= " offset %.4g\n" % tex
.nabla
94 text_strg
+= " form <%.4g,%.4g,%.4g>\n" % (
99 if tex
.distance_metric
== "DISTANCE":
100 text_strg
+= " metric 2.5\n"
101 if tex
.distance_metric
== "DISTANCE_SQUARED":
102 text_strg
+= " metric 2.5\n"
103 text_strg
+= " poly_wave 2\n"
104 if tex
.distance_metric
== "MINKOVSKY":
105 text_strg
+= " metric %s\n" % tex
.minkovsky_exponent
106 if tex
.distance_metric
== "MINKOVSKY_FOUR":
107 text_strg
+= " metric 4\n"
108 if tex
.distance_metric
== "MINKOVSKY_HALF":
109 text_strg
+= " metric 0.5\n"
110 if tex
.distance_metric
== "CHEBYCHEV":
111 text_strg
+= " metric 10\n"
112 if tex
.distance_metric
== "MANHATTAN":
113 text_strg
+= " metric 1\n"
115 if tex
.color_mode
== "POSITION":
116 text_strg
+= "solid\n"
117 text_strg
+= "scale 0.25\n"
118 if tex
.use_color_ramp
:
119 text_strg
+= export_color_ramp(tex
)
121 text_strg
+= "color_map {\n"
122 text_strg
+= "[0 color rgbt<0,0,0,1>]\n"
123 text_strg
+= "[1 color rgbt<1,1,1,0>]\n"
126 # ------------------------- EMULATE BLENDER CLOUDS TEXTURE ------------------------- #
127 if tex
.type == "CLOUDS":
128 if tex
.noise_type
== "SOFT_NOISE":
129 text_strg
+= "wrinkles\n"
130 text_strg
+= "scale 0.25\n"
132 text_strg
+= "granite\n"
133 if tex
.use_color_ramp
:
134 text_strg
+= export_color_ramp(tex
)
136 text_strg
+= "color_map {\n"
137 text_strg
+= "[0 color rgbt<0,0,0,1>]\n"
138 text_strg
+= "[1 color rgbt<1,1,1,0>]\n"
141 # ------------------------- EMULATE BLENDER WOOD TEXTURE ------------------------- #
142 if tex
.type == "WOOD":
143 if tex
.wood_type
== "RINGS":
144 text_strg
+= "wood\n"
145 text_strg
+= "scale 0.25\n"
146 if tex
.wood_type
== "RINGNOISE":
147 text_strg
+= "wood\n"
148 text_strg
+= "scale 0.25\n"
149 text_strg
+= "turbulence %.4g\n" % (tex
.turbulence
/ 100)
150 if tex
.wood_type
== "BANDS":
151 text_strg
+= "marble\n"
152 text_strg
+= "scale 0.25\n"
153 text_strg
+= "rotate <45,-45,45>\n"
154 if tex
.wood_type
== "BANDNOISE":
155 text_strg
+= "marble\n"
156 text_strg
+= "scale 0.25\n"
157 text_strg
+= "rotate <45,-45,45>\n"
158 text_strg
+= "turbulence %.4g\n" % (tex
.turbulence
/ 10)
160 if tex
.noise_basis_2
== "SIN":
161 text_strg
+= "sine_wave\n"
162 if tex
.noise_basis_2
== "TRI":
163 text_strg
+= "triangle_wave\n"
164 if tex
.noise_basis_2
== "SAW":
165 text_strg
+= "ramp_wave\n"
166 if tex
.use_color_ramp
:
167 text_strg
+= export_color_ramp(tex
)
169 text_strg
+= "color_map {\n"
170 text_strg
+= "[0 color rgbt<0,0,0,0>]\n"
171 text_strg
+= "[1 color rgbt<1,1,1,0>]\n"
174 # ------------------------- EMULATE BLENDER STUCCI TEXTURE ------------------------- #
175 if tex
.type == "STUCCI":
176 text_strg
+= "bozo\n"
177 text_strg
+= "scale 0.25\n"
178 if tex
.noise_type
== "HARD_NOISE":
179 text_strg
+= "triangle_wave\n"
180 if tex
.use_color_ramp
:
181 text_strg
+= export_color_ramp(tex
)
183 text_strg
+= "color_map {\n"
184 text_strg
+= "[0 color rgbf<1,1,1,0>]\n"
185 text_strg
+= "[1 color rgbt<0,0,0,1>]\n"
188 if tex
.use_color_ramp
:
189 text_strg
+= export_color_ramp(tex
)
191 text_strg
+= "color_map {\n"
192 text_strg
+= "[0 color rgbf<0,0,0,1>]\n"
193 text_strg
+= "[1 color rgbt<1,1,1,0>]\n"
196 # ------------------------- EMULATE BLENDER MAGIC TEXTURE ------------------------- #
197 if tex
.type == "MAGIC":
198 text_strg
+= "leopard\n"
199 if tex
.use_color_ramp
:
200 text_strg
+= export_color_ramp(tex
)
202 text_strg
+= "color_map {\n"
203 text_strg
+= "[0 color rgbt<1,1,1,0.5>]\n"
204 text_strg
+= "[0.25 color rgbf<0,1,0,0.75>]\n"
205 text_strg
+= "[0.5 color rgbf<0,0,1,0.75>]\n"
206 text_strg
+= "[0.75 color rgbf<1,0,1,0.75>]\n"
207 text_strg
+= "[1 color rgbf<0,1,0,0.75>]\n"
209 text_strg
+= "scale 0.1\n"
211 # ------------------------- EMULATE BLENDER MARBLE TEXTURE ------------------------- #
212 if tex
.type == "MARBLE":
213 text_strg
+= "marble\n"
214 text_strg
+= "turbulence 0.5\n"
215 text_strg
+= "noise_generator 3\n"
216 text_strg
+= "scale 0.75\n"
217 text_strg
+= "rotate <45,-45,45>\n"
218 if tex
.use_color_ramp
:
219 text_strg
+= export_color_ramp(tex
)
221 if tex
.marble_type
== "SOFT":
222 text_strg
+= "color_map {\n"
223 text_strg
+= "[0 color rgbt<0,0,0,0>]\n"
224 text_strg
+= "[0.05 color rgbt<0,0,0,0>]\n"
225 text_strg
+= "[1 color rgbt<0.9,0.9,0.9,0>]\n"
227 elif tex
.marble_type
== "SHARP":
228 text_strg
+= "color_map {\n"
229 text_strg
+= "[0 color rgbt<0,0,0,0>]\n"
230 text_strg
+= "[0.025 color rgbt<0,0,0,0>]\n"
231 text_strg
+= "[1 color rgbt<0.9,0.9,0.9,0>]\n"
234 text_strg
+= "[0 color rgbt<0,0,0,0>]\n"
235 text_strg
+= "[1 color rgbt<1,1,1,0>]\n"
237 if tex
.noise_basis_2
== "SIN":
238 text_strg
+= "sine_wave\n"
239 if tex
.noise_basis_2
== "TRI":
240 text_strg
+= "triangle_wave\n"
241 if tex
.noise_basis_2
== "SAW":
242 text_strg
+= "ramp_wave\n"
244 # ------------------------- EMULATE BLENDER BLEND TEXTURE ------------------------- #
245 if tex
.type == "BLEND":
246 if tex
.progression
== "RADIAL":
247 text_strg
+= "radial\n"
248 if tex
.use_flip_axis
== "HORIZONTAL":
249 text_strg
+= "rotate x*90\n"
251 text_strg
+= "rotate <-90,0,90>\n"
252 text_strg
+= "ramp_wave\n"
253 elif tex
.progression
== "SPHERICAL":
254 text_strg
+= "spherical\n"
255 text_strg
+= "scale 3\n"
256 text_strg
+= "poly_wave 1\n"
257 elif tex
.progression
== "QUADRATIC_SPHERE":
258 text_strg
+= "spherical\n"
259 text_strg
+= "scale 3\n"
260 text_strg
+= " poly_wave 2\n"
261 elif tex
.progression
== "DIAGONAL":
262 text_strg
+= "gradient <1,1,0>\n"
263 text_strg
+= "scale 3\n"
264 elif tex
.use_flip_axis
== "HORIZONTAL":
265 text_strg
+= "gradient x\n"
266 text_strg
+= "scale 2.01\n"
267 elif tex
.use_flip_axis
== "VERTICAL":
268 text_strg
+= "gradient y\n"
269 text_strg
+= "scale 2.01\n"
270 # text_strg+="ramp_wave\n"
271 # text_strg+="frequency 0.5\n"
272 text_strg
+= "phase 0.5\n"
273 if tex
.use_color_ramp
:
274 text_strg
+= export_color_ramp(tex
)
276 text_strg
+= "color_map {\n"
277 text_strg
+= "[0 color rgbt<1,1,1,0>]\n"
278 text_strg
+= "[1 color rgbf<0,0,0,1>]\n"
280 if tex
.progression
== "LINEAR":
281 text_strg
+= " poly_wave 1\n"
282 if tex
.progression
== "QUADRATIC":
283 text_strg
+= " poly_wave 2\n"
284 if tex
.progression
== "EASING":
285 text_strg
+= " poly_wave 1.5\n"
287 # ------------------------- EMULATE BLENDER MUSGRAVE TEXTURE ------------------------- #
288 # if tex.type == 'MUSGRAVE':
289 # text_strg+="function{ f_ridged_mf( x, y, 0, 1, 2, 9, -0.5, 3,3 )*0.5}\n"
290 # text_strg+="color_map {\n"
291 # text_strg+="[0 color rgbf<0,0,0,1>]\n"
292 # text_strg+="[1 color rgbf<1,1,1,0>]\n"
294 # simplified for now:
296 if tex
.type == "MUSGRAVE":
297 text_strg
+= "bozo scale 0.25 \n"
298 if tex
.use_color_ramp
:
299 text_strg
+= export_color_ramp(tex
)
302 "color_map {[0.5 color rgbf<0,0,0,1>][1 color rgbt<1,1,1,0>]}ramp_wave \n"
305 # ------------------------- EMULATE BLENDER DISTORTED NOISE TEXTURE ------------------------- #
306 if tex
.type == "DISTORTED_NOISE":
307 text_strg
+= "average\n"
308 text_strg
+= " pigment_map {\n"
309 text_strg
+= " [1 bozo scale 0.25 turbulence %.4g\n" % tex
.distortion
310 if tex
.use_color_ramp
:
311 text_strg
+= export_color_ramp(tex
)
313 text_strg
+= "color_map {\n"
314 text_strg
+= "[0 color rgbt<1,1,1,0>]\n"
315 text_strg
+= "[1 color rgbf<0,0,0,1>]\n"
319 if tex
.noise_distortion
== "CELL_NOISE":
320 text_strg
+= " [1 cells scale 0.1\n"
321 if tex
.use_color_ramp
:
322 text_strg
+= export_color_ramp(tex
)
324 text_strg
+= "color_map {\n"
325 text_strg
+= "[0 color rgbt<1,1,1,0>]\n"
326 text_strg
+= "[1 color rgbf<0,0,0,1>]\n"
329 if tex
.noise_distortion
== "VORONOI_CRACKLE":
330 text_strg
+= " [1 crackle scale 0.25\n"
331 if tex
.use_color_ramp
:
332 text_strg
+= export_color_ramp(tex
)
334 text_strg
+= "color_map {\n"
335 text_strg
+= "[0 color rgbt<1,1,1,0>]\n"
336 text_strg
+= "[1 color rgbf<0,0,0,1>]\n"
339 if tex
.noise_distortion
in [
346 text_strg
+= " [1 crackle metric 2.5 scale 0.25 turbulence %.4g\n" % (
349 if tex
.use_color_ramp
:
350 text_strg
+= export_color_ramp(tex
)
352 text_strg
+= "color_map {\n"
353 text_strg
+= "[0 color rgbt<1,1,1,0>]\n"
354 text_strg
+= "[1 color rgbf<0,0,0,1>]\n"
358 text_strg
+= " [1 wrinkles scale 0.25\n"
359 if tex
.use_color_ramp
:
360 text_strg
+= export_color_ramp(tex
)
362 text_strg
+= "color_map {\n"
363 text_strg
+= "[0 color rgbt<1,1,1,0>]\n"
364 text_strg
+= "[1 color rgbf<0,0,0,1>]\n"
369 # ------------------------- EMULATE BLENDER NOISE TEXTURE ------------------------- #
370 if tex
.type == "NOISE":
371 text_strg
+= "cells\n"
372 text_strg
+= "turbulence 3\n"
373 text_strg
+= "omega 3\n"
374 if tex
.use_color_ramp
:
375 text_strg
+= export_color_ramp(tex
)
377 text_strg
+= "color_map {\n"
378 text_strg
+= "[0.75 color rgb<0,0,0,>]\n"
379 text_strg
+= "[1 color rgb<1,1,1,>]\n"
382 # ------------------------- IGNORE OTHER BLENDER TEXTURE ------------------------- #
383 else: # non translated textures
387 text_strg
+= "#declare f%s=\n" % pat_name
388 text_strg
+= "function{pigment{%s}}\n" % pat_name
391 elif pat
.tex_pattern_type
!= "emulator":
392 text_strg
+= "pigment {\n"
393 text_strg
+= "%s\n" % pat
.tex_pattern_type
394 if pat
.tex_pattern_type
== "agate":
395 text_strg
+= "agate_turb %.4g\n" % pat
.modifier_turbulence
396 if pat
.tex_pattern_type
in {"spiral1", "spiral2", "tiling"}:
397 text_strg
+= "%s\n" % pat
.modifier_numbers
398 if pat
.tex_pattern_type
== "quilted":
399 text_strg
+= "control0 %s control1 %s\n" % (
400 pat
.modifier_control0
,
401 pat
.modifier_control1
,
403 if pat
.tex_pattern_type
== "mandel":
404 text_strg
+= "%s exponent %s \n" % (pat
.f_iter
, pat
.f_exponent
)
405 if pat
.tex_pattern_type
== "julia":
406 text_strg
+= "<%.4g, %.4g> %s exponent %s \n" % (
412 if pat
.tex_pattern_type
== "magnet" and pat
.magnet_style
== "mandel":
413 text_strg
+= "%s mandel %s \n" % (pat
.magnet_type
, pat
.f_iter
)
414 if pat
.tex_pattern_type
== "magnet" and pat
.magnet_style
== "julia":
415 text_strg
+= "%s julia <%.4g, %.4g> %s\n" % (
421 if pat
.tex_pattern_type
in {"mandel", "julia", "magnet"}:
422 text_strg
+= "interior %s, %.4g\n" % (pat
.f_ior
, pat
.f_ior_fac
)
423 text_strg
+= "exterior %s, %.4g\n" % (pat
.f_eor
, pat
.f_eor_fac
)
424 if pat
.tex_pattern_type
== "gradient":
425 text_strg
+= "<%s, %s, %s> \n" % (
430 if pat
.tex_pattern_type
== "pavement":
431 num_tiles
= pat
.pave_tiles
433 if pat
.pave_sides
== "4" and pat
.pave_tiles
== 3:
434 num_pattern
= pat
.pave_pat_2
435 if pat
.pave_sides
== "6" and pat
.pave_tiles
== 3:
436 num_pattern
= pat
.pave_pat_3
437 if pat
.pave_sides
== "3" and pat
.pave_tiles
== 4:
438 num_pattern
= pat
.pave_pat_3
439 if pat
.pave_sides
== "3" and pat
.pave_tiles
== 5:
440 num_pattern
= pat
.pave_pat_4
441 if pat
.pave_sides
== "4" and pat
.pave_tiles
== 4:
442 num_pattern
= pat
.pave_pat_5
443 if pat
.pave_sides
== "6" and pat
.pave_tiles
== 4:
444 num_pattern
= pat
.pave_pat_7
445 if pat
.pave_sides
== "4" and pat
.pave_tiles
== 5:
446 num_pattern
= pat
.pave_pat_12
447 if pat
.pave_sides
== "3" and pat
.pave_tiles
== 6:
448 num_pattern
= pat
.pave_pat_12
449 if pat
.pave_sides
== "6" and pat
.pave_tiles
== 5:
450 num_pattern
= pat
.pave_pat_22
451 if pat
.pave_sides
== "4" and pat
.pave_tiles
== 6:
452 num_pattern
= pat
.pave_pat_35
453 if pat
.pave_sides
== "6" and pat
.pave_tiles
== 6:
455 text_strg
+= "number_of_sides %s number_of_tiles %s pattern %s form %s \n" % (
461 # ------------------------- functions ------------------------- #
462 if pat
.tex_pattern_type
== "function":
463 text_strg
+= "{ %s" % pat
.func_list
465 if pat
.func_plus_x
!= "NONE":
466 if pat
.func_plus_x
== "increase":
468 if pat
.func_plus_x
== "plus":
470 text_strg
+= "%.4g" % pat
.func_x
472 if pat
.func_plus_y
!= "NONE":
473 if pat
.func_plus_y
== "increase":
475 if pat
.func_plus_y
== "plus":
477 text_strg
+= "%.4g" % pat
.func_y
479 if pat
.func_plus_z
!= "NONE":
480 if pat
.func_plus_z
== "increase":
482 if pat
.func_plus_z
== "plus":
484 text_strg
+= "%.4g" % pat
.func_z
486 if pat
.func_list
in {
499 "f_kummer_surface_v1",
500 "f_lemniscate_of_gerono",
509 "f_quartic_paraboloid",
517 if pat
.func_list
in {
525 if pat
.func_list
in {
528 "f_hyperbolic_torus",
529 "f_kampyle_of_eudoxus",
531 "f_quartic_cylinder",
535 if pat
.func_list
in {
537 "f_cross_ellipsoids",
539 "f_isect_ellipsoids",
540 "f_kummer_surface_v2",
541 "f_ovals_of_cassini",
547 if pat
.func_list
in {
558 if pat
.func_list
in {
561 "f_folium_surface_2d",
563 "f_kampyle_of_eudoxus_2d",
564 "f_lemniscate_of_gerono_2d",
572 if pat
.func_list
in {
579 if pat
.func_list
== "f_helical_torus":
582 text_strg
+= ",%.4g" % pat
.func_P0
584 text_strg
+= ",%.4g" % pat
.func_P1
586 text_strg
+= ",%.4g" % pat
.func_P2
588 text_strg
+= ",%.4g" % pat
.func_P3
590 text_strg
+= ",%.4g" % pat
.func_P4
592 text_strg
+= ",%.4g" % pat
.func_P5
594 text_strg
+= ",%.4g" % pat
.func_P6
596 text_strg
+= ",%.4g" % pat
.func_P7
597 text_strg
+= ",%.4g" % pat
.func_P8
598 text_strg
+= ",%.4g" % pat
.func_P9
600 # ------------------------- end functions ------------------------- #
601 if pat
.tex_pattern_type
not in {
608 text_strg
+= "color_map {\n"
609 if tex
.use_color_ramp
:
610 for num_color
, el
in enumerate(tex
.color_ramp
.elements
, start
=1):
613 col_r
, col_g
, col_b
, col_a
= col
[0], col
[1], col
[2], 1 - col
[3]
614 if pat
.tex_pattern_type
not in {
621 text_strg
+= "[%.4g color rgbf<%.4g,%.4g,%.4g,%.4g>] \n" % (
628 if pat
.tex_pattern_type
in {"brick", "checker"} and num_color
< 3:
629 text_strg
+= "color rgbf<%.4g,%.4g,%.4g,%.4g> \n" % (
635 if pat
.tex_pattern_type
== "hexagon" and num_color
< 4:
636 text_strg
+= "color rgbf<%.4g,%.4g,%.4g,%.4g> \n" % (
642 if pat
.tex_pattern_type
== "square" and num_color
< 5:
643 text_strg
+= "color rgbf<%.4g,%.4g,%.4g,%.4g> \n" % (
649 if pat
.tex_pattern_type
== "triangular" and num_color
< 7:
650 text_strg
+= "color rgbf<%.4g,%.4g,%.4g,%.4g> \n" % (
657 text_strg
+= "[0 color rgbf<0,0,0,1>]\n"
658 text_strg
+= "[1 color rgbf<1,1,1,0>]\n"
659 if pat
.tex_pattern_type
not in {
667 if pat
.tex_pattern_type
== "brick":
668 text_strg
+= "brick_size <%.4g, %.4g, %.4g> mortar %.4g \n" % (
674 text_strg
+= "%s \n" % mapping_dif
675 text_strg
+= "rotate <%.4g,%.4g,%.4g> \n" % (
680 text_strg
+= "turbulence <%.4g,%.4g,%.4g> \n" % (
681 pat
.warp_turbulence_x
,
682 pat
.warp_turbulence_y
,
683 pat
.warp_turbulence_z
,
685 text_strg
+= "octaves %s \n" % pat
.modifier_octaves
686 text_strg
+= "lambda %.4g \n" % pat
.modifier_lambda
687 text_strg
+= "omega %.4g \n" % pat
.modifier_omega
688 text_strg
+= "frequency %.4g \n" % pat
.modifier_frequency
689 text_strg
+= "phase %.4g \n" % pat
.modifier_phase
691 text_strg
+= "#declare f%s=\n" % pat_name
692 text_strg
+= "function{pigment{%s}}\n" % pat_name