craphics 0.0.1__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.
craphics-0.0.1/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Moinak Debnath
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,340 @@
1
+ Metadata-Version: 2.4
2
+ Name: craphics
3
+ Version: 0.0.1
4
+ Summary: A small Python Library for CPU - rendered graphics
5
+ Author: Moinak Debnath
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/findstring/craphics
8
+ Project-URL: Repository, https://github.com/findstring/craphics
9
+ Project-URL: Issues, https://github.com/findstring/craphics/issues
10
+ Keywords: graphics,cpu,rendering,tkinter,math
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Topic :: Multimedia :: Graphics
14
+ Classifier: Topic :: Multimedia :: Graphics :: 3D Modeling
15
+ Requires-Python: >=3.9
16
+ Description-Content-Type: text/markdown
17
+ License-File: LICENSE
18
+ Dynamic: license-file
19
+
20
+ # Craphics
21
+
22
+ A small and lightweight Python 3D graphics module built using Python's standard libraries **`tkinter`**, **`math`**, and **`time`**.
23
+
24
+ Craphics provides basic 3D rendering with perspective projection, camera movement, mouse-controlled rotation, triangle rendering, and `.obj` model loading.
25
+
26
+ > **Version:** `v0.0.1`
27
+
28
+ ## Features
29
+
30
+ * 🖥️ Tkinter-based rendering
31
+ * 📐 Basic 3D perspective projection
32
+ * 🎥 Movable camera
33
+ * 🖱️ Mouse-controlled camera rotation
34
+ * 🔺 Triangle-based object rendering
35
+ * 📦 Wavefront `.obj` file loading
36
+ * 👁️ Near and far rendering planes
37
+ * 🎨 Custom object fill and outline colors
38
+ * 📊 Optional rendering logs
39
+ * ⚙️ Configurable FPS and mouse sensitivity
40
+ * 📚 Uses only Python standard libraries
41
+
42
+ ## Installation
43
+
44
+ Install Craphics using `pip`:
45
+
46
+ ```bash
47
+ pip install craphics
48
+ ```
49
+
50
+ ## Requirements
51
+
52
+ Craphics is built using Python's standard library:
53
+
54
+ * `tkinter`
55
+ * `math`
56
+ * `time`
57
+
58
+ No additional Python dependencies are required.
59
+
60
+ > **Note:** Your Python installation must have Tkinter available.
61
+
62
+ ## Quick Start
63
+
64
+ ```python
65
+ import tkinter as tk
66
+ from craphics import CRAPHICS
67
+
68
+ window = tk.Tk()
69
+ window.title("Craphics Demo")
70
+ window.geometry("800x600")
71
+
72
+ graphics = CRAPHICS(
73
+ window=window,
74
+ BG="black",
75
+ FOCAL_LENGTH=500,
76
+ CAMERA_DISTANCE=5,
77
+ RENDER_DISTANCE=1000,
78
+ SENSITIVITY=0.005,
79
+ FPS=60,
80
+ LOG=True
81
+ )
82
+
83
+ window.mainloop()
84
+ ```
85
+
86
+ ## Controls
87
+
88
+ | Key / Input | Action |
89
+ | ------------ | -------------------- |
90
+ | `W` | Move camera forward |
91
+ | `S` | Move camera backward |
92
+ | `A` | Move camera left |
93
+ | `D` | Move camera right |
94
+ | `Space` | Move camera upward |
95
+ | `Left Shift` | Move camera downward |
96
+ | Mouse | Rotate camera |
97
+
98
+ The mouse cursor is hidden while using the Craphics canvas.
99
+
100
+ ## API
101
+
102
+ ### `CRAPHICS()`
103
+
104
+ Creates a Craphics renderer inside the supplied Tkinter window.
105
+
106
+ ```python
107
+ CRAPHICS(
108
+ window,
109
+ BG,
110
+ FOCAL_LENGTH,
111
+ CAMERA_DISTANCE,
112
+ RENDER_DISTANCE,
113
+ SENSITIVITY,
114
+ FPS,
115
+ LOG
116
+ )
117
+ ```
118
+
119
+ ### Arguments
120
+
121
+ | Argument | Description |
122
+ | ----------------- | ----------------------------------------------------------------- |
123
+ | `window` | Tkinter parent window in which the rendering canvas is created |
124
+ | `BG` | Background color of the rendering canvas |
125
+ | `FOCAL_LENGTH` | Focal length used for perspective projection. Must not be `0` |
126
+ | `CAMERA_DISTANCE` | Initial distance of the camera along the Z axis. Must not be `0` |
127
+ | `RENDER_DISTANCE` | Maximum distance from the camera at which objects can be rendered |
128
+ | `SENSITIVITY` | Mouse rotation sensitivity |
129
+ | `FPS` | Target rendering frames per second. Must be greater than `0` |
130
+ | `LOG` | If `True`, prints rendering information to the console |
131
+
132
+ ## Adding Objects
133
+
134
+ ### `add_object()`
135
+
136
+ Adds a triangle-based 3D object to the scene.
137
+
138
+ ```python
139
+ graphics.add_object(
140
+ name,
141
+ fill,
142
+ outline,
143
+ polygons
144
+ )
145
+ ```
146
+
147
+ ### Arguments
148
+
149
+ | Argument | Description |
150
+ | ---------- | ----------------------------------------- |
151
+ | `name` | Unique name used to identify the object |
152
+ | `fill` | Fill color of the object's triangles |
153
+ | `outline` | Outline color of the object's triangles |
154
+ | `polygons` | List of triangles that make up the object |
155
+
156
+ Each triangle consists of three 3D vertices:
157
+
158
+ ```python
159
+ polygons = [
160
+ [
161
+ [x1, y1, z1],
162
+ [x2, y2, z2],
163
+ [x3, y3, z3]
164
+ ]
165
+ ]
166
+ ```
167
+
168
+ For example:
169
+
170
+ ```python
171
+ triangle = [
172
+ [
173
+ [-1, -1, 0],
174
+ [1, -1, 0],
175
+ [0, 1, 0]
176
+ ]
177
+ ]
178
+
179
+ graphics.add_object(
180
+ "Triangle",
181
+ "red",
182
+ "white",
183
+ triangle
184
+ )
185
+ ```
186
+
187
+ ## Removing Objects
188
+
189
+ ### `remove_object()`
190
+
191
+ Removes an object from the scene using its name.
192
+
193
+ ```python
194
+ graphics.remove_object("Triangle")
195
+ ```
196
+
197
+ ## Loading `.obj` Models
198
+
199
+ ### `add_objfile()`
200
+
201
+ Craphics can load geometry from a Wavefront `.obj` file.
202
+
203
+ ```python
204
+ graphics.add_objfile(
205
+ name,
206
+ fill,
207
+ outline,
208
+ file
209
+ )
210
+ ```
211
+
212
+ ### Arguments
213
+
214
+ | Argument | Description |
215
+ | --------- | -------------------------------- |
216
+ | `name` | Name used to identify the object |
217
+ | `fill` | Fill color of the model |
218
+ | `outline` | Outline color of the model |
219
+ | `file` | Path to the `.obj` file |
220
+
221
+ Example:
222
+
223
+ ```python
224
+ graphics.add_objfile(
225
+ "Cube",
226
+ "blue",
227
+ "white",
228
+ "cube.obj"
229
+ )
230
+ ```
231
+
232
+ ### `.obj` Support
233
+
234
+ The current `.obj` loader supports:
235
+
236
+ * Vertex definitions (`v`)
237
+ * Triangle faces (`f`)
238
+ * Vertex/texture/normal face formats such as `f 1/1/1 2/2/2 3/3/3`
239
+ * Comments (`#`)
240
+ * Vertex normals (`vn`) are ignored
241
+
242
+ The current implementation expects faces to contain **three vertices**, meaning models should use triangular faces.
243
+
244
+ ## Rendering
245
+
246
+ Craphics uses a basic perspective projection:
247
+
248
+ ```text
249
+ screen_x = FOCAL_LENGTH × x / z
250
+ screen_y = FOCAL_LENGTH × y / z
251
+ ```
252
+
253
+ Objects are transformed according to the camera's:
254
+
255
+ * Position
256
+ * Yaw
257
+ * Pitch
258
+
259
+ Triangles outside the near and far clipping planes are skipped.
260
+
261
+ The renderer also performs basic back-face culling, so triangles facing away from the camera are not rendered.
262
+
263
+ ## Camera
264
+
265
+ The camera starts at:
266
+
267
+ ```python
268
+ CAMERA_X = 0
269
+ CAMERA_Y = 0
270
+ CAMERA_Z = CAMERA_DISTANCE
271
+ ```
272
+
273
+ Camera movement is controlled using the keyboard, while yaw and pitch are controlled by mouse movement.
274
+
275
+ ### Camera Parameters
276
+
277
+ | Parameter | Description |
278
+ | ----------------- | -------------------------------------------------- |
279
+ | `CAMERA_DISTANCE` | Initial Z position of the camera |
280
+ | `SENSITIVITY` | Amount of camera rotation caused by mouse movement |
281
+ | `RENDER_DISTANCE` | Maximum rendering range |
282
+
283
+ ## Rendering Logs
284
+
285
+ Set `LOG=True` to display rendering information:
286
+
287
+ ```python
288
+ graphics = CRAPHICS(
289
+ window,
290
+ "black",
291
+ 500,
292
+ 5,
293
+ 1000,
294
+ 0.005,
295
+ 60,
296
+ True
297
+ )
298
+ ```
299
+
300
+ The console will display information such as:
301
+
302
+ ```text
303
+ [CRAPHICS] Added Object : Cube
304
+ [CRAPHICS] Rendered 1 objects | Render time: 2.31 ms | Render FPS: 432.9 | Target FPS: 60
305
+ ```
306
+
307
+ Set `LOG=False` to disable these messages.
308
+
309
+ ## Limitations
310
+
311
+ Craphics is currently intended to be a **simple and experimental 3D renderer**, rather than a full 3D engine.
312
+
313
+ Current limitations include:
314
+
315
+ * Triangle-based rendering
316
+ * `.obj` faces should be triangles
317
+ * No textures
318
+ * No lighting system
319
+ * No materials
320
+ * No shadows
321
+ * No perspective-correct texture mapping
322
+ * Basic back-face culling
323
+ * CPU-based rendering through Tkinter
324
+ * Performance decreases with complex models
325
+
326
+ ## Version
327
+
328
+ **Craphics v0.0.1**
329
+
330
+ This is an early version of the project and the API may change in future releases.
331
+
332
+ ## License
333
+
334
+ **MIT License © 2026**
335
+
336
+ See the `LICENSE` file for the full license text.
337
+
338
+ ---
339
+
340
+ Made with Python 🐍 and Tkinter.
@@ -0,0 +1,321 @@
1
+ # Craphics
2
+
3
+ A small and lightweight Python 3D graphics module built using Python's standard libraries **`tkinter`**, **`math`**, and **`time`**.
4
+
5
+ Craphics provides basic 3D rendering with perspective projection, camera movement, mouse-controlled rotation, triangle rendering, and `.obj` model loading.
6
+
7
+ > **Version:** `v0.0.1`
8
+
9
+ ## Features
10
+
11
+ * 🖥️ Tkinter-based rendering
12
+ * 📐 Basic 3D perspective projection
13
+ * 🎥 Movable camera
14
+ * 🖱️ Mouse-controlled camera rotation
15
+ * 🔺 Triangle-based object rendering
16
+ * 📦 Wavefront `.obj` file loading
17
+ * 👁️ Near and far rendering planes
18
+ * 🎨 Custom object fill and outline colors
19
+ * 📊 Optional rendering logs
20
+ * ⚙️ Configurable FPS and mouse sensitivity
21
+ * 📚 Uses only Python standard libraries
22
+
23
+ ## Installation
24
+
25
+ Install Craphics using `pip`:
26
+
27
+ ```bash
28
+ pip install craphics
29
+ ```
30
+
31
+ ## Requirements
32
+
33
+ Craphics is built using Python's standard library:
34
+
35
+ * `tkinter`
36
+ * `math`
37
+ * `time`
38
+
39
+ No additional Python dependencies are required.
40
+
41
+ > **Note:** Your Python installation must have Tkinter available.
42
+
43
+ ## Quick Start
44
+
45
+ ```python
46
+ import tkinter as tk
47
+ from craphics import CRAPHICS
48
+
49
+ window = tk.Tk()
50
+ window.title("Craphics Demo")
51
+ window.geometry("800x600")
52
+
53
+ graphics = CRAPHICS(
54
+ window=window,
55
+ BG="black",
56
+ FOCAL_LENGTH=500,
57
+ CAMERA_DISTANCE=5,
58
+ RENDER_DISTANCE=1000,
59
+ SENSITIVITY=0.005,
60
+ FPS=60,
61
+ LOG=True
62
+ )
63
+
64
+ window.mainloop()
65
+ ```
66
+
67
+ ## Controls
68
+
69
+ | Key / Input | Action |
70
+ | ------------ | -------------------- |
71
+ | `W` | Move camera forward |
72
+ | `S` | Move camera backward |
73
+ | `A` | Move camera left |
74
+ | `D` | Move camera right |
75
+ | `Space` | Move camera upward |
76
+ | `Left Shift` | Move camera downward |
77
+ | Mouse | Rotate camera |
78
+
79
+ The mouse cursor is hidden while using the Craphics canvas.
80
+
81
+ ## API
82
+
83
+ ### `CRAPHICS()`
84
+
85
+ Creates a Craphics renderer inside the supplied Tkinter window.
86
+
87
+ ```python
88
+ CRAPHICS(
89
+ window,
90
+ BG,
91
+ FOCAL_LENGTH,
92
+ CAMERA_DISTANCE,
93
+ RENDER_DISTANCE,
94
+ SENSITIVITY,
95
+ FPS,
96
+ LOG
97
+ )
98
+ ```
99
+
100
+ ### Arguments
101
+
102
+ | Argument | Description |
103
+ | ----------------- | ----------------------------------------------------------------- |
104
+ | `window` | Tkinter parent window in which the rendering canvas is created |
105
+ | `BG` | Background color of the rendering canvas |
106
+ | `FOCAL_LENGTH` | Focal length used for perspective projection. Must not be `0` |
107
+ | `CAMERA_DISTANCE` | Initial distance of the camera along the Z axis. Must not be `0` |
108
+ | `RENDER_DISTANCE` | Maximum distance from the camera at which objects can be rendered |
109
+ | `SENSITIVITY` | Mouse rotation sensitivity |
110
+ | `FPS` | Target rendering frames per second. Must be greater than `0` |
111
+ | `LOG` | If `True`, prints rendering information to the console |
112
+
113
+ ## Adding Objects
114
+
115
+ ### `add_object()`
116
+
117
+ Adds a triangle-based 3D object to the scene.
118
+
119
+ ```python
120
+ graphics.add_object(
121
+ name,
122
+ fill,
123
+ outline,
124
+ polygons
125
+ )
126
+ ```
127
+
128
+ ### Arguments
129
+
130
+ | Argument | Description |
131
+ | ---------- | ----------------------------------------- |
132
+ | `name` | Unique name used to identify the object |
133
+ | `fill` | Fill color of the object's triangles |
134
+ | `outline` | Outline color of the object's triangles |
135
+ | `polygons` | List of triangles that make up the object |
136
+
137
+ Each triangle consists of three 3D vertices:
138
+
139
+ ```python
140
+ polygons = [
141
+ [
142
+ [x1, y1, z1],
143
+ [x2, y2, z2],
144
+ [x3, y3, z3]
145
+ ]
146
+ ]
147
+ ```
148
+
149
+ For example:
150
+
151
+ ```python
152
+ triangle = [
153
+ [
154
+ [-1, -1, 0],
155
+ [1, -1, 0],
156
+ [0, 1, 0]
157
+ ]
158
+ ]
159
+
160
+ graphics.add_object(
161
+ "Triangle",
162
+ "red",
163
+ "white",
164
+ triangle
165
+ )
166
+ ```
167
+
168
+ ## Removing Objects
169
+
170
+ ### `remove_object()`
171
+
172
+ Removes an object from the scene using its name.
173
+
174
+ ```python
175
+ graphics.remove_object("Triangle")
176
+ ```
177
+
178
+ ## Loading `.obj` Models
179
+
180
+ ### `add_objfile()`
181
+
182
+ Craphics can load geometry from a Wavefront `.obj` file.
183
+
184
+ ```python
185
+ graphics.add_objfile(
186
+ name,
187
+ fill,
188
+ outline,
189
+ file
190
+ )
191
+ ```
192
+
193
+ ### Arguments
194
+
195
+ | Argument | Description |
196
+ | --------- | -------------------------------- |
197
+ | `name` | Name used to identify the object |
198
+ | `fill` | Fill color of the model |
199
+ | `outline` | Outline color of the model |
200
+ | `file` | Path to the `.obj` file |
201
+
202
+ Example:
203
+
204
+ ```python
205
+ graphics.add_objfile(
206
+ "Cube",
207
+ "blue",
208
+ "white",
209
+ "cube.obj"
210
+ )
211
+ ```
212
+
213
+ ### `.obj` Support
214
+
215
+ The current `.obj` loader supports:
216
+
217
+ * Vertex definitions (`v`)
218
+ * Triangle faces (`f`)
219
+ * Vertex/texture/normal face formats such as `f 1/1/1 2/2/2 3/3/3`
220
+ * Comments (`#`)
221
+ * Vertex normals (`vn`) are ignored
222
+
223
+ The current implementation expects faces to contain **three vertices**, meaning models should use triangular faces.
224
+
225
+ ## Rendering
226
+
227
+ Craphics uses a basic perspective projection:
228
+
229
+ ```text
230
+ screen_x = FOCAL_LENGTH × x / z
231
+ screen_y = FOCAL_LENGTH × y / z
232
+ ```
233
+
234
+ Objects are transformed according to the camera's:
235
+
236
+ * Position
237
+ * Yaw
238
+ * Pitch
239
+
240
+ Triangles outside the near and far clipping planes are skipped.
241
+
242
+ The renderer also performs basic back-face culling, so triangles facing away from the camera are not rendered.
243
+
244
+ ## Camera
245
+
246
+ The camera starts at:
247
+
248
+ ```python
249
+ CAMERA_X = 0
250
+ CAMERA_Y = 0
251
+ CAMERA_Z = CAMERA_DISTANCE
252
+ ```
253
+
254
+ Camera movement is controlled using the keyboard, while yaw and pitch are controlled by mouse movement.
255
+
256
+ ### Camera Parameters
257
+
258
+ | Parameter | Description |
259
+ | ----------------- | -------------------------------------------------- |
260
+ | `CAMERA_DISTANCE` | Initial Z position of the camera |
261
+ | `SENSITIVITY` | Amount of camera rotation caused by mouse movement |
262
+ | `RENDER_DISTANCE` | Maximum rendering range |
263
+
264
+ ## Rendering Logs
265
+
266
+ Set `LOG=True` to display rendering information:
267
+
268
+ ```python
269
+ graphics = CRAPHICS(
270
+ window,
271
+ "black",
272
+ 500,
273
+ 5,
274
+ 1000,
275
+ 0.005,
276
+ 60,
277
+ True
278
+ )
279
+ ```
280
+
281
+ The console will display information such as:
282
+
283
+ ```text
284
+ [CRAPHICS] Added Object : Cube
285
+ [CRAPHICS] Rendered 1 objects | Render time: 2.31 ms | Render FPS: 432.9 | Target FPS: 60
286
+ ```
287
+
288
+ Set `LOG=False` to disable these messages.
289
+
290
+ ## Limitations
291
+
292
+ Craphics is currently intended to be a **simple and experimental 3D renderer**, rather than a full 3D engine.
293
+
294
+ Current limitations include:
295
+
296
+ * Triangle-based rendering
297
+ * `.obj` faces should be triangles
298
+ * No textures
299
+ * No lighting system
300
+ * No materials
301
+ * No shadows
302
+ * No perspective-correct texture mapping
303
+ * Basic back-face culling
304
+ * CPU-based rendering through Tkinter
305
+ * Performance decreases with complex models
306
+
307
+ ## Version
308
+
309
+ **Craphics v0.0.1**
310
+
311
+ This is an early version of the project and the API may change in future releases.
312
+
313
+ ## License
314
+
315
+ **MIT License © 2026**
316
+
317
+ See the `LICENSE` file for the full license text.
318
+
319
+ ---
320
+
321
+ Made with Python 🐍 and Tkinter.
@@ -0,0 +1 @@
1
+ from .craphics import *
@@ -0,0 +1,202 @@
1
+ import tkinter as tk
2
+ import math
3
+ import time
4
+
5
+ CRAPHICS_VERSION = "0.0.1"
6
+
7
+ class CRAPHICS:
8
+ def __init__(self, window, BG, FOCAL_LENGTH, CAMERA_DISTANCE, RENDER_DISTANCE, SENSITIVITY, FPS, LOG):
9
+ self.LOG = LOG
10
+ self.FPS = FPS
11
+ self.last_mouse_x = None
12
+ self.last_mouse_y = None
13
+ self.SENSITIVITY = SENSITIVITY
14
+ self.YAW = 0
15
+ self.PITCH = 0
16
+ self.NEAR_PLANE = 0.1
17
+ self.FAR_PLANE = self.NEAR_PLANE + RENDER_DISTANCE
18
+ self.RENDER_DISTANCE = RENDER_DISTANCE
19
+ self.CAMERA_X = 0
20
+ self.CAMERA_Y = 0
21
+ self.FOCAL_LENGTH = FOCAL_LENGTH
22
+ self.CAMERA_Z = CAMERA_DISTANCE
23
+ self.objects = {}
24
+ self.canvas = tk.Canvas(window, bg = BG)
25
+ self.canvas.pack(expand = True, fill = "both")
26
+ self.canvas.focus_set()
27
+ self.canvas.bind("<KeyPress-w>", lambda event: self._move_forward(0.1))
28
+ self.canvas.bind("<KeyPress-s>", lambda event: self._move_forward(-0.1))
29
+ self.canvas.bind("<KeyPress-a>", lambda event: self._move_right(-0.1))
30
+ self.canvas.bind("<KeyPress-d>", lambda event: self._move_right(0.1))
31
+ self.canvas.bind("<KeyPress-space>", lambda event: self._change_y(0.1))
32
+ self.canvas.bind("<KeyPress-Shift_L>", lambda event: self._change_y(-0.1))
33
+ self.canvas.bind("<Motion>", self._mouse_move)
34
+ self.canvas.config(cursor="none")
35
+ self._render()
36
+
37
+ def _mouse_move(self, event):
38
+ if self.last_mouse_x is None:
39
+ self.last_mouse_x = event.x
40
+ self.last_mouse_y = event.y
41
+ return
42
+
43
+ dx = event.x - self.last_mouse_x
44
+ dy = event.y - self.last_mouse_y
45
+
46
+ self.YAW += dx * self.SENSITIVITY
47
+ self.PITCH -= dy * self.SENSITIVITY
48
+
49
+ self.last_mouse_x = event.x
50
+ self.last_mouse_y = event.y
51
+
52
+ def _change_y(self, amount):
53
+ self.CAMERA_Y += amount
54
+
55
+ def _move_forward(self, amount):
56
+ self.CAMERA_X += math.sin(self.YAW) * amount
57
+ self.CAMERA_Z += math.cos(self.YAW) * amount
58
+
59
+ def _move_right(self, amount):
60
+ self.CAMERA_X += math.cos(self.YAW) * amount
61
+ self.CAMERA_Z -= math.sin(self.YAW) * amount
62
+
63
+ def add_object(self, name, fill, outline, polygons):
64
+ self.objects[name] = (name, fill, outline, polygons)
65
+ if self.LOG:
66
+ print("[CRAPHICS] Added Object :", name)
67
+
68
+ def remove_object(self, name):
69
+ if name in self.objects:
70
+ del self.objects[name]
71
+ if self.LOG:
72
+ print("[CRAPHICS] Removed Object :", name)
73
+
74
+ def _get_projection(self,x,y,z):
75
+ x -= self.CAMERA_X
76
+ y -= self.CAMERA_Y
77
+ z -= self.CAMERA_Z
78
+
79
+ x_new = x * math.cos(self.YAW) - z * math.sin(self.YAW)
80
+ z_new = x * math.sin(self.YAW) + z * math.cos(self.YAW)
81
+
82
+ y_rot = y * math.cos(self.PITCH) - z_new * math.sin(self.PITCH)
83
+ z_rot = y * math.sin(self.PITCH) + z_new * math.cos(self.PITCH)
84
+
85
+ y_new = y_rot
86
+ z_new = z_rot
87
+
88
+ if z_new <= self.NEAR_PLANE or z_new >= self.FAR_PLANE:
89
+ return None
90
+
91
+ x_new = float(self.FOCAL_LENGTH * x_new / z_new)
92
+ y_new = float(self.FOCAL_LENGTH * y_new / z_new)
93
+ return x_new, y_new
94
+
95
+ def _convert_coordinates(self,x,y):
96
+ x = x + self.canvas.winfo_width() / 2
97
+ y = -y + self.canvas.winfo_height() / 2
98
+ return x,y
99
+
100
+ def add_objfile(self, name, fill, outline, file):
101
+ with open(file, "r") as f:
102
+ content = f.readlines()
103
+ vertices = []
104
+ polygons = []
105
+
106
+ for line in content:
107
+ if line[0] == "#" or line[0] == "vn":
108
+ continue
109
+ elif line[0] == "v":
110
+ line = line.split()
111
+ vertices.append([float(line[1]),float(line[2]),float(line[3])])
112
+ elif line[0] == "f":
113
+ line.split()
114
+ point1 = int(line.split()[1].split("/")[0])
115
+ point2 = int(line.split()[2].split("/")[0])
116
+ point3 = int(line.split()[3].split("/")[0])
117
+ polygons.append([vertices[point1 - 1],vertices[point2 - 1],vertices[point3 - 1]])
118
+
119
+ self.add_object(name, fill, outline, polygons)
120
+
121
+ def _get_camera_z(self, x, y, z):
122
+ x -= self.CAMERA_X
123
+ y -= self.CAMERA_Y
124
+ z -= self.CAMERA_Z
125
+
126
+ x_new = x * math.cos(self.YAW) - z * math.sin(self.YAW)
127
+ z_new = x * math.sin(self.YAW) + z * math.cos(self.YAW)
128
+
129
+ y_rot = y * math.cos(self.PITCH) - z_new * math.sin(self.PITCH)
130
+ z_rot = y * math.sin(self.PITCH) + z_new * math.cos(self.PITCH)
131
+
132
+ return z_rot
133
+
134
+ def _render(self):
135
+ start = time.perf_counter()
136
+
137
+ self.canvas.update()
138
+ self.canvas.delete("all")
139
+ count = 0
140
+ for object in self.objects.values():
141
+ name = object[0]
142
+ fill = object[1]
143
+ outline = object[2]
144
+ polygons = object[3]
145
+ rendered = 0
146
+
147
+ polygons = sorted(polygons, key=lambda polygon: sum(self._get_camera_z(*vertex) for vertex in polygon) / len(polygon),reverse=True)
148
+
149
+ for polygon in polygons:
150
+ x1,y1,z1 = polygon[0]
151
+ x2,y2,z2 = polygon[1]
152
+ x3,y3,z3 = polygon[2]
153
+
154
+ ax = x2 - x1
155
+ ay = y2 - y1
156
+ az = z2 - z1
157
+
158
+ bx = x3 - x1
159
+ by = y3 - y1
160
+ bz = z3 - z1
161
+
162
+ nx = ay * bz - az * by
163
+ ny = az * bx - ax * bz
164
+ nz = ax * by - ay * bx
165
+
166
+ vx = self.CAMERA_X - x1
167
+ vy = self.CAMERA_Y - y1
168
+ vz = self.CAMERA_Z - z1
169
+
170
+ dot = nx * vx + ny * vy + nz * vz
171
+
172
+ if dot <= 0:
173
+ continue
174
+
175
+ value1 = self._get_projection(x1,y1,z1)
176
+ value2 = self._get_projection(x2,y2,z2)
177
+ value3 = self._get_projection(x3,y3,z3)
178
+
179
+ if not value1 or not value2 or not value3:
180
+ continue
181
+
182
+ x1,y1 = self._convert_coordinates(*value1)
183
+ x2,y2 = self._convert_coordinates(*value2)
184
+ x3,y3 = self._convert_coordinates(*value3)
185
+
186
+ rendered += 1
187
+ self.canvas.create_polygon(x1,y1,x2,y2,x3,y3, fill = fill, outline = outline)
188
+
189
+ if rendered > 0 :
190
+ count += 1
191
+
192
+ render_time = time.perf_counter() - start
193
+
194
+ if self.LOG:
195
+ print(
196
+ f"[CRAPHICS] Rendered {count} objects "
197
+ f"| Render time: {render_time * 1000:.2f} ms "
198
+ f"| Render FPS: {1 / render_time:.1f} "
199
+ f"| Target FPS: {self.FPS}"
200
+ )
201
+
202
+ self.canvas.after(1000 // self.FPS, self._render)
@@ -0,0 +1,340 @@
1
+ Metadata-Version: 2.4
2
+ Name: craphics
3
+ Version: 0.0.1
4
+ Summary: A small Python Library for CPU - rendered graphics
5
+ Author: Moinak Debnath
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/findstring/craphics
8
+ Project-URL: Repository, https://github.com/findstring/craphics
9
+ Project-URL: Issues, https://github.com/findstring/craphics/issues
10
+ Keywords: graphics,cpu,rendering,tkinter,math
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Topic :: Multimedia :: Graphics
14
+ Classifier: Topic :: Multimedia :: Graphics :: 3D Modeling
15
+ Requires-Python: >=3.9
16
+ Description-Content-Type: text/markdown
17
+ License-File: LICENSE
18
+ Dynamic: license-file
19
+
20
+ # Craphics
21
+
22
+ A small and lightweight Python 3D graphics module built using Python's standard libraries **`tkinter`**, **`math`**, and **`time`**.
23
+
24
+ Craphics provides basic 3D rendering with perspective projection, camera movement, mouse-controlled rotation, triangle rendering, and `.obj` model loading.
25
+
26
+ > **Version:** `v0.0.1`
27
+
28
+ ## Features
29
+
30
+ * 🖥️ Tkinter-based rendering
31
+ * 📐 Basic 3D perspective projection
32
+ * 🎥 Movable camera
33
+ * 🖱️ Mouse-controlled camera rotation
34
+ * 🔺 Triangle-based object rendering
35
+ * 📦 Wavefront `.obj` file loading
36
+ * 👁️ Near and far rendering planes
37
+ * 🎨 Custom object fill and outline colors
38
+ * 📊 Optional rendering logs
39
+ * ⚙️ Configurable FPS and mouse sensitivity
40
+ * 📚 Uses only Python standard libraries
41
+
42
+ ## Installation
43
+
44
+ Install Craphics using `pip`:
45
+
46
+ ```bash
47
+ pip install craphics
48
+ ```
49
+
50
+ ## Requirements
51
+
52
+ Craphics is built using Python's standard library:
53
+
54
+ * `tkinter`
55
+ * `math`
56
+ * `time`
57
+
58
+ No additional Python dependencies are required.
59
+
60
+ > **Note:** Your Python installation must have Tkinter available.
61
+
62
+ ## Quick Start
63
+
64
+ ```python
65
+ import tkinter as tk
66
+ from craphics import CRAPHICS
67
+
68
+ window = tk.Tk()
69
+ window.title("Craphics Demo")
70
+ window.geometry("800x600")
71
+
72
+ graphics = CRAPHICS(
73
+ window=window,
74
+ BG="black",
75
+ FOCAL_LENGTH=500,
76
+ CAMERA_DISTANCE=5,
77
+ RENDER_DISTANCE=1000,
78
+ SENSITIVITY=0.005,
79
+ FPS=60,
80
+ LOG=True
81
+ )
82
+
83
+ window.mainloop()
84
+ ```
85
+
86
+ ## Controls
87
+
88
+ | Key / Input | Action |
89
+ | ------------ | -------------------- |
90
+ | `W` | Move camera forward |
91
+ | `S` | Move camera backward |
92
+ | `A` | Move camera left |
93
+ | `D` | Move camera right |
94
+ | `Space` | Move camera upward |
95
+ | `Left Shift` | Move camera downward |
96
+ | Mouse | Rotate camera |
97
+
98
+ The mouse cursor is hidden while using the Craphics canvas.
99
+
100
+ ## API
101
+
102
+ ### `CRAPHICS()`
103
+
104
+ Creates a Craphics renderer inside the supplied Tkinter window.
105
+
106
+ ```python
107
+ CRAPHICS(
108
+ window,
109
+ BG,
110
+ FOCAL_LENGTH,
111
+ CAMERA_DISTANCE,
112
+ RENDER_DISTANCE,
113
+ SENSITIVITY,
114
+ FPS,
115
+ LOG
116
+ )
117
+ ```
118
+
119
+ ### Arguments
120
+
121
+ | Argument | Description |
122
+ | ----------------- | ----------------------------------------------------------------- |
123
+ | `window` | Tkinter parent window in which the rendering canvas is created |
124
+ | `BG` | Background color of the rendering canvas |
125
+ | `FOCAL_LENGTH` | Focal length used for perspective projection. Must not be `0` |
126
+ | `CAMERA_DISTANCE` | Initial distance of the camera along the Z axis. Must not be `0` |
127
+ | `RENDER_DISTANCE` | Maximum distance from the camera at which objects can be rendered |
128
+ | `SENSITIVITY` | Mouse rotation sensitivity |
129
+ | `FPS` | Target rendering frames per second. Must be greater than `0` |
130
+ | `LOG` | If `True`, prints rendering information to the console |
131
+
132
+ ## Adding Objects
133
+
134
+ ### `add_object()`
135
+
136
+ Adds a triangle-based 3D object to the scene.
137
+
138
+ ```python
139
+ graphics.add_object(
140
+ name,
141
+ fill,
142
+ outline,
143
+ polygons
144
+ )
145
+ ```
146
+
147
+ ### Arguments
148
+
149
+ | Argument | Description |
150
+ | ---------- | ----------------------------------------- |
151
+ | `name` | Unique name used to identify the object |
152
+ | `fill` | Fill color of the object's triangles |
153
+ | `outline` | Outline color of the object's triangles |
154
+ | `polygons` | List of triangles that make up the object |
155
+
156
+ Each triangle consists of three 3D vertices:
157
+
158
+ ```python
159
+ polygons = [
160
+ [
161
+ [x1, y1, z1],
162
+ [x2, y2, z2],
163
+ [x3, y3, z3]
164
+ ]
165
+ ]
166
+ ```
167
+
168
+ For example:
169
+
170
+ ```python
171
+ triangle = [
172
+ [
173
+ [-1, -1, 0],
174
+ [1, -1, 0],
175
+ [0, 1, 0]
176
+ ]
177
+ ]
178
+
179
+ graphics.add_object(
180
+ "Triangle",
181
+ "red",
182
+ "white",
183
+ triangle
184
+ )
185
+ ```
186
+
187
+ ## Removing Objects
188
+
189
+ ### `remove_object()`
190
+
191
+ Removes an object from the scene using its name.
192
+
193
+ ```python
194
+ graphics.remove_object("Triangle")
195
+ ```
196
+
197
+ ## Loading `.obj` Models
198
+
199
+ ### `add_objfile()`
200
+
201
+ Craphics can load geometry from a Wavefront `.obj` file.
202
+
203
+ ```python
204
+ graphics.add_objfile(
205
+ name,
206
+ fill,
207
+ outline,
208
+ file
209
+ )
210
+ ```
211
+
212
+ ### Arguments
213
+
214
+ | Argument | Description |
215
+ | --------- | -------------------------------- |
216
+ | `name` | Name used to identify the object |
217
+ | `fill` | Fill color of the model |
218
+ | `outline` | Outline color of the model |
219
+ | `file` | Path to the `.obj` file |
220
+
221
+ Example:
222
+
223
+ ```python
224
+ graphics.add_objfile(
225
+ "Cube",
226
+ "blue",
227
+ "white",
228
+ "cube.obj"
229
+ )
230
+ ```
231
+
232
+ ### `.obj` Support
233
+
234
+ The current `.obj` loader supports:
235
+
236
+ * Vertex definitions (`v`)
237
+ * Triangle faces (`f`)
238
+ * Vertex/texture/normal face formats such as `f 1/1/1 2/2/2 3/3/3`
239
+ * Comments (`#`)
240
+ * Vertex normals (`vn`) are ignored
241
+
242
+ The current implementation expects faces to contain **three vertices**, meaning models should use triangular faces.
243
+
244
+ ## Rendering
245
+
246
+ Craphics uses a basic perspective projection:
247
+
248
+ ```text
249
+ screen_x = FOCAL_LENGTH × x / z
250
+ screen_y = FOCAL_LENGTH × y / z
251
+ ```
252
+
253
+ Objects are transformed according to the camera's:
254
+
255
+ * Position
256
+ * Yaw
257
+ * Pitch
258
+
259
+ Triangles outside the near and far clipping planes are skipped.
260
+
261
+ The renderer also performs basic back-face culling, so triangles facing away from the camera are not rendered.
262
+
263
+ ## Camera
264
+
265
+ The camera starts at:
266
+
267
+ ```python
268
+ CAMERA_X = 0
269
+ CAMERA_Y = 0
270
+ CAMERA_Z = CAMERA_DISTANCE
271
+ ```
272
+
273
+ Camera movement is controlled using the keyboard, while yaw and pitch are controlled by mouse movement.
274
+
275
+ ### Camera Parameters
276
+
277
+ | Parameter | Description |
278
+ | ----------------- | -------------------------------------------------- |
279
+ | `CAMERA_DISTANCE` | Initial Z position of the camera |
280
+ | `SENSITIVITY` | Amount of camera rotation caused by mouse movement |
281
+ | `RENDER_DISTANCE` | Maximum rendering range |
282
+
283
+ ## Rendering Logs
284
+
285
+ Set `LOG=True` to display rendering information:
286
+
287
+ ```python
288
+ graphics = CRAPHICS(
289
+ window,
290
+ "black",
291
+ 500,
292
+ 5,
293
+ 1000,
294
+ 0.005,
295
+ 60,
296
+ True
297
+ )
298
+ ```
299
+
300
+ The console will display information such as:
301
+
302
+ ```text
303
+ [CRAPHICS] Added Object : Cube
304
+ [CRAPHICS] Rendered 1 objects | Render time: 2.31 ms | Render FPS: 432.9 | Target FPS: 60
305
+ ```
306
+
307
+ Set `LOG=False` to disable these messages.
308
+
309
+ ## Limitations
310
+
311
+ Craphics is currently intended to be a **simple and experimental 3D renderer**, rather than a full 3D engine.
312
+
313
+ Current limitations include:
314
+
315
+ * Triangle-based rendering
316
+ * `.obj` faces should be triangles
317
+ * No textures
318
+ * No lighting system
319
+ * No materials
320
+ * No shadows
321
+ * No perspective-correct texture mapping
322
+ * Basic back-face culling
323
+ * CPU-based rendering through Tkinter
324
+ * Performance decreases with complex models
325
+
326
+ ## Version
327
+
328
+ **Craphics v0.0.1**
329
+
330
+ This is an early version of the project and the API may change in future releases.
331
+
332
+ ## License
333
+
334
+ **MIT License © 2026**
335
+
336
+ See the `LICENSE` file for the full license text.
337
+
338
+ ---
339
+
340
+ Made with Python 🐍 and Tkinter.
@@ -0,0 +1,9 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ craphics/__init__.py
5
+ craphics/craphics.py
6
+ craphics.egg-info/PKG-INFO
7
+ craphics.egg-info/SOURCES.txt
8
+ craphics.egg-info/dependency_links.txt
9
+ craphics.egg-info/top_level.txt
@@ -0,0 +1 @@
1
+ craphics
@@ -0,0 +1,28 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "craphics"
7
+ version = "0.0.1"
8
+ description = "A small Python Library for CPU - rendered graphics"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ license-files = ["LICENSE"]
12
+ requires-python = ">=3.9"
13
+ authors = [
14
+ { name = "Moinak Debnath" }
15
+ ]
16
+ keywords = ["graphics", "cpu", "rendering", "tkinter", "math"]
17
+ classifiers = [
18
+ "Intended Audience :: Developers",
19
+ "Programming Language :: Python :: 3",
20
+ "Topic :: Multimedia :: Graphics",
21
+ "Topic :: Multimedia :: Graphics :: 3D Modeling",
22
+ ]
23
+ dependencies = []
24
+
25
+ [project.urls]
26
+ Homepage = "https://github.com/findstring/craphics"
27
+ Repository = "https://github.com/findstring/craphics"
28
+ Issues = "https://github.com/findstring/craphics/issues"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+