I found a script that can draw 3D only on iOS by using SceneKit with objc_util of Pythonista, so I will introduce it.
3d-omz.py Note: If you don't add load_framework (‘SceneKit’), you will get an error. https://github.com/tdamdouni/Pythonista/blob/master/scenes/3d-omz.py
3D in Pythonista https://forum.omz-software.com/topic/1686/3d-in-pythonista
from objc_util import *
Allows you to directly call the functionality provided by the objc_util module.
Since the objc_util module is based on the standard module ctypes, this one line also allows you to use the Structure etc. provided by the ctypes module.
load_framework('SceneKit')
Load the SceneKit framework so that it can be manipulated programmatically.
Since it was not described in 3d-omz.py, it may not have been necessary to call it in the past, but in iPadOS13, when converting the SCNView class etc. provided by SceneKit to a format that can be used in Python with ObjCClass I get angry with the error no Objective-C class named'xxxx' found.
SCNView, SCNScene, SCNBox, SCNText, SCNNode, SCNLight, SCNAction, UIFont = map(ObjCClass, ['SCNView', 'SCNScene', 'SCNBox', 'SCNText', 'SCNNode', 'SCNLight', 'SCNAction', 'UIFont'])
The classes provided by SceneKit are converted to a format that can be used in Python using obj_util.ObjCClass.
It's easy to use the standard function map because you can write the same process all at once.
class SCNVector3 (Structure):
_fields_ = [('x', c_float), ('y', c_float), ('z', c_float)]
Use ctypes.Structure to define a structure with three attributes (x, y, z) of type float. The structure defined here will be used later to get the BoundingBox of Text.
main_view = ui.View()
main_view_objc = ObjCInstance(main_view)
I'm getting a pointer to access from Objective-C by creating an empty ui.View and passing that View instance to objc_util.ObjCInstance.
It seems that you can later hang the SceneKit View as a child of this main_view so that you can see the SceneKit drawings inside the Pythonista ui.View. (Details are not understood due to lack of study)
scene_view = SCNView.alloc().initWithFrame_options_(((0, 0),(400, 400)), None).autorelease()
scene_view.setAutoresizingMask_(18)
scene_view.setAllowsCameraControl_(True)
Create an instance of SCNView by calling the alloc () method. It then calls initWithFrame: options: to initialize it to size (400,400) at position (0,0). Finally, by calling autorelease () on the instance, it is set to automatically destroy the memory when it is no longer needed.
SCNView.initWithFrame:options: https://developer.apple.com/documentation/scenekit/scnview/1524215-initwithframe?language=objc
setAutoresizeMask_ is a method to set what to do when the size of the parent View changes. The number 18 is the logical sum of 2 for flexibleWidth and 16 for flexibleHeight, and by setting this, the width and height will be tracked when the size of the parent View changes.
It's easy to imagine that this is the same as the flex attribute of the View class of the Pythonista ui module.
UIView.AutoresizingMask https://developer.apple.com/documentation/uikit/uiview/1622559-autoresizingmask
Setting setAllowsCameraControl_ to True allows you to swipe the screen and rotate the camera. It is convenient and good to set this to True for some viewers and early development checks.
scene = SCNScene.scene()
node_root = scene.rootNode()
Cameras, lights, and drawings managed by SceneKit are all layered by Node. The SCNScene rootNode is the parent of that hierarchy.
After this, by adding various nodes to rootNode, what will be displayed on the screen and how will be decided.
Recommended Posts