fractex 0.1.2__tar.gz → 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. {fractex-0.1.2/fractex.egg-info → fractex-0.2.0}/PKG-INFO +1 -1
  2. {fractex-0.1.2 → fractex-0.2.0}/fractex/cli.py +1 -0
  3. {fractex-0.1.2 → fractex-0.2.0}/fractex/examples/__init__.py +1 -0
  4. {fractex-0.1.2 → fractex-0.2.0}/fractex/examples/architecture_pattern.py +1 -0
  5. fractex-0.2.0/fractex/examples/fire_flame.py +141 -0
  6. {fractex-0.1.2 → fractex-0.2.0/fractex.egg-info}/PKG-INFO +1 -1
  7. {fractex-0.1.2 → fractex-0.2.0}/fractex.egg-info/SOURCES.txt +1 -0
  8. {fractex-0.1.2 → fractex-0.2.0}/pyproject.toml +1 -1
  9. {fractex-0.1.2 → fractex-0.2.0}/LICENSE +0 -0
  10. {fractex-0.1.2 → fractex-0.2.0}/MANIFEST.in +0 -0
  11. {fractex-0.1.2 → fractex-0.2.0}/README.md +0 -0
  12. {fractex-0.1.2 → fractex-0.2.0}/fractex/3d.py +0 -0
  13. {fractex-0.1.2 → fractex-0.2.0}/fractex/__init__.py +0 -0
  14. {fractex-0.1.2 → fractex-0.2.0}/fractex/advanced.py +0 -0
  15. {fractex-0.1.2 → fractex-0.2.0}/fractex/core.py +0 -0
  16. {fractex-0.1.2 → fractex-0.2.0}/fractex/dynamic_textures_3d.py +0 -0
  17. {fractex-0.1.2 → fractex-0.2.0}/fractex/examples/3d.py +0 -0
  18. {fractex-0.1.2 → fractex-0.2.0}/fractex/examples/3d_integration.py +0 -0
  19. {fractex-0.1.2 → fractex-0.2.0}/fractex/examples/3d_integration_2d.py +0 -0
  20. {fractex-0.1.2 → fractex-0.2.0}/fractex/examples/_output.py +0 -0
  21. {fractex-0.1.2 → fractex-0.2.0}/fractex/examples/atmosphere.py +0 -0
  22. {fractex-0.1.2 → fractex-0.2.0}/fractex/examples/composite_material.py +0 -0
  23. {fractex-0.1.2 → fractex-0.2.0}/fractex/examples/crystal_cave.py +0 -0
  24. {fractex-0.1.2 → fractex-0.2.0}/fractex/examples/custom_pattern.py +0 -0
  25. {fractex-0.1.2 → fractex-0.2.0}/fractex/examples/game_integration.py +0 -0
  26. {fractex-0.1.2 → fractex-0.2.0}/fractex/examples/game_texture.py +0 -0
  27. {fractex-0.1.2 → fractex-0.2.0}/fractex/examples/integration.py +0 -0
  28. {fractex-0.1.2 → fractex-0.2.0}/fractex/examples/physic_integration.py +0 -0
  29. {fractex-0.1.2 → fractex-0.2.0}/fractex/examples/splash.py +0 -0
  30. {fractex-0.1.2 → fractex-0.2.0}/fractex/examples/terrain.py +0 -0
  31. {fractex-0.1.2 → fractex-0.2.0}/fractex/examples/underwater.py +0 -0
  32. {fractex-0.1.2 → fractex-0.2.0}/fractex/examples/underwater_volkano.py +0 -0
  33. {fractex-0.1.2 → fractex-0.2.0}/fractex/geometric_patterns_3d.py +0 -0
  34. {fractex-0.1.2 → fractex-0.2.0}/fractex/interactive.py +0 -0
  35. {fractex-0.1.2 → fractex-0.2.0}/fractex/simplex_noise.py +0 -0
  36. {fractex-0.1.2 → fractex-0.2.0}/fractex/texture_blending.py +0 -0
  37. {fractex-0.1.2 → fractex-0.2.0}/fractex/volume_scattering.py +0 -0
  38. {fractex-0.1.2 → fractex-0.2.0}/fractex/volume_textures.py +0 -0
  39. {fractex-0.1.2 → fractex-0.2.0}/fractex.egg-info/dependency_links.txt +0 -0
  40. {fractex-0.1.2 → fractex-0.2.0}/fractex.egg-info/entry_points.txt +0 -0
  41. {fractex-0.1.2 → fractex-0.2.0}/fractex.egg-info/requires.txt +0 -0
  42. {fractex-0.1.2 → fractex-0.2.0}/fractex.egg-info/top_level.txt +0 -0
  43. {fractex-0.1.2 → fractex-0.2.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fractex
3
- Version: 0.1.2
3
+ Version: 0.2.0
4
4
  Summary: Fractal texture engine for procedural and infinite-detail textures.
5
5
  Author-email: Timur Isanov <tisanov@yahoo.com>
6
6
  License: MIT License
@@ -11,6 +11,7 @@ from typing import List
11
11
  def _examples() -> List[str]:
12
12
  return [
13
13
  "splash",
14
+ "fire_flame",
14
15
  "custom_pattern",
15
16
  "architecture_pattern",
16
17
  "composite_material",
@@ -10,6 +10,7 @@ from typing import List, Optional
10
10
  def list_examples() -> List[str]:
11
11
  return [
12
12
  "splash",
13
+ "fire_flame",
13
14
  "custom_pattern",
14
15
  "architecture_pattern",
15
16
  "composite_material",
@@ -2,6 +2,7 @@
2
2
  import sys
3
3
  from pathlib import Path
4
4
  import argparse
5
+ import numpy as np
5
6
 
6
7
  ROOT = Path(__file__).resolve().parents[2]
7
8
  if str(ROOT) not in sys.path:
@@ -0,0 +1,141 @@
1
+ import sys
2
+ from pathlib import Path
3
+ import argparse
4
+ import numpy as np
5
+
6
+ ROOT = Path(__file__).resolve().parents[2]
7
+ if str(ROOT) not in sys.path:
8
+ sys.path.insert(0, str(ROOT))
9
+ EXAMPLES_DIR = Path(__file__).resolve().parent
10
+ if str(EXAMPLES_DIR) not in sys.path:
11
+ sys.path.insert(0, str(EXAMPLES_DIR))
12
+
13
+ from fractex.simplex_noise import SimplexNoise
14
+ from fractex.interactive import add_interactive_args, InteractiveConfig, run_interactive
15
+ from _output import save_ppm
16
+
17
+
18
+ def _render_flame(t: float, w: int, h: int, noise: SimplexNoise) -> np.ndarray:
19
+ x = np.linspace(-1.0, 1.0, w)
20
+ y = np.linspace(0.0, 2.0, h)
21
+ xx, yy = np.meshgrid(x, y)
22
+ taper = 1.0 - 0.5 * np.clip(yy / 2.0, 0, 1)
23
+ xx_t = xx * taper
24
+ zz = np.ones_like(xx) * (t * 0.15)
25
+
26
+ base = noise.noise_3d(xx_t * 1.5, yy * 1.2, zz)
27
+ detail = noise.noise_3d(xx_t * 5.0, yy * 4.0, zz * 1.8)
28
+ micro = noise.noise_3d(xx_t * 14.0, yy * 10.0, zz * 5.0)
29
+ warp = noise.noise_3d(xx_t * 1.2, yy * 1.0, zz * 0.8)
30
+ turbulence = base * 0.45 + detail * 0.3 + micro * 0.2 + warp * 0.05
31
+ turbulence = (turbulence + 1) * 0.5
32
+
33
+ # Центральное ядро + вытянутая форма вверх (с повышенным контрастом)
34
+ core = np.exp(-((xx_t * 1.8) ** 2)) * np.clip(2.6 - yy, 0, 1)
35
+ # Языки с резкими краями (степень для контраста)
36
+ tongues_raw = np.exp(-((xx_t * 5.0 + warp * 1.6) ** 2)) * np.clip(3.0 - yy, 0, 1)
37
+ tongues = np.clip(tongues_raw * 1.5 - 0.2, 0, 1) ** 0.7
38
+ lobe_raw = np.exp(-((xx_t * 6.0) ** 2)) * np.clip(3.2 - yy, 0, 1) * (0.6 + 0.4 * np.sin(t * 0.7 + yy * 4.0))
39
+ lobe = np.clip(lobe_raw * 1.4 - 0.15, 0, 1) ** 0.8
40
+ jets_raw = np.clip(turbulence - 0.15, 0, 1) * np.exp(-((xx_t * 7.0 + warp * 1.8) ** 2)) * np.clip(3.4 - yy, 0, 1)
41
+ jets = np.clip(jets_raw * 1.6 - 0.1, 0, 1) ** 0.6
42
+ rips = np.clip(turbulence * 1.4 - 0.35, 0, 1) * np.exp(-((xx_t * 4.2) ** 2)) * np.clip(2.2 - yy, 0, 1)
43
+
44
+ # Усиленные языки у основания (резкие)
45
+ base_tongues_raw = np.exp(-((xx_t * 3.5 + warp * 2.0) ** 2)) * np.clip(1.0 - yy * 0.6, 0, 1)
46
+ base_tongues = np.clip(base_tongues_raw * 1.5 - 0.15, 0, 1) ** 0.7
47
+ base_flicker = (0.7 + 0.3 * np.sin(t * 2.5 + xx * 8.0)) * np.clip(0.8 - yy, 0, 1)
48
+ base_texture = np.clip(detail * 0.8 + micro * 0.4, 0, 1) * np.exp(-((xx_t * 2.0) ** 2)) * np.clip(0.6 - yy * 0.5, 0, 1)
49
+
50
+ # Языки пламени веером от центра основания к краям
51
+ yy_safe = np.maximum(yy, 0.05) # избегаем деления на 0
52
+ # Больше языков под меньшими углами (более вертикальные)
53
+ tongue_angles = [-0.2, -0.13, -0.07, 0.0, 0.07, 0.13, 0.2] # 7 языков, узкий веер
54
+ tongues_radial = np.zeros_like(xx)
55
+ for i, ta in enumerate(tongue_angles):
56
+ # Ось языка с динамическим колебанием
57
+ wobble = noise.noise_3d(np.full_like(xx, i * 0.7), yy * 1.5 - t * 0.6, zz) * 0.08
58
+ tongue_axis = yy_safe * (ta + wobble)
59
+ dist_from_axis = np.abs(xx_t - tongue_axis)
60
+ # Ширина: больше у основания, сужается вверх
61
+ width = 0.10 * np.clip(1.0 - yy * 0.35, 0.25, 1.0)
62
+ tongue_shape = np.exp(-((dist_from_axis / width) ** 2))
63
+ # Контрастность: резкие края
64
+ tongue_shape = np.clip(tongue_shape * 1.5 - 0.2, 0, 1) ** 0.7
65
+ # Яркость: сильнее у основания, центральный язык ярче
66
+ center_boost = 1.0 + 0.4 * np.exp(-(ta * 8) ** 2) # центр ярче
67
+ brightness = np.clip(2.0 - yy * 1.0, 0, 1) * (0.8 + 0.2 * np.sin(t * 2.0 + i * 1.0)) * center_boost
68
+ tongues_radial += tongue_shape * brightness
69
+ tongues_radial = np.clip(tongues_radial * 0.6, 0, 1)
70
+
71
+ flame = np.clip(core * (0.2 + 1.0 * turbulence) + tongues * 1.0 + lobe * 0.7 + jets * 0.7 + rips * 0.4 + base_tongues * 0.8 + base_flicker * 0.4 + base_texture * 0.5 + tongues_radial * 0.7, 0, 1)
72
+ flame = np.clip((flame - 0.1) * 1.6, 0, 1)
73
+
74
+ # Подсветка ядра
75
+ core_glow = np.exp(-((xx_t * 3.2) ** 2 + (yy * 1.6) ** 2)) * np.clip(1.6 - yy, 0, 1)
76
+
77
+ # Дым: только в верхней части (выше yy=1.0) - полностью чистый низ
78
+ smoke_vertical = np.clip((yy - 1.0) * 2.0, 0, 1) # маска: 0 внизу, 1 вверху
79
+ smoke = np.clip((yy - 1.5) * 0.7, 0, 1) * (0.2 + 0.5 * turbulence)
80
+ side_mask = np.clip((np.abs(xx) * 1.8 - 0.5), 0, 1)
81
+ smoke = smoke * np.exp(-((xx_t * 1.5 + warp * 0.6) ** 2)) * side_mask
82
+ trail = np.exp(-((xx_t * 0.8 + warp * 0.6) ** 2)) * np.clip(yy - 1.2, 0, 1)
83
+ trail = trail * (0.3 + 0.5 * turbulence) * (0.5 + 0.5 * np.sin(t * 0.3 + yy * 1.5))
84
+ smoke = np.clip((smoke + trail * 0.4) * smoke_vertical, 0, 1)
85
+
86
+ # Искры: у основания без маски, выше - только по краям
87
+ spark_mask = np.clip(micro - 0.7, 0, 1)
88
+ edge = np.clip(np.abs(xx_t) * 2.0, 0, 1)
89
+ bottom_zone = np.clip(1.0 - yy, 0, 1)
90
+ sparks = spark_mask ** 2 * (bottom_zone * 1.2 + (1 - bottom_zone) * edge * 0.5)
91
+
92
+ rgb = np.full((h, w, 3), np.array([0.55, 0.27, 0.20], dtype=np.float32), dtype=np.float32)
93
+ heat = np.clip(flame * 1.2, 0, 1)
94
+
95
+ # Температурный градиент: краснее/оранжевее у основания, белее к ядру
96
+ vertical = np.clip(1.2 - yy, 0, 1)
97
+ temp = np.clip(vertical * 0.6 + heat * 0.7, 0, 1)
98
+ cold_color = np.array([1.0, 0.35, 0.02], dtype=np.float32) # более насыщенный оранжево-красный
99
+ hot_color = np.array([1.0, 0.92, 0.8], dtype=np.float32)
100
+ temp_rgb = cold_color * (1 - temp)[..., None] + hot_color * temp[..., None]
101
+ base_boost = np.clip(1.0 - yy * 0.3, 0.75, 1.0)
102
+ base_heat = np.clip(1.0 - yy * 0.5, 0, 1) * np.exp(-((xx_t * 1.8) ** 2))
103
+ # Дополнительная оранжевая текстура у основания (усилена)
104
+ orange_base = np.clip(detail * 0.5 + 0.5, 0, 1) * np.clip(0.8 - yy * 0.45, 0, 1) * np.exp(-((xx_t * 1.5) ** 2))
105
+ # Красное свечение у самого основания
106
+ red_base = np.clip(0.5 - yy * 0.6, 0, 1) * np.exp(-((xx_t * 1.2) ** 2)) * (0.7 + 0.3 * turbulence)
107
+
108
+ core_boost = 1.0 + 0.5 * core_glow
109
+ core_ripple = 0.85 + 0.15 * np.sin(t * 1.4 + (xx_t + yy) * 3.5) * core_glow
110
+ rgb[..., 0] = np.clip(temp_rgb[..., 0] * heat * core_boost * core_ripple * (1.15 * base_boost) + base_heat * 0.55 + orange_base * 0.7 + red_base * 0.5 + sparks * 1.6 + core_glow * 0.35, 0, 1)
111
+ rgb[..., 1] = np.clip(temp_rgb[..., 1] * heat * core_boost * core_ripple * (1.08 * base_boost) + base_heat * 0.35 + orange_base * 0.35 + red_base * 0.15 + sparks * 0.8 + core_glow * 0.2, 0, 1)
112
+ rgb[..., 2] = np.clip(temp_rgb[..., 2] * heat * (0.9 + 0.3 * core_glow) * core_ripple * (0.95 * base_boost) + base_heat * 0.03 + core_glow * 0.06, 0, 1)
113
+
114
+ # Добавляем дым как серо-синий слой
115
+ rgb[..., 0] = np.clip(rgb[..., 0] * (1 - smoke) + smoke * 0.3, 0, 1)
116
+ rgb[..., 1] = np.clip(rgb[..., 1] * (1 - smoke) + smoke * 0.35, 0, 1)
117
+ rgb[..., 2] = np.clip(rgb[..., 2] * (1 - smoke) + smoke * 0.4, 0, 1)
118
+ return rgb
119
+
120
+
121
+ def main():
122
+ parser = argparse.ArgumentParser(description="Fire flame example")
123
+ add_interactive_args(parser)
124
+ args = parser.parse_args()
125
+
126
+ noise = SimplexNoise(seed=42)
127
+
128
+ if args.interactive:
129
+ config = InteractiveConfig.from_args(args, title="fractex")
130
+
131
+ def render_frame(t, w, h):
132
+ return _render_flame(t, w, h, noise)
133
+
134
+ run_interactive(render_frame, config)
135
+ else:
136
+ image = _render_flame(0.0, 512, 512, noise)
137
+ save_ppm(image, EXAMPLES_DIR / "output" / "fire_flame.ppm", stretch=True)
138
+
139
+
140
+ if __name__ == "__main__":
141
+ main()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fractex
3
- Version: 0.1.2
3
+ Version: 0.2.0
4
4
  Summary: Fractal texture engine for procedural and infinite-detail textures.
5
5
  Author-email: Timur Isanov <tisanov@yahoo.com>
6
6
  License: MIT License
@@ -30,6 +30,7 @@ fractex/examples/atmosphere.py
30
30
  fractex/examples/composite_material.py
31
31
  fractex/examples/crystal_cave.py
32
32
  fractex/examples/custom_pattern.py
33
+ fractex/examples/fire_flame.py
33
34
  fractex/examples/game_integration.py
34
35
  fractex/examples/game_texture.py
35
36
  fractex/examples/integration.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "fractex"
7
- version = "0.1.2"
7
+ version = "0.2.0"
8
8
  description = "Fractal texture engine for procedural and infinite-detail textures."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes