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.
This commit is contained in:
parent
ef3681fc5b
commit
33dce4ecfd
2 changed files with 139 additions and 3 deletions
120
examples/extra/mesh_creation.py
Normal file
120
examples/extra/mesh_creation.py
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
from array import array
|
||||||
|
import pyray as pr
|
||||||
|
|
||||||
|
W, H = 640, 480
|
||||||
|
|
||||||
|
|
||||||
|
def make_cube(width, height, length):
|
||||||
|
vertices = array('f', [
|
||||||
|
-width / 2, -height / 2, length / 2,
|
||||||
|
width / 2, -height / 2, length / 2,
|
||||||
|
width / 2, height / 2, length / 2,
|
||||||
|
-width / 2, height / 2, length / 2,
|
||||||
|
-width / 2, -height / 2, -length / 2,
|
||||||
|
-width / 2, height / 2, -length / 2,
|
||||||
|
width / 2, height / 2, -length / 2,
|
||||||
|
width / 2, -height / 2, -length / 2,
|
||||||
|
-width / 2, height / 2, -length / 2,
|
||||||
|
-width / 2, height / 2, length / 2,
|
||||||
|
width / 2, height / 2, length / 2,
|
||||||
|
width / 2, height / 2, -length / 2,
|
||||||
|
-width / 2, -height / 2, -length / 2,
|
||||||
|
width / 2, -height / 2, -length / 2,
|
||||||
|
width / 2, -height / 2, length / 2,
|
||||||
|
-width / 2, -height / 2, length / 2,
|
||||||
|
width / 2, -height / 2, -length / 2,
|
||||||
|
width / 2, height / 2, -length / 2,
|
||||||
|
width / 2, height / 2, length / 2,
|
||||||
|
width / 2, -height / 2, length / 2,
|
||||||
|
-width / 2, -height / 2, -length / 2,
|
||||||
|
-width / 2, -height / 2, length / 2,
|
||||||
|
-width / 2, height / 2, length / 2,
|
||||||
|
-width / 2, height / 2, -length / 2
|
||||||
|
])
|
||||||
|
|
||||||
|
texcoords = array('f', [
|
||||||
|
0.0, 0.0,
|
||||||
|
1.0, 0.0,
|
||||||
|
1.0, 1.0,
|
||||||
|
0.0, 1.0,
|
||||||
|
1.0, 0.0,
|
||||||
|
1.0, 1.0,
|
||||||
|
0.0, 1.0,
|
||||||
|
0.0, 0.0,
|
||||||
|
0.0, 1.0,
|
||||||
|
0.0, 0.0,
|
||||||
|
1.0, 0.0,
|
||||||
|
1.0, 1.0,
|
||||||
|
1.0, 1.0,
|
||||||
|
0.0, 1.0,
|
||||||
|
0.0, 0.0,
|
||||||
|
1.0, 0.0,
|
||||||
|
1.0, 0.0,
|
||||||
|
1.0, 1.0,
|
||||||
|
0.0, 1.0,
|
||||||
|
0.0, 0.0,
|
||||||
|
0.0, 0.0,
|
||||||
|
1.0, 0.0,
|
||||||
|
1.0, 1.0,
|
||||||
|
0.0, 1.0])
|
||||||
|
|
||||||
|
normals = array('f', [
|
||||||
|
0.0, 0.0, 1.0,
|
||||||
|
0.0, 0.0, 1.0,
|
||||||
|
0.0, 0.0, 1.0,
|
||||||
|
0.0, 0.0, 1.0,
|
||||||
|
0.0, 0.0, -1.0,
|
||||||
|
0.0, 0.0, -1.0,
|
||||||
|
0.0, 0.0, -1.0,
|
||||||
|
0.0, 0.0, -1.0,
|
||||||
|
0.0, 1.0, 0.0,
|
||||||
|
0.0, 1.0, 0.0,
|
||||||
|
0.0, 1.0, 0.0,
|
||||||
|
0.0, 1.0, 0.0,
|
||||||
|
0.0, -1.0, 0.0,
|
||||||
|
0.0, -1.0, 0.0,
|
||||||
|
0.0, -1.0, 0.0,
|
||||||
|
0.0, -1.0, 0.0,
|
||||||
|
1.0, 0.0, 0.0,
|
||||||
|
1.0, 0.0, 0.0,
|
||||||
|
1.0, 0.0, 0.0,
|
||||||
|
1.0, 0.0, 0.0,
|
||||||
|
-1.0, 0.0, 0.0,
|
||||||
|
-1.0, 0.0, 0.0,
|
||||||
|
-1.0, 0.0, 0.0,
|
||||||
|
-1.0, 0.0, 0.0
|
||||||
|
])
|
||||||
|
|
||||||
|
indices = array('h',
|
||||||
|
sum([[4 * k, 4 * k + 1, 4 * k + 2, 4 * k, 4 * k + 2, 4 * k + 3] for k in range(0, 6)], []))
|
||||||
|
|
||||||
|
print(vertices, indices)
|
||||||
|
|
||||||
|
return (pr.Mesh(24, 12, vertices, texcoords,
|
||||||
|
None, normals, None, None, indices,
|
||||||
|
None, None, None, None, 0, None))
|
||||||
|
|
||||||
|
|
||||||
|
pr.init_window(W, H, "Mesh creation")
|
||||||
|
|
||||||
|
msh = make_cube(3, 4, 40)
|
||||||
|
pr.upload_mesh(msh, False)
|
||||||
|
matdefault = pr.load_material_default()
|
||||||
|
eye = pr.matrix_identity()
|
||||||
|
|
||||||
|
camera = pr.Camera3D((30.0, 20.0, 30.0), (0.0, 0.0, 0.0), (0.0, 1.0, 0.0), 70.0,
|
||||||
|
pr.CameraProjection.CAMERA_PERSPECTIVE)
|
||||||
|
|
||||||
|
# Export so we can inspect it
|
||||||
|
pr.export_mesh(msh, "test-cube.obj")
|
||||||
|
|
||||||
|
while not pr.window_should_close():
|
||||||
|
pr.update_camera(camera, pr.CameraMode.CAMERA_ORBITAL)
|
||||||
|
pr.begin_drawing()
|
||||||
|
pr.clear_background(pr.BLACK)
|
||||||
|
pr.begin_mode_3d(camera)
|
||||||
|
pr.draw_grid(10, 5.0)
|
||||||
|
pr.draw_mesh(msh, matdefault, eye)
|
||||||
|
pr.end_mode_3d()
|
||||||
|
pr.end_drawing()
|
||||||
|
pr.close_window()
|
|
@ -11,6 +11,8 @@
|
||||||
# available at https://www.gnu.org/software/classpath/license.html.
|
# available at https://www.gnu.org/software/classpath/license.html.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
|
# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
|
||||||
|
import weakref
|
||||||
|
from array import array
|
||||||
|
|
||||||
from raylib import rl, ffi
|
from raylib import rl, ffi
|
||||||
from raylib.colors import *
|
from raylib.colors import *
|
||||||
|
@ -43,7 +45,7 @@ def makefunc(a):
|
||||||
def func(*args):
|
def func(*args):
|
||||||
modified_args = []
|
modified_args = []
|
||||||
for (c_arg, arg) in zip(ffi.typeof(a).args, args):
|
for (c_arg, arg) in zip(ffi.typeof(a).args, args):
|
||||||
#print("arg:",str(arg), "c_arg.kind:", c_arg.kind, "c_arg:", c_arg, "type(arg):",str(type(arg)))
|
# print("arg:",str(arg), "c_arg.kind:", c_arg.kind, "c_arg:", c_arg, "type(arg):",str(type(arg)))
|
||||||
if c_arg.kind == 'pointer':
|
if c_arg.kind == 'pointer':
|
||||||
if type(arg) == str:
|
if type(arg) == str:
|
||||||
arg = arg.encode('utf-8')
|
arg = arg.encode('utf-8')
|
||||||
|
@ -53,7 +55,7 @@ def makefunc(a):
|
||||||
arg = ffi.new("int *", arg)
|
arg = ffi.new("int *", arg)
|
||||||
elif type(arg) is float:
|
elif type(arg) is float:
|
||||||
arg = ffi.new("float *", arg)
|
arg = ffi.new("float *", arg)
|
||||||
elif type(arg) is list and str(c_arg) == "<ctype 'char * *'>":
|
elif type(arg) is list and str(c_arg) == "<ctype 'char * *'>":
|
||||||
arg = [ffi.new("char[]", x.encode('utf-8')) for x in arg]
|
arg = [ffi.new("char[]", x.encode('utf-8')) for x in arg]
|
||||||
elif str(type(arg)) == "<class '_cffi_backend.__CDataOwn'>" and "*" not in str(arg): # CPython
|
elif str(type(arg)) == "<class '_cffi_backend.__CDataOwn'>" and "*" not in str(arg): # CPython
|
||||||
arg = ffi.addressof(arg)
|
arg = ffi.addressof(arg)
|
||||||
|
@ -74,10 +76,24 @@ def makefunc(a):
|
||||||
|
|
||||||
return func
|
return func
|
||||||
|
|
||||||
|
global_weakkeydict = weakref.WeakKeyDictionary()
|
||||||
|
|
||||||
def makeStructHelper(struct):
|
def makeStructHelper(struct):
|
||||||
def func(*args):
|
def func(*args):
|
||||||
return ffi.new(f"struct {struct} *", args)[0]
|
# print(struct, args)
|
||||||
|
modified_args = []
|
||||||
|
for (field, arg) in zip(ffi.typeof(struct).fields, args):
|
||||||
|
# print("arg:", str(arg), "field:", field[1], "field type:", field[1].type, "type(arg):", str(type(arg)))
|
||||||
|
if arg is None:
|
||||||
|
arg = ffi.NULL
|
||||||
|
elif (field[1].type.kind == 'pointer'
|
||||||
|
and (str(type(arg)) == "<class 'numpy.ndarray'>"
|
||||||
|
or isinstance(arg, (array, bytes, bytearray, memoryview)))):
|
||||||
|
arg = ffi.from_buffer(field[1].type, arg)
|
||||||
|
modified_args.append(arg)
|
||||||
|
s = ffi.new(f"struct {struct} *", modified_args)[0]
|
||||||
|
global_weakkeydict[s] = modified_args
|
||||||
|
return s
|
||||||
|
|
||||||
return func
|
return func
|
||||||
|
|
||||||
|
|
Reference in a new issue