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 +21 -0
- sdforge-0.1.0/MANIFEST.in +1 -0
- sdforge-0.1.0/PKG-INFO +235 -0
- sdforge-0.1.0/README.md +199 -0
- sdforge-0.1.0/sdforge/__init__.py +37 -0
- sdforge-0.1.0/sdforge/api.py +554 -0
- sdforge-0.1.0/sdforge/glsl/scene/camera.glsl +25 -0
- sdforge-0.1.0/sdforge/glsl/scene/lighting.glsl +24 -0
- sdforge-0.1.0/sdforge/glsl/scene/raymarching.glsl +25 -0
- sdforge-0.1.0/sdforge/glsl/sdf/operations.glsl +40 -0
- sdforge-0.1.0/sdforge/glsl/sdf/primitives.glsl +79 -0
- sdforge-0.1.0/sdforge/glsl/sdf/transforms.glsl +46 -0
- sdforge-0.1.0/sdforge/mesh.py +95 -0
- sdforge-0.1.0/sdforge/render.py +415 -0
- sdforge-0.1.0/sdforge.egg-info/PKG-INFO +235 -0
- sdforge-0.1.0/sdforge.egg-info/SOURCES.txt +19 -0
- sdforge-0.1.0/sdforge.egg-info/dependency_links.txt +1 -0
- sdforge-0.1.0/sdforge.egg-info/requires.txt +11 -0
- sdforge-0.1.0/sdforge.egg-info/top_level.txt +1 -0
- sdforge-0.1.0/setup.cfg +4 -0
- sdforge-0.1.0/setup.py +37 -0
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.
|
sdforge-0.1.0/README.md
ADDED
|
@@ -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
|