omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular

    Welcome!

    This is the community forum for my apps Pythonista and Editorial.

    For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.


    3D in Pythonista?

    Pythonista
    12
    16
    18935
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • zencuke
      zencuke last edited by

      Additional note: What is hard in 3D graphics isn't the geometry, it is rendering, i.e. coloring the surfaces. Dooms biggest trick was to require all objects/walls to be perpendicular to the viewer. That simplified the rendering requirements substantially. Essentially every object in doom was a 2D shape with an image drawn on it. You scale to represent distance.

      1 Reply Last reply Reply Quote 0
      • Webmaster4o
        Webmaster4o last edited by

        Are there any 3D libraries out there that could be made to work with numpy/PIL?

        1 Reply Last reply Reply Quote 0
        • Moe
          Moe last edited by

          Take a look at SceneKit. While there is no python wrapper for it, you could use objc_util to accomplish that. It would probably make your life easier if you were to make a python wrapper first. To load that framework use

          from objc_util import *
          
          ObjcClass('NSBundle').bundleWithPath_('System/Library/Frameworks/SceneKit.framework').load()
          
          1 Reply Last reply Reply Quote 0
          • omz
            omz last edited by omz

            If you want to play with SceneKit, here's a starting point (requires beta #160023):

            Screenshot

            Note: You can use gestures (pan/pinch) to control the camera.

            from objc_util import *
            import ui
            import math
            
            load_framework('SceneKit')
            SCNView, SCNScene, SCNBox, SCNText, SCNNode, SCNLight, SCNAction, UIFont = map(ObjCClass, ['SCNView', 'SCNScene', 'SCNBox', 'SCNText', 'SCNNode', 'SCNLight', 'SCNAction', 'UIFont'])
            
            class SCNVector3 (Structure):
            	_fields_ = [('x', c_float), ('y', c_float), ('z', c_float)]
            
            @on_main_thread
            def demo():
            	main_view = ui.View()
            	main_view_objc = ObjCInstance(main_view)
            	scene_view = SCNView.alloc().initWithFrame_options_(((0, 0),(400, 400)), None).autorelease()
            	scene_view.setAutoresizingMask_(18)
            	scene_view.setAllowsCameraControl_(True)
            	scene = SCNScene.scene()
            	root_node = scene.rootNode()
            	text_mesh = SCNText.textWithString_extrusionDepth_('Pythonista', 6.0)
            	text_mesh.setFlatness_(0.2)
            	text_mesh.setChamferRadius_(0.4)
            	text_mesh.setFont_(UIFont.fontWithName_size_('HelveticaNeue-Bold', 18))
            	bbox_min, bbox_max = SCNVector3(), SCNVector3()
            	text_mesh.getBoundingBoxMin_max_(byref(bbox_min), byref(bbox_max), restype=None, argtypes=[POINTER(SCNVector3), POINTER(SCNVector3)])
            	text_width = bbox_max.x - bbox_min.x
            	text_node = SCNNode.nodeWithGeometry_(text_mesh)
            	text_node.setCastsShadow_(True)
            	text_container = SCNNode.node()
            	text_container.addChildNode_(text_node)
            	text_container.setPosition_((0, 40, 0))
            	text_node.setPosition_((-text_width/2, 0, 0))
            	box = SCNBox.boxWithWidth_height_length_chamferRadius_(100, 4, 100, 1)
            	box_node = SCNNode.nodeWithGeometry_(box)
            	root_node.addChildNode_(box_node)
            	rotate_action = SCNAction.repeatActionForever_(SCNAction.rotateByX_y_z_duration_(0, math.pi*2, math.pi*2, 10))
            	text_container.runAction_(rotate_action)
            	root_node.addChildNode_(text_container)
            	light_node = SCNNode.node()
            	light_node.setPosition_((0, 100, 10))
            	light_node.setRotation_((1, 0, 0, -math.pi/2))
            	light = SCNLight.light()
            	light.setType_('spot')
            	light.setCastsShadow_(True)
            	light.setColor_(UIColor.cyanColor().CGColor())
            	light_node.setLight_(light)
            	root_node.addChildNode_(light_node)
            	scene_view.setScene_(scene)
            	main_view_objc.addSubview_(scene_view)
            	main_view.name = 'SceneKit Demo'
            	main_view.present()
            
            demo()
            
            1 Reply Last reply Reply Quote 0
            • Utsira
              Utsira last edited by

              Apologies for bumping a 2-year-old thread. When I try to run the above script in Python 3.5 I get an error at the map command saying:

              no Objective-C class named 'b'SCNView'' found

              Is this some 2.7 -> 3.5 issue? What is the extraneous 'b in the error message referring to?

              thanks in advance.

              1 Reply Last reply Reply Quote 0
              • ccc
                ccc last edited by

                The b'bytes string' is https://docs.python.org/3/reference/lexical_analysis.html#grammar-token-bytesprefix

                SCNView is https://developer.apple.com/reference/scenekit/scnview

                But I know nothing more.

                1 Reply Last reply Reply Quote 0
                • omz
                  omz last edited by

                  Try adding load_framework('SceneKit') before the line with the error.

                  1 Reply Last reply Reply Quote 1
                  • abcabc
                    abcabc last edited by abcabc

                    Thanks Omz . I tried also the basic code from following tutorial using your template and it is working fine.
                    https://code.tutsplus.com/tutorials/an-introduction-to-scenekit-fundamentals--cms-23847

                    from objc_util import *
                    import ui
                    import math
                    
                    load_framework('SceneKit')
                    
                    SCNView, SCNScene, SCNBox, SCNText, SCNNode, SCNLight, SCNCamera, SCNAction, UIFont = map(ObjCClass, ['SCNView', 'SCNScene', 'SCNBox', 'SCNText', 'SCNNode', 'SCNLight',  'SCNCamera', 'SCNAction', 'UIFont'])
                    
                    class SCNVector3 (Structure):
                        _fields_ = [('x', c_float), ('y', c_float), ('z', c_float)]
                        
                    '''
                    https://code.tutsplus.com/tutorials/an-introduction-to-scenekit-fundamentals--cms-23847
                    '''
                    '''
                    override func viewDidLoad() {
                        super.viewDidLoad()
                         
                        let sceneView = SCNView(frame: self.view.frame)
                        self.view.addSubview(sceneView)
                             
                        let scene = SCNScene()
                        sceneView.scene = scene
                     
                        let camera = SCNCamera()
                        let cameraNode = SCNNode()
                        cameraNode.camera = camera
                        cameraNode.position = SCNVector3(x: 0.0, y: 0.0, z: 3.0)
                     
                        let light = SCNLight()
                        light.type = SCNLightTypeOmni
                        let lightNode = SCNNode()
                        lightNode.light = light
                        lightNode.position = SCNVector3(x: 1.5, y: 1.5, z: 1.5)
                     
                        let cubeGeometry = SCNBox(width: 1.0, height: 1.0, length: 1.0, chamferRadius: 0.0)
                        let cubeNode = SCNNode(geometry: cubeGeometry)
                     
                        scene.rootNode.addChildNode(lightNode)
                        scene.rootNode.addChildNode(cameraNode)
                        scene.rootNode.addChildNode(cubeNode)
                    }
                    '''
                    
                    @on_main_thread
                    def demo():
                        main_view = ui.View()
                        main_view_objc = ObjCInstance(main_view)
                        scene_view = SCNView.alloc().initWithFrame_options_(((0, 0),(400, 400)), None).autorelease()
                        scene_view.setAutoresizingMask_(18)
                        scene_view.setAllowsCameraControl_(True)
                        main_view_objc.addSubview_(scene_view)
                        main_view.name = 'SceneKit Demo'
                        
                        scene = SCNScene.scene()
                        scene_view.setScene_(scene)
                        
                        root_node = scene.rootNode()
                        
                        camera = SCNCamera.camera()
                        camera_node = SCNNode.node()
                        camera_node.setCamera(camera)
                        camera_node.setPosition((0.0, 0.0, 3.0))
                    
                        light = SCNLight.light()
                        light.setType_('omni')
                        light_node = SCNNode.node()
                        light_node.setLight_(light)
                        light_node.setPosition((1.5, 1.5, 1.5))
                        
                        cube_geometry = SCNBox.boxWithWidth_height_length_chamferRadius_(1, 1, 1, 0)
                        cube_node = SCNNode.nodeWithGeometry_(cube_geometry)
                        
                        root_node.addChildNode_(light_node)
                        root_node.addChildNode_(camera_node)        
                        root_node.addChildNode_(cube_node)
                        
                        main_view.present()
                    
                    demo()
                    
                    
                    
                    

                    Full example here
                    https://gist.github.com/balachandrana/644840a223b636ecd84d14a595dad33b

                    1 Reply Last reply Reply Quote 0
                    • Utsira
                      Utsira last edited by

                      @omz thanks, it works now, that's awesome. I've used SceneKit quite a lot with Swift, but I'm still new to Python/ Pythonista. One question, how come you implement SCNVector3 as a Python class, rather than importing it with the other ObjC classes? Just trying to understand the implications of working with ObjC libraries in Pythonista. thanks.

                      1 Reply Last reply Reply Quote 0
                      • dgelessus
                        dgelessus last edited by

                        SCNVector3 is a C struct, not an Objective-C class. Objective-C classes carry lots of information at runtime (their name, superclass, protocols, methods, etc.), and all Objective-C objects contain a pointer to their class. All of this information can be looked up via APIs provided by the Objective-C runtime library. That's what makes objc_util possible.

                        C structs, on the other hand, carry no runtime info at all. If you look at some struct data, you cannot see what its type is. For all you know, it might not even be a struct. It could also be an int, or an array of bytes. There is also no way to see what struct types there are, or what fields a certain struct type has.

                        So to be able to work with struct data, you first need to describe its type. In ctypes, you do that by creating a subclass of the ctypes.Structure class. Your subclass's _fields_ attribute lists the name and type of every field in the struct. Once you've done that, you can allocate instances of your struct in memory, and you can tell ctypes that a function takes or returns struct data of that type.

                        In this specific case, I don't think the declaration of SCNVector3 is actually needed. In the above code, you can see that all places where a SCNVector3 would be used in Swift, the Python/objc_util version simply uses a tuple. This is only possible because Objective-C is involved. All Objective-C methods have a type signature, which describes the types of their return value and all arguments, including structs. This allows objc_util to get some basic info about a method's struct arguments, which is enough to convert a Python tuple into correctly formated C struct data. This only works with Objective-C method arguments though, and not anywhere else. For plain C functions and variables, you still need to declare the struct type by hand.

                        1 Reply Last reply Reply Quote 1
                        • Utsira
                          Utsira last edited by

                          Thank you for your answer @dgelessus , really interesting.

                          1 Reply Last reply Reply Quote 0
                          • bcraig_6973
                            bcraig_6973 @JadedTuna last edited by

                            @JadedTuna
                            I am new to this
                            Have you got a better Handel on how to do this
                            All I want to do is just using 3 Python learn to how create a 2d flat grid in 3d space
                            What are the step by steps to do this kind of thing ?

                            1 Reply Last reply Reply Quote 0
                            • Brun0oO
                              Brun0oO last edited by Brun0oO

                              Hi,

                              I got, from a swift project, some SceneKit assets (files with ‘.scn’ extension). I put them in a ###.scnassets directory and try to load them using the SCNScene.sceneNamed_ method.
                              This call fails, i got None as result.
                              Do you know if I need to make a kind of initialization for the SceneKit resources mechanism ?

                              Thanks for your help...

                              1 Reply Last reply Reply Quote 0
                              • First post
                                Last post
                              Powered by NodeBB Forums | Contributors