Search code examples
pythonopenglgraphics3dpyopengl

How can I create a cylinder linking two points with Python withour using blender's bpy?


I want to position a cylinder such that the center of one end is at (x0, y0, z0) and the center of the other end is at (x1, y1, z1) using the pure Python API.

I want to attain this using Python OpenGL or any other GL libs but not blender lib

My Problem
I searched in stackoverflow and found this question

https://blender.stackexchange.com/questions/5898/how-can-i-create-a-cylinder-linking-two-points-with-python

But it is using blender and I don't want it

I need to run the python script from command line or pycharm ide

So bpy module can't work outside blender

I want a function like this format

cylinder_between(x1, y1, z1, x2, y2, z2, rad):

The function have to display a cylinder

Please guide me

2) also suggest how to clear the screen fully after drawing the cylinder


Solution

  • If you want to use modern OpenGL then you've to generate a Vertex Array Object and to write a Shader.

    A solution with less lines of code is to use Legacy OpenGL and either gluCylinder or glutSolidCylinder.

    With this (deprecated) tool set a cylinder with few lines of code can be drawn e.g.:

    from OpenGL.GLUT import *
    from OpenGL.GLU import *
    from OpenGL.GL import *
    import math
    
    def cross(a, b):
        return [a[1]*b[2]-a[2]*b[1], a[2]*b[0]-a[0]*b[2], a[0]*b[1]-a[1]*b[0]]
    
    def cylinder_between(x1, y1, z1, x2, y2, z2, rad):
        v = [x2-x1, y2-y1, z2-z1]
        height = math.sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2])
        axis = (1, 0, 0) if math.hypot(v[0], v[1]) < 0.001 else cross(v, (0, 0, 1))
        angle = -math.atan2(math.hypot(v[0], v[1]), v[2])*180/math.pi
        
        glPushMatrix()
        glTranslate(x1, y1, z1)
        glRotate(angle, *axis)
        glutSolidCylinder(rad, height, 32, 16)
        glPopMatrix()
    
    def draw():
    
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        gluPerspective(45, wnd_w/wnd_h, 0.1, 10)
        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()
        gluLookAt(0, -2, 0, 0, 0, 0, 0, 0, 1)
    
        glClearColor(0.5, 0.5, 0.5, 1.0)  
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    
        # glEnable(GL_DEPTH_TEST)
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE) # causes wire frame
        glColor(1, 1, 0.5)
        cylinder_between(0.2, 0.4, -0.5, -0.2, -0.4, 0.5, 0.3)
    
        glutSwapBuffers()
        glutPostRedisplay()
    
    wnd_w, wnd_h = 300, 300
    glutInit()
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH)
    glutInitWindowSize(wnd_w, wnd_h)
    glutInitWindowPosition(50, 50)
    glutCreateWindow("cylinder")
    glutDisplayFunc(draw)
    glutMainLoop()
    

    See also Immediate mode and legacy OpenGL


    Is there any way to implement manually do pan , rotate , tilt ,move the viewport like we do in 3D modeling software using mouse (that alt+mmb )

    See: