Skip to content

Commit 33dce4e

Browse files
Improve struct creation helper methods by auto converting arguments: (#119)
* None to ffi.NULL * array and ndarray to buffer, and keep weakref so it doesn't get GCed This makes it possible to create Mesh structs without too much faffing.
1 parent ef3681f commit 33dce4e

File tree

2 files changed

+139
-3
lines changed

2 files changed

+139
-3
lines changed

examples/extra/mesh_creation.py

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
from array import array
2+
import pyray as pr
3+
4+
W, H = 640, 480
5+
6+
7+
def make_cube(width, height, length):
8+
vertices = array('f', [
9+
-width / 2, -height / 2, length / 2,
10+
width / 2, -height / 2, length / 2,
11+
width / 2, height / 2, length / 2,
12+
-width / 2, height / 2, length / 2,
13+
-width / 2, -height / 2, -length / 2,
14+
-width / 2, height / 2, -length / 2,
15+
width / 2, height / 2, -length / 2,
16+
width / 2, -height / 2, -length / 2,
17+
-width / 2, height / 2, -length / 2,
18+
-width / 2, height / 2, length / 2,
19+
width / 2, height / 2, length / 2,
20+
width / 2, height / 2, -length / 2,
21+
-width / 2, -height / 2, -length / 2,
22+
width / 2, -height / 2, -length / 2,
23+
width / 2, -height / 2, length / 2,
24+
-width / 2, -height / 2, length / 2,
25+
width / 2, -height / 2, -length / 2,
26+
width / 2, height / 2, -length / 2,
27+
width / 2, height / 2, length / 2,
28+
width / 2, -height / 2, length / 2,
29+
-width / 2, -height / 2, -length / 2,
30+
-width / 2, -height / 2, length / 2,
31+
-width / 2, height / 2, length / 2,
32+
-width / 2, height / 2, -length / 2
33+
])
34+
35+
texcoords = array('f', [
36+
0.0, 0.0,
37+
1.0, 0.0,
38+
1.0, 1.0,
39+
0.0, 1.0,
40+
1.0, 0.0,
41+
1.0, 1.0,
42+
0.0, 1.0,
43+
0.0, 0.0,
44+
0.0, 1.0,
45+
0.0, 0.0,
46+
1.0, 0.0,
47+
1.0, 1.0,
48+
1.0, 1.0,
49+
0.0, 1.0,
50+
0.0, 0.0,
51+
1.0, 0.0,
52+
1.0, 0.0,
53+
1.0, 1.0,
54+
0.0, 1.0,
55+
0.0, 0.0,
56+
0.0, 0.0,
57+
1.0, 0.0,
58+
1.0, 1.0,
59+
0.0, 1.0])
60+
61+
normals = array('f', [
62+
0.0, 0.0, 1.0,
63+
0.0, 0.0, 1.0,
64+
0.0, 0.0, 1.0,
65+
0.0, 0.0, 1.0,
66+
0.0, 0.0, -1.0,
67+
0.0, 0.0, -1.0,
68+
0.0, 0.0, -1.0,
69+
0.0, 0.0, -1.0,
70+
0.0, 1.0, 0.0,
71+
0.0, 1.0, 0.0,
72+
0.0, 1.0, 0.0,
73+
0.0, 1.0, 0.0,
74+
0.0, -1.0, 0.0,
75+
0.0, -1.0, 0.0,
76+
0.0, -1.0, 0.0,
77+
0.0, -1.0, 0.0,
78+
1.0, 0.0, 0.0,
79+
1.0, 0.0, 0.0,
80+
1.0, 0.0, 0.0,
81+
1.0, 0.0, 0.0,
82+
-1.0, 0.0, 0.0,
83+
-1.0, 0.0, 0.0,
84+
-1.0, 0.0, 0.0,
85+
-1.0, 0.0, 0.0
86+
])
87+
88+
indices = array('h',
89+
sum([[4 * k, 4 * k + 1, 4 * k + 2, 4 * k, 4 * k + 2, 4 * k + 3] for k in range(0, 6)], []))
90+
91+
print(vertices, indices)
92+
93+
return (pr.Mesh(24, 12, vertices, texcoords,
94+
None, normals, None, None, indices,
95+
None, None, None, None, 0, None))
96+
97+
98+
pr.init_window(W, H, "Mesh creation")
99+
100+
msh = make_cube(3, 4, 40)
101+
pr.upload_mesh(msh, False)
102+
matdefault = pr.load_material_default()
103+
eye = pr.matrix_identity()
104+
105+
camera = pr.Camera3D((30.0, 20.0, 30.0), (0.0, 0.0, 0.0), (0.0, 1.0, 0.0), 70.0,
106+
pr.CameraProjection.CAMERA_PERSPECTIVE)
107+
108+
# Export so we can inspect it
109+
pr.export_mesh(msh, "test-cube.obj")
110+
111+
while not pr.window_should_close():
112+
pr.update_camera(camera, pr.CameraMode.CAMERA_ORBITAL)
113+
pr.begin_drawing()
114+
pr.clear_background(pr.BLACK)
115+
pr.begin_mode_3d(camera)
116+
pr.draw_grid(10, 5.0)
117+
pr.draw_mesh(msh, matdefault, eye)
118+
pr.end_mode_3d()
119+
pr.end_drawing()
120+
pr.close_window()

pyray/__init__.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
# available at https://www.gnu.org/software/classpath/license.html.
1212
#
1313
# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
14+
import weakref
15+
from array import array
1416

1517
from raylib import rl, ffi
1618
from raylib.colors import *
@@ -43,7 +45,7 @@ def makefunc(a):
4345
def func(*args):
4446
modified_args = []
4547
for (c_arg, arg) in zip(ffi.typeof(a).args, args):
46-
#print("arg:",str(arg), "c_arg.kind:", c_arg.kind, "c_arg:", c_arg, "type(arg):",str(type(arg)))
48+
# print("arg:",str(arg), "c_arg.kind:", c_arg.kind, "c_arg:", c_arg, "type(arg):",str(type(arg)))
4749
if c_arg.kind == 'pointer':
4850
if type(arg) == str:
4951
arg = arg.encode('utf-8')
@@ -53,7 +55,7 @@ def func(*args):
5355
arg = ffi.new("int *", arg)
5456
elif type(arg) is float:
5557
arg = ffi.new("float *", arg)
56-
elif type(arg) is list and str(c_arg) == "<ctype 'char * *'>":
58+
elif type(arg) is list and str(c_arg) == "<ctype 'char * *'>":
5759
arg = [ffi.new("char[]", x.encode('utf-8')) for x in arg]
5860
elif str(type(arg)) == "<class '_cffi_backend.__CDataOwn'>" and "*" not in str(arg): # CPython
5961
arg = ffi.addressof(arg)
@@ -74,10 +76,24 @@ def func(*args):
7476

7577
return func
7678

79+
global_weakkeydict = weakref.WeakKeyDictionary()
7780

7881
def makeStructHelper(struct):
7982
def func(*args):
80-
return ffi.new(f"struct {struct} *", args)[0]
83+
# print(struct, args)
84+
modified_args = []
85+
for (field, arg) in zip(ffi.typeof(struct).fields, args):
86+
# print("arg:", str(arg), "field:", field[1], "field type:", field[1].type, "type(arg):", str(type(arg)))
87+
if arg is None:
88+
arg = ffi.NULL
89+
elif (field[1].type.kind == 'pointer'
90+
and (str(type(arg)) == "<class 'numpy.ndarray'>"
91+
or isinstance(arg, (array, bytes, bytearray, memoryview)))):
92+
arg = ffi.from_buffer(field[1].type, arg)
93+
modified_args.append(arg)
94+
s = ffi.new(f"struct {struct} *", modified_args)[0]
95+
global_weakkeydict[s] = modified_args
96+
return s
8197

8298
return func
8399

0 commit comments

Comments
 (0)