sdforge 0.1.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.
sdforge-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 nassimberrada
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ recursive-include sdforge/glsl *.glsl
sdforge-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,235 @@
1
+ Metadata-Version: 2.4
2
+ Name: sdforge
3
+ Version: 0.1.0
4
+ Summary: A Python library for SDF modeling with real-time GLSL rendering and mesh export.
5
+ Home-page: https://github.com/nassimberrada/sdforge
6
+ Author: nassimberrada
7
+ Classifier: Development Status :: 4 - Beta
8
+ Classifier: Intended Audience :: Developers
9
+ Classifier: Intended Audience :: Science/Research
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Topic :: Multimedia :: Graphics :: 3D Modeling
13
+ Classifier: Topic :: Scientific/Engineering :: Visualization
14
+ Requires-Python: >=3.6
15
+ Description-Content-Type: text/markdown
16
+ License-File: LICENSE
17
+ Requires-Dist: numpy
18
+ Requires-Dist: scikit-image>=0.17
19
+ Requires-Dist: watchdog
20
+ Requires-Dist: moderngl
21
+ Requires-Dist: glfw
22
+ Provides-Extra: gpu
23
+ Provides-Extra: record
24
+ Requires-Dist: imageio; extra == "record"
25
+ Requires-Dist: imageio-ffmpeg; extra == "record"
26
+ Dynamic: author
27
+ Dynamic: classifier
28
+ Dynamic: description
29
+ Dynamic: description-content-type
30
+ Dynamic: home-page
31
+ Dynamic: license-file
32
+ Dynamic: provides-extra
33
+ Dynamic: requires-dist
34
+ Dynamic: requires-python
35
+ Dynamic: summary
36
+
37
+ <p align="center">
38
+ <picture>
39
+ <source srcset="./assets/logo_dark.png" media="(prefers-color-scheme: dark)">
40
+ <source srcset="./assets/logo_light.png" media="(prefers-color-scheme: light)">
41
+ <img src="./assets/logo_light.png" alt="SDForge Logo" height="200">
42
+ </picture>
43
+ </p>
44
+
45
+ SDF Forge is a Python library for creating 3D models using Signed Distance Functions (SDFs). It provides a real-time, interactive rendering experience in a native desktop window, powered by GLSL raymarching.
46
+
47
+ ## Features
48
+
49
+ - **Simple, Pythonic API:** Define complex shapes by combining primitives using standard operators (`|`, `-`, `&`).
50
+ - **Real-time Rendering with Hot-Reloading:** Get instant visual feedback in a lightweight native window powered by `moderngl` and `glfw`.
51
+ - **Mesh Exporting:** Save your creations as `.stl` files for 3D printing or use in other software.
52
+ - **Flexible Scene Construction:** Write custom SDF logic directly in GLSL, easily assign different materials to individual objects, etc.
53
+
54
+ ## Quick Start
55
+
56
+ ```python
57
+ from sdforge import *
58
+
59
+ # A sphere intersected with a box
60
+ f = sphere(1) & box(1.5)
61
+
62
+ # Subtract three cylinders along each axis
63
+ c = cylinder(0.5)
64
+ f -= c.orient(X) | c.orient(Y) | c.orient(Z)
65
+
66
+ # Render a live preview in a native window.
67
+ # With watch=True, the view will update when you save the file.
68
+ f.render(watch=True)
69
+ ```
70
+
71
+ ## Advanced
72
+
73
+ ### Custom GLSL with `Forge`
74
+
75
+ For complex or highly-performant shapes, you can write GLSL code directly. This object integrates perfectly with the rest of the API.
76
+
77
+ ```python
78
+ from sdforge import *
79
+
80
+ # A standard library primitive
81
+ s = sphere(1.2)
82
+
83
+ # A custom shape defined with GLSL
84
+ # 'p' is the vec3 point in space
85
+ custom_twist = Forge("""
86
+ float k = 10.0;
87
+ float c = cos(k*p.y);
88
+ float s = sin(k*p.y);
89
+ mat2 m = mat2(c,-s,s,c);
90
+ vec3 q = vec3(m*p.xz,p.y);
91
+ return length(q) - 0.5;
92
+ """)
93
+
94
+ f = s - custom_twist
95
+
96
+ # Rendering and saving works out of the box
97
+ f.render()
98
+ f.save('example_forge.stl')
99
+ ```
100
+
101
+ ### Camera Controls
102
+
103
+ You can override the default mouse-orbit camera to create cinematic animations or set a static viewpoint. The `Camera` object accepts GLSL expressions for its position and target, which will be updated every frame.
104
+
105
+ To use a custom camera, have your `main` function return a tuple containing your `SDFObject` and your `Camera` object.
106
+
107
+ ```python
108
+ from sdforge import *
109
+
110
+ def main():
111
+ # A simple shape to look at
112
+ shape = sphere(1) & box(1.5)
113
+
114
+ # An animated camera that orbits around the origin
115
+ cam = Camera(
116
+ position=(
117
+ "5.0 * sin(u_time * 0.5)",
118
+ "3.0",
119
+ "5.0 * cos(u_time * 0.5)"
120
+ ),
121
+ target=(0, 0, 0) # Look at the center
122
+ )
123
+
124
+ # For hot-reloading to work, the main function must return the shape and camera
125
+ return shape, cam
126
+
127
+ if __name__ == '__main__':
128
+ sdf_object, camera_object = main()
129
+ sdf_object.render(camera=camera_object, watch=True)
130
+ ```
131
+
132
+ ### Light Controls
133
+
134
+ You can customize the scene's lighting, including light position, ambient light, and shadow softness. The `Light` object accepts GLSL expressions for its properties, which will be updated every frame.
135
+
136
+ To use custom lighting, your `main` function can return a tuple containing your `SDFObject`, your `Camera` object, and your `Light` object.
137
+
138
+ ```python
139
+ from sdforge import *
140
+
141
+ # A simple shape to look at
142
+ shape = sphere(1) - cylinder(0.5)
143
+
144
+ # A standard orbiting camera
145
+ cam = Camera(position=("5.0 * sin(u_time * 0.5)", "3.0", "5.0 * cos(u_time * 0.5)"))
146
+
147
+ # An animated light source with soft shadows
148
+ lighting = Light(
149
+ position=(
150
+ "8.0 * sin(u_time * 0.3)",
151
+ "5.0",
152
+ "8.0 * cos(u_time * 0.3)"
153
+ ),
154
+ ambient_strength=0.05,
155
+ shadow_softness="8.0 + 7.0 * sin(u_time * 0.7)"
156
+ )
157
+
158
+ # For hot-reloading, return all scene objects from main
159
+ def main():
160
+ return shape, cam, lighting
161
+
162
+ if __name__ == '__main__':
163
+ sdf_obj, cam_obj, light_obj = main()
164
+ sdf_obj.render(camera=cam_obj, lighting=light_obj, watch=True)
165
+ ```
166
+
167
+ ### Material Assignment
168
+
169
+ You can assign a unique color to any object or group of objects using the `.color()` method. The renderer will automatically handle combining the shapes and their materials correctly.
170
+
171
+ ```python
172
+ from sdforge import *
173
+
174
+ # Define shapes with different colors
175
+ red_sphere = sphere(0.8).color(1, 0, 0)
176
+ blue_box = box(1.2).color(0, 0, 1)
177
+
178
+ # Combine colored objects
179
+ # The union operation will correctly preserve the material of the closest surface
180
+ model = red_sphere | blue_box.translate(X * 0.5)
181
+
182
+ # You can also set a custom background color
183
+ model.render(bg_color=(0.1, 0.2, 0.3))
184
+ ```
185
+
186
+ ### Render to File
187
+
188
+ You can save any static (non-animated) SDF model to an `.stl` file for 3D printing or use in other software. The `.save()` method uses the Marching Cubes algorithm to generate a mesh from the SDF.
189
+
190
+ ```python
191
+ from sdforge import *
192
+
193
+ # A sphere intersected with a box
194
+ f = sphere(1) & box(1.5)
195
+
196
+ # Subtract three cylinders along each axis
197
+ c = cylinder(0.5)
198
+ f -= c.orient(X) | c.orient(Y) | c.orient(Z)
199
+
200
+ # Save the model to a file
201
+ f.save('model.stl', samples=2**24) # Higher samples = more detail
202
+ ```
203
+
204
+ ### Record Render
205
+
206
+ You can record the interactive session to an MP4 video file by passing the `record` argument to the `.render()` method. This requires the optional `[record]` dependencies.
207
+
208
+ ```python
209
+ from sdforge import *
210
+
211
+ # Animate a box size using the u_time uniform
212
+ f = box(size="0.5 + 0.3 * sin(u_time)")
213
+
214
+ # Render and record the output to a video file.
215
+ # Close the window to stop the recording.
216
+ f.render(record="animated_box.mp4")
217
+ ```
218
+
219
+ ## Installation
220
+
221
+ The library and its core dependencies can be installed using pip:
222
+
223
+ ```bash
224
+ pip install sdforge
225
+ ```
226
+
227
+ To enable optional video recording features, install the `[record]` extra:
228
+
229
+ ```bash
230
+ pip install sdforge[record]
231
+ ```
232
+
233
+ ## Acknowledgements
234
+
235
+ This project is inspired by the simplicity and elegant API of Michael Fogleman's [fogleman/sdf](https://github.com/fogleman/sdf) library. SDF Forge aims to build on that foundation by adding a real-time, interactive GLSL-powered renderer.
@@ -0,0 +1,199 @@
1
+ <p align="center">
2
+ <picture>
3
+ <source srcset="./assets/logo_dark.png" media="(prefers-color-scheme: dark)">
4
+ <source srcset="./assets/logo_light.png" media="(prefers-color-scheme: light)">
5
+ <img src="./assets/logo_light.png" alt="SDForge Logo" height="200">
6
+ </picture>
7
+ </p>
8
+
9
+ SDF Forge is a Python library for creating 3D models using Signed Distance Functions (SDFs). It provides a real-time, interactive rendering experience in a native desktop window, powered by GLSL raymarching.
10
+
11
+ ## Features
12
+
13
+ - **Simple, Pythonic API:** Define complex shapes by combining primitives using standard operators (`|`, `-`, `&`).
14
+ - **Real-time Rendering with Hot-Reloading:** Get instant visual feedback in a lightweight native window powered by `moderngl` and `glfw`.
15
+ - **Mesh Exporting:** Save your creations as `.stl` files for 3D printing or use in other software.
16
+ - **Flexible Scene Construction:** Write custom SDF logic directly in GLSL, easily assign different materials to individual objects, etc.
17
+
18
+ ## Quick Start
19
+
20
+ ```python
21
+ from sdforge import *
22
+
23
+ # A sphere intersected with a box
24
+ f = sphere(1) & box(1.5)
25
+
26
+ # Subtract three cylinders along each axis
27
+ c = cylinder(0.5)
28
+ f -= c.orient(X) | c.orient(Y) | c.orient(Z)
29
+
30
+ # Render a live preview in a native window.
31
+ # With watch=True, the view will update when you save the file.
32
+ f.render(watch=True)
33
+ ```
34
+
35
+ ## Advanced
36
+
37
+ ### Custom GLSL with `Forge`
38
+
39
+ For complex or highly-performant shapes, you can write GLSL code directly. This object integrates perfectly with the rest of the API.
40
+
41
+ ```python
42
+ from sdforge import *
43
+
44
+ # A standard library primitive
45
+ s = sphere(1.2)
46
+
47
+ # A custom shape defined with GLSL
48
+ # 'p' is the vec3 point in space
49
+ custom_twist = Forge("""
50
+ float k = 10.0;
51
+ float c = cos(k*p.y);
52
+ float s = sin(k*p.y);
53
+ mat2 m = mat2(c,-s,s,c);
54
+ vec3 q = vec3(m*p.xz,p.y);
55
+ return length(q) - 0.5;
56
+ """)
57
+
58
+ f = s - custom_twist
59
+
60
+ # Rendering and saving works out of the box
61
+ f.render()
62
+ f.save('example_forge.stl')
63
+ ```
64
+
65
+ ### Camera Controls
66
+
67
+ You can override the default mouse-orbit camera to create cinematic animations or set a static viewpoint. The `Camera` object accepts GLSL expressions for its position and target, which will be updated every frame.
68
+
69
+ To use a custom camera, have your `main` function return a tuple containing your `SDFObject` and your `Camera` object.
70
+
71
+ ```python
72
+ from sdforge import *
73
+
74
+ def main():
75
+ # A simple shape to look at
76
+ shape = sphere(1) & box(1.5)
77
+
78
+ # An animated camera that orbits around the origin
79
+ cam = Camera(
80
+ position=(
81
+ "5.0 * sin(u_time * 0.5)",
82
+ "3.0",
83
+ "5.0 * cos(u_time * 0.5)"
84
+ ),
85
+ target=(0, 0, 0) # Look at the center
86
+ )
87
+
88
+ # For hot-reloading to work, the main function must return the shape and camera
89
+ return shape, cam
90
+
91
+ if __name__ == '__main__':
92
+ sdf_object, camera_object = main()
93
+ sdf_object.render(camera=camera_object, watch=True)
94
+ ```
95
+
96
+ ### Light Controls
97
+
98
+ You can customize the scene's lighting, including light position, ambient light, and shadow softness. The `Light` object accepts GLSL expressions for its properties, which will be updated every frame.
99
+
100
+ To use custom lighting, your `main` function can return a tuple containing your `SDFObject`, your `Camera` object, and your `Light` object.
101
+
102
+ ```python
103
+ from sdforge import *
104
+
105
+ # A simple shape to look at
106
+ shape = sphere(1) - cylinder(0.5)
107
+
108
+ # A standard orbiting camera
109
+ cam = Camera(position=("5.0 * sin(u_time * 0.5)", "3.0", "5.0 * cos(u_time * 0.5)"))
110
+
111
+ # An animated light source with soft shadows
112
+ lighting = Light(
113
+ position=(
114
+ "8.0 * sin(u_time * 0.3)",
115
+ "5.0",
116
+ "8.0 * cos(u_time * 0.3)"
117
+ ),
118
+ ambient_strength=0.05,
119
+ shadow_softness="8.0 + 7.0 * sin(u_time * 0.7)"
120
+ )
121
+
122
+ # For hot-reloading, return all scene objects from main
123
+ def main():
124
+ return shape, cam, lighting
125
+
126
+ if __name__ == '__main__':
127
+ sdf_obj, cam_obj, light_obj = main()
128
+ sdf_obj.render(camera=cam_obj, lighting=light_obj, watch=True)
129
+ ```
130
+
131
+ ### Material Assignment
132
+
133
+ You can assign a unique color to any object or group of objects using the `.color()` method. The renderer will automatically handle combining the shapes and their materials correctly.
134
+
135
+ ```python
136
+ from sdforge import *
137
+
138
+ # Define shapes with different colors
139
+ red_sphere = sphere(0.8).color(1, 0, 0)
140
+ blue_box = box(1.2).color(0, 0, 1)
141
+
142
+ # Combine colored objects
143
+ # The union operation will correctly preserve the material of the closest surface
144
+ model = red_sphere | blue_box.translate(X * 0.5)
145
+
146
+ # You can also set a custom background color
147
+ model.render(bg_color=(0.1, 0.2, 0.3))
148
+ ```
149
+
150
+ ### Render to File
151
+
152
+ You can save any static (non-animated) SDF model to an `.stl` file for 3D printing or use in other software. The `.save()` method uses the Marching Cubes algorithm to generate a mesh from the SDF.
153
+
154
+ ```python
155
+ from sdforge import *
156
+
157
+ # A sphere intersected with a box
158
+ f = sphere(1) & box(1.5)
159
+
160
+ # Subtract three cylinders along each axis
161
+ c = cylinder(0.5)
162
+ f -= c.orient(X) | c.orient(Y) | c.orient(Z)
163
+
164
+ # Save the model to a file
165
+ f.save('model.stl', samples=2**24) # Higher samples = more detail
166
+ ```
167
+
168
+ ### Record Render
169
+
170
+ You can record the interactive session to an MP4 video file by passing the `record` argument to the `.render()` method. This requires the optional `[record]` dependencies.
171
+
172
+ ```python
173
+ from sdforge import *
174
+
175
+ # Animate a box size using the u_time uniform
176
+ f = box(size="0.5 + 0.3 * sin(u_time)")
177
+
178
+ # Render and record the output to a video file.
179
+ # Close the window to stop the recording.
180
+ f.render(record="animated_box.mp4")
181
+ ```
182
+
183
+ ## Installation
184
+
185
+ The library and its core dependencies can be installed using pip:
186
+
187
+ ```bash
188
+ pip install sdforge
189
+ ```
190
+
191
+ To enable optional video recording features, install the `[record]` extra:
192
+
193
+ ```bash
194
+ pip install sdforge[record]
195
+ ```
196
+
197
+ ## Acknowledgements
198
+
199
+ This project is inspired by the simplicity and elegant API of Michael Fogleman's [fogleman/sdf](https://github.com/fogleman/sdf) library. SDF Forge aims to build on that foundation by adding a real-time, interactive GLSL-powered renderer.
@@ -0,0 +1,37 @@
1
+ from .api import (
2
+ # Base class (for type hinting or extension)
3
+ SDFObject,
4
+
5
+ # Primitives
6
+ sphere,
7
+ box,
8
+ rounded_box,
9
+ cylinder,
10
+ torus,
11
+ capsule,
12
+ cone,
13
+ plane,
14
+ hex_prism,
15
+ octahedron,
16
+ ellipsoid,
17
+
18
+ # Custom GLSL
19
+ Forge,
20
+
21
+ # Camera
22
+ Camera,
23
+
24
+ # Light
25
+ Light,
26
+
27
+ # Constants
28
+ X, Y, Z,
29
+ )
30
+
31
+ # By attaching render and save to the base class, any created object
32
+ # can call them directly, e.g., sphere(1).render()
33
+ from .render import render
34
+ from .mesh import save
35
+ from .api import SDFObject
36
+ SDFObject.render = render
37
+ SDFObject.save = save