开源改变世界!!

OpenGL 支持:允许使用鼠标自由旋转 3D 视图 #591

推推 grbl 2年前 (2023-02-01) 150次浏览
打开
Harvie 打开了这个问题 2017 年 5 月 15 日 · 21条评论
打开

OpenGL 支持:允许使用鼠标自由旋转 3D 视图#591

Harvie 打开了这个问题 2017 年 5 月 15 日 · 21条评论

注释

OpenGL 支持:允许使用鼠标自由旋转 3D 视图 #591
合作者

能够通过鼠标拖动自由旋转 3D 视图真的很有用。预定义的 ISO1-3 视图有点做这个工作,但它有助于查看轻微移动的对象,以便更快地掌握它们的形状。

OpenGL 支持:允许使用鼠标自由旋转 3D 视图 #591
所有者

我正在手动进行 3D 渲染(不使用任何 3d 库)并且 python 在这方面不是很快。
我可能会这样做,但它不会是互动的。

OpenGL 支持:允许使用鼠标自由旋转 3D 视图 #591
合作者作者
哈维 评论了 2017 年 5 月 20 日  

这是有原因的吗?我想有针对 python 的经过良好测试的 OpenGL 绑定,或者类似的东西……

OpenGL 支持:允许使用鼠标自由旋转 3D 视图 #591
所有者

是的,bCNC 没有使用 OpenGL,它使用了最少的外部依赖。

OpenGL 支持:允许使用鼠标自由旋转 3D 视图 #591
合作者作者
哈维 评论了 2017 年 5 月 28 日  

我知道,但这有合理的理由吗?这种“不是在这里发明”的方法并不总是那么明智。特别是当它不仅缺乏基本的旋转功能,而且你显然会遇到性能问题(超时渲染)等……

顺便说一句,我已经为大约一百个程序制作了 linux 包,所以我知道外部依赖项是多么烦人。但有时使用少量外部库是有意义的。特别是当它们广泛流行并且已经打包时。这是关于某种平衡。你不想要 100 个外部库的依赖地狱,但是使用像 opengl 这样常见的东西进行 3d 渲染是有道理的……

OpenGL 支持:允许使用鼠标自由旋转 3D 视图 #591
所有者

如果您能帮助将 OpenGL 添加为渲染,我将非常高兴。

OpenGL 支持:允许使用鼠标自由旋转 3D 视图 #591
合作者作者

你知道哪些方法需要移植到OpenGL吗?

OpenGL 支持:允许使用鼠标自由旋转 3D 视图 #591
合作者作者
哈维 评论了 2018 年 7 月 9 日  

只是偶然发现了这个:https
: //docs.enthought.com/mayavi/mayavi/ 不确定是否可以在 bCNC 中重新用作显示…

OpenGL 支持:允许使用鼠标自由旋转 3D 视图 #591 哈维 改了标题 允许使用鼠标自由旋转 3D 视图 OpenGL 支持:允许使用鼠标自由旋转 3D 视图 2018 年 8 月 18 日
OpenGL 支持:允许使用鼠标自由旋转 3D 视图 #591
合作者作者
哈维 评论了 2018 年 8 月 18 日  

VisPy 似乎拥有我们需要的一切,但我不知道如何将它集成到 tkinter 窗口:-(

http://vispy.org https://github.com/vispy/vispy
https://glumpy.github.io/ https://github.com/glumpy/glumpy
https://kivy.org/doc/stable /examples/gen__3Drendering__main__py.html

OpenGL 支持:允许使用鼠标自由旋转 3D 视图 #591
合作者作者

也许 GL 胶可以把它放在一起?
https://github.com/ousttrue/glglue

也许是 GLUT 或 PyGame?

OpenGL 支持:允许使用鼠标自由旋转 3D 视图 #591
合作者作者

在我看来,Tkinter 是编写 GL 应用程序的糟糕选择。我们必须重新发明一些基础知识才能让它发挥作用。

OpenGL 支持:允许使用鼠标自由旋转 3D 视图 #591
合作者作者
哈维 评论了 2018 年 8 月 18 日  

基本上,在不放弃 Tkinter 的情况下拥有 OpenGL 的唯一方法是使用一些有 10 年历史的名为 Togl 的库,这是 b*tch 来安装和分发。这样的皮塔饼。

http://pyopengl.sourceforge.net/pydoc/OpenGL.Tk.html说:

Togl 的传统 PyOpenGL 接口

该模块使用创建一组
默认“检查”操作的相对“厚”包装器 API提供对 Tkinter Togl 小部件的访问。

请注意,许多(大多数)Linux 发行版
现在已将 Tkinter 绑定拆分到一个单独的包中,
并且必须单独下载 Togl(
源发行版中提供了一个脚本,
可以为您下载和安装 Togl 2.0 二进制文件)。

由于安装的复杂性和脆弱性,
建议您
在实际项目中使用 Pygame、wxPython、PyGtk 或 PyQt,

在简单的 演示/测试界面中使用 GLUT 或 Pygame 。

Togl 项目位于此处:
http ://togl.sourceforge.net/

OpenGL 支持:允许使用鼠标自由旋转 3D 视图 #591
合作者作者

https://stackoverflow.com/questions/8584272/using-pygame-features-in-tkinter
这似乎使我们能够将 pygame 嵌入到 tkinter 中。可能最好的办法是使用 tkinter。

import Tkinter as tk
import os

w, h = 500, 200

# Add a couple widgets. We're going to put pygame in `embed`.
root = tk.Tk()
embed = tk.Frame(root, width=w, height=h)
embed.pack()
text = tk.Button(root, text='Blah.')
text.pack()

# Tell pygame's SDL window which window ID to use    
os.environ['SDL_WINDOWID'] = str(embed.winfo_id())

# The wxPython wiki says you might need the following line on Windows
# (http://wiki.wxpython.org/IntegratingPyGame).
#os.environ['SDL_VIDEODRIVER'] = 'windib'

# Show the window so it's assigned an ID.
root.update()

# Usual pygame initialization
import pygame as pg
pg.display.init()
screen = pg.display.set_mode((w,h))

pos = 0
while 1:
    # Do some pygame stuff
    screen.fill(pg.Color(0,0,0))
    pos = (pos + 1) % screen.get_width()
    pg.draw.circle(screen, pg.Color(255,255,255), (pos,100), 30)

    # Update the pygame display
    pg.display.flip()

    # Update the Tk display
    root.update()
OpenGL 支持:允许使用鼠标自由旋转 3D 视图 #591
合作者作者
哈维 评论了 2018 年 8 月 18 日  

这基本上意味着,您可以通过将 env SDL_WINDOWID 设置为 Frame.winfo_id()将任何 SDL 或 PyGame 应用程序包含到 Tkinter Frame 中

例如:在这里,我收到了 bCNC 画布的窗口 ID,
print("canvas wid",self.canvasFrame.canvas.winfo_id())
然后使用该 ID 启动了简单的 SDL 游戏,从而将该游戏嵌入到 bCNC 中。然而,鼠标/键盘输入仍会转到 bCNC,因此游戏无法玩。

OpenGL 支持:允许使用鼠标自由旋转 3D 视图 #591

我也不确定这是否适用于 Windows 或 Mac。

OpenGL 支持:允许使用鼠标自由旋转 3D 视图 #591
合作者作者

Tkinter 画布必须很慢吗?这似乎比较快:

https://www.youtube.com/watch?v=rkNToAMcIcs

但是它没有抗锯齿,这很糟糕……

OpenGL 支持:允许使用鼠标自由旋转 3D 视图 #591
合作者作者
哈维 评论了 2018 年 8 月 18 日  

这使用鼠标进行实时 tkinter 画布旋转,在我看来似乎并不太慢:

https://github.com/ActiveState/code/tree/master/recipes/Python/578876_Rotatable_Tetrahedron
http://code.activestate.com/recipes/578876-rotatable-tetrahedron/

#!/usr/bin/env python
# coding: UTF-8
#
## @package _12_tet
#
#  Draws a 3D tetrahedron and allows a user to rotate it
#  (mouse left button and wheel).
#
#  The Tetrahedron is represented by a 3 x 4 matrix. 
#  Each column represents a 3D vertex.
#
#  note: a m x n matrix is represented by a list of lines:
#     [[l_1] [l_2] .. [l_m]].
#  m = len(mat), n = len(mat[0]), mat(i,j) = mat[i][j]
#
#  @author Paulo Roma
#  @since 01/05/2014
#  @see http://www.orimosenzon.com/wiki/index.php/Python_samples
#  @see http://mathworld.wolfram.com/RotationMatrix.html

try:
   from tkinter import *     # python 3
except ImportError:
   from Tkinter import *     # python 2
from math import *

def createZeroMat(m,n):
    """Return a matrix (m x n) filled with zeros."""

    ret = [0] * m
    for i in range(m):
        ret[i] = [0] * n
    return ret   

def matMul(mat1, mat2):
    """Return mat1 x mat2 (mat1 multiplied by mat2)."""

    m = len(mat1)
    n = len(mat2[0])
    common = len(mat2)
   
    ret = createZeroMat(m,n)
    if  len(mat1[0]) == len(mat2):
      for i in range(m):
          for j in range(n):
              for k in range(common):
                  ret[i][j] += mat1[i][k] * mat2[k][j]
    return ret

def matTrans(mat):
    """Return mat (n x m) transposed (m x n)."""

    m = len(mat[0])
    n = len(mat)

    ret = createZeroMat(m,n)
    for i in range(m):
        for j in range(n):
            ret[i][j] = mat[j][i]
    return ret

def translate(x,y,dx,dy):
    """Translate vector(x,y) by (dx,dy)."""

    return x+dx, y+dy
   
def drawTet(tet,col):
    """Draw a tetrahedron."""

    w = canvas.winfo_width()/2
    h = canvas.winfo_height()/2
    canvas.delete(ALL) # delete all edges
    nv = len(tet[0])   # number of vertices in tet (4)

    # draw the 6 edges of the tetrahedron
    for p1 in range(nv):
        for p2 in range(p1+1,nv):
            canvas.create_line(translate(tet[0][p1], tet[1][p1], w, h),
                               translate(tet[0][p2], tet[1][p2], w, h), fill = col)

def init():
    """Initialize global variables."""

    global ROT_X, ROT_Y, ROT_Z
    global eps, EPS, tet
    global lastX, lastY, tetColor, bgColor

    tet = matTrans([[0,-100,0],[-100,100,0],[100,100,0],[0,0,200]])
 
    # counter-clockwise rotation about the X axis
    ROT_X = lambda x: matTrans([[1,0,0],           [0,cos(x),-sin(x)], [0,sin(x),cos(x)] ])

    # counter-clockwise rotation about the Y axis
    ROT_Y = lambda y: matTrans([[cos(y),0,sin(y)], [0,1,0],            [-sin(y),0,cos(y)]])

    # counter-clockwise rotation about the Z axis
    ROT_Z = lambda z: matTrans([[cos(z),sin(z),0], [-sin(z),cos(z),0], [0,0,1]])

    eps = lambda d: pi/300 if (d>0) else -pi/300
    EPS = lambda d: d*pi/300

    lastX = 0 
    lastY = 0
    tetColor = 'black'
    bgColor = 'white'

def cbClicked(event):
    """Save current mouse position."""

    global lastX, lastY

    lastX = event.x
    lastY = event.y

def cbMottion(event):
    """Map mouse displacements in Y direction to rotations about X axis,
       and mouse displacements in X direction to rotations about Y axis.""" 

    global tet

    # Y coordinate is upside down
    dx = lastY - event.y 
    tet = matMul(ROT_X(EPS(-dx)),tet)

    dy = lastX - event.x
    tet = matMul(ROT_Y(EPS(dy)),tet)

    drawTet(tet,tetColor)
    cbClicked(event)   

def wheelUp(event):
    """Map mouse wheel up displacements to rotations about Z axis."""

    global tet
    tet = matMul(ROT_Z(EPS(1)),tet)
    drawTet(tet,tetColor)

def wheelDown(event):
    """Map mouse wheel down displacements to rotations about Z axis."""

    global tet
    tet = matMul(ROT_Z(EPS(-1)),tet)
    drawTet(tet,tetColor)

def wheel(event):
    """Map mouse wheel displacements to rotations about Z axis."""

    global tet
    tet = matMul(ROT_Z(EPS(event.delta/120)),tet)
    drawTet(tet,tetColor)

def resize(event):
    """Redraw the tetrahedron, in case of a window change due to user resizing it.""" 

    drawTet(tet,tetColor)
                
def main():
    global canvas
    root = Tk()
    root.title('Tetrahedron')
    root.geometry('+0+0')

    init()

    canvas = Canvas(root, width=400, height=400, background=bgColor)
    canvas.pack(fill=BOTH,expand=YES)               
    canvas.bind("<Button-1>", cbClicked)
    canvas.bind("<B1-Motion>", cbMottion)
    canvas.bind("<Configure>", resize)

    from platform import uname
    os = uname()[0]
    if ( os == "Linux" ):
         canvas.bind('<Button-4>', wheelUp)      # X11
         canvas.bind('<Button-5>', wheelDown)
    elif ( os == "Darwin" ):
         canvas.bind('<MouseWheel>', wheel)      # MacOS
    else: 
         canvas.bind_all('<MouseWheel>', wheel)  # windows

    drawTet(tet,tetColor)

    mainloop()

if __name__=='__main__':
    sys.exit(main())
OpenGL 支持:允许使用鼠标自由旋转 3D 视图 #591
合作者作者
哈维 评论了 2018 年 8 月 18 日  

刚刚尝试向该代码添加更多 3D 线。在处理 10000 条 3D 线时,它似乎相当快,我会说它运行多达 3000 条线时几乎可以平稳运行。但是仍然……没有办法获得抗锯齿:-(

OpenGL 支持:允许使用鼠标自由旋转 3D 视图 #591
合作者作者
哈维 评论了 2018 年 8 月 18 日  

另一种解决方案可能是将 bCNC 重写为 GTK3 (PyGTK) 或 wxWidgets (wxPython),它们比 Tkinter 更新并且与 OpenGL 没有问题。但这至少是劳动密集型的。

OpenGL 支持:允许使用鼠标自由旋转 3D 视图 #591
合作者作者

刚刚试过这个,它看起来很有前途:

https://github.com/jonwright/pyopengltk

我在 Tkinter 窗口中有 OpenGL 上下文,没有任何黑客攻击!

OpenGL 支持:允许使用鼠标自由旋转 3D 视图 #591

OpenGL 支持:允许使用鼠标自由旋转 3D 视图 #591

看起来很有前途!!
干得好。

这个被引用了2018 年 9 月 29 日

免费注册 在 GitHub 上加入此对话。已有帐户? 登录评论
标签
项目

还没有

发展

没有分支机构或拉取请求

3人参加
OpenGL 支持:允许使用鼠标自由旋转 3D 视图 #591OpenGL 支持:允许使用鼠标自由旋转 3D 视图 #591OpenGL 支持:允许使用鼠标自由旋转 3D 视图 #591

喜欢 (0)