50種3D效果演示(OpenGL)

效果:

在這里插入圖片描述
在這里插入圖片描述

一、只需打開命令行(Windows 可用 cmd),輸入:

pip install PyQt5 PyOpenGL numpy

二、用命令行進入保存 .py 文件的目錄,運行:

python openGL_3d_demo.py

三、建立python文件命名openGL_3d_demo.py后粘貼代碼,然后運行

import sys
import math
import time
import numpy as np
from PyQt5.QtCore import Qt, QTimer
from PyQt5.QtGui import QFont, QPalette, QColor
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QGridLayout,QTabWidget, QLabel, QFrame, QOpenGLWidget
)
from OpenGL.GL import *
from OpenGL.GLU import *# ========== 通用3D控件 ==========
class Base3DGL(QOpenGLWidget):name = "3D效果"def __init__(self, parent=None):super().__init__(parent)self.last_pos = Noneself.angle_x, self.angle_y = 20, 20self.fps = 0self._frames = 0self._last_time = time.time()self.setMinimumSize(220, 180)self.timer = QTimer(self)self.timer.timeout.connect(self.update)self.timer.start(16)def initializeGL(self):glClearColor(0.10, 0.11, 0.15, 1.0)glEnable(GL_DEPTH_TEST)glShadeModel(GL_SMOOTH)def resizeGL(self, w, h):glViewport(0, 0, w, h)glMatrixMode(GL_PROJECTION)glLoadIdentity()gluPerspective(40.0, w / float(h or 1), 1.0, 100.0)glMatrixMode(GL_MODELVIEW)def paintGL(self):self._frames += 1now = time.time()if now - self._last_time > 1.0:self.fps = self._frames / (now - self._last_time)self._last_time = nowself._frames = 0glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)glLoadIdentity()glTranslatef(0, 0, -9)glRotatef(self.angle_x, 1, 0, 0)glRotatef(self.angle_y, 0, 1, 0)self.render_scene()def mousePressEvent(self, event):self.last_pos = event.pos()def mouseMoveEvent(self, event):if self.last_pos:dx = event.x() - self.last_pos.x()dy = event.y() - self.last_pos.y()self.angle_y += dx * 0.7self.angle_x += dy * 0.7self.last_pos = event.pos()self.update()# ========== 50種3D效果 ==========# ----------- 第1頁(常見幾何體) -----------
class SphereGL(Base3DGL):name = "漸變球體"def render_scene(self):for i in range(30):lat0 = math.pi * (-0.5 + float(i) / 30)z0 = math.sin(lat0)zr0 = math.cos(lat0)lat1 = math.pi * (-0.5 + float(i + 1) / 30)z1 = math.sin(lat1)zr1 = math.cos(lat1)glBegin(GL_QUAD_STRIP)for j in range(32):lng = 2 * math.pi * float(j) / 32x = math.cos(lng)y = math.sin(lng)c1 = abs(x)c2 = abs(y)c3 = abs(z0)glColor3f(0.5*c1+0.2, 0.2+0.5*c2, 0.4+0.5*c3)glVertex3f(x * zr0, y * zr0, z0)c3b = abs(z1)glColor3f(0.5*c1+0.3, 0.4+0.5*c2, 0.3+0.5*c3b)glVertex3f(x * zr1, y * zr1, z1)glEnd()class CubeGL(Base3DGL):name = "彩色立方體"def render_scene(self):faces = [((1,1,1), (1,1,-1), (1,-1,-1), (1,-1,1)),   # +X((-1,1,1), (-1,1,-1), (-1,-1,-1), (-1,-1,1)), # -X((1,1,1), (1,1,-1), (-1,1,-1), (-1,1,1)),   # +Y((1,-1,1), (1,-1,-1), (-1,-1,-1), (-1,-1,1)), # -Y((1,1,1), (1,-1,1), (-1,-1,1), (-1,1,1)),   # +Z((1,1,-1), (1,-1,-1), (-1,-1,-1), (-1,1,-1))  # -Z]colors = [(1,0,0), (0,1,0), (0,0,1), (1,1,0), (1,0,1), (0,1,1)]glBegin(GL_QUADS)for i, f in enumerate(faces):glColor3f(*colors[i])for v in f:glVertex3f(*v)glEnd()class OctahedronGL(Base3DGL):name = "多彩八面體"def render_scene(self):verts = [(1,0,0), (-1,0,0), (0,1,0), (0,-1,0), (0,0,1), (0,0,-1)]faces = [(0,2,4),(2,1,4),(1,3,4),(3,0,4),(0,2,5),(2,1,5),(1,3,5),(3,0,5)]colors = [(1,0,0),(0,1,0),(0,0,1),(1,1,0),(1,0,1),(0,1,1),(1,0.5,0.5),(0.5,1,0.5)]glBegin(GL_TRIANGLES)for i, f in enumerate(faces):glColor3f(*colors[i%len(colors)])for idx in f:glVertex3f(*verts[idx])glEnd()class IcosahedronGL(Base3DGL):name = "漸變二十面體"def render_scene(self):t = (1.0 + math.sqrt(5.0)) / 2.0verts = [(-1,  t,  0), ( 1,  t,  0), (-1, -t,  0), ( 1, -t,  0),( 0, -1,  t), ( 0,  1,  t), ( 0, -1, -t), ( 0,  1, -t),( t,  0, -1), ( t,  0,  1), (-t,  0, -1), (-t,  0,  1)]faces = [(0,11,5),(0,5,1),(0,1,7),(0,7,10),(0,10,11),(1,5,9),(5,11,4),(11,10,2),(10,7,6),(7,1,8),(3,9,4),(3,4,2),(3,2,6),(3,6,8),(3,8,9),(4,9,5),(2,4,11),(6,2,10),(8,6,7),(9,8,1)]glBegin(GL_TRIANGLES)for i, f in enumerate(faces):c = (i%3/2.0, (i*2)%5/5.0, (i*3)%7/7.0)glColor3f(*c)for idx in f:v = verts[idx]s = 0.6glVertex3f(v[0]*s, v[1]*s, v[2]*s)glEnd()class DodecahedronGL(Base3DGL):name = "炫彩十二面體"def render_scene(self):phi = (1 + 5 ** 0.5) / 2a, b = 1, 1/phiverts = [[+a,+a,+a], [+a,+a,-a], [+a,-a,+a], [+a,-a,-a],[-a,+a,+a], [-a,+a,-a], [-a,-a,+a], [-a,-a,-a],[0,+b+phi,+b], [0,+b+phi,-b], [0,-b-phi,+b], [0,-b-phi,-b],[+b,+0,+b+phi], [+b,+0,-b-phi], [-b,+0,+b+phi], [-b,+0,-b-phi],[+b+phi,+b,+0], [+b+phi,-b,+0], [-b-phi,+b,+0], [-b-phi,-b,+0]]faces = [[0,8,4,14,12], [0,12,16,2,10], [0,10,6,18,8], [8,18,19,5,4], [12,14,15,17,16],[2,16,17,1,13], [10,2,13,11,6], [6,11,7,19,18], [4,5,15,14], [1,17,15,5,9], [1,9,3,13], [3,11,13,9,7,19]]for i, face in enumerate(faces):glBegin(GL_POLYGON)c = [(i%3)/2.0, (i*2)%5/5.0, (i*3)%7/7.0]glColor3f(*c)for idx in face:v = verts[idx]glVertex3f(*[0.36*e for e in v])glEnd()class CylinderGL(Base3DGL):name = "三色圓柱體"def render_scene(self):N = 32for j, color in enumerate([(1,0,0), (0,1,0), (0,0,1)]):glColor3f(*color)glBegin(GL_QUAD_STRIP)for i in range(j*N//3,(j+1)*N//3+1):ang = 2*math.pi*i/Nx = math.cos(ang)y = math.sin(ang)glVertex3f(x, y, 1)glVertex3f(x, y, -1)glEnd()for z, c in [(1, (0.7,0.8,0.4)), (-1, (0.5,0.9,0.6))]:glColor3f(*c)glBegin(GL_TRIANGLE_FAN)glVertex3f(0,0,z)for i in range(N+1):ang = 2*math.pi*i/NglVertex3f(math.cos(ang), math.sin(ang), z)glEnd()class ConeGL(Base3DGL):name = "三色圓錐體"def render_scene(self):N = 32for cidx, color in enumerate([(1,0,0),(0,1,0),(0,0,1)]):glColor3f(*color)glBegin(GL_TRIANGLE_FAN)glVertex3f(0,0,1.3)for i in range(cidx*N//3,(cidx+1)*N//3+1):ang = 2*math.pi*i/NglVertex3f(math.cos(ang), math.sin(ang), -1)glEnd()glColor3f(0.2, 0.6, 0.4)glBegin(GL_TRIANGLE_FAN)glVertex3f(0,0,-1)for i in range(N+1):ang = 2*math.pi*i/NglVertex3f(math.cos(ang), math.sin(ang), -1)glEnd()class TorusGL(Base3DGL):name = "彩虹圓環體"def render_scene(self):R, r = 1.0, 0.36N, M = 32, 18for i in range(N):glBegin(GL_QUAD_STRIP)for j in range(M+1):for k in [0, 1]:s = 2 * math.pi * (i + k) / Nt = 2 * math.pi * j / Mx = (R + r * math.cos(t)) * math.cos(s)y = (R + r * math.cos(t)) * math.sin(s)z = r * math.sin(t)glColor3f(abs(math.cos(s)), abs(math.sin(t)), abs(math.cos(t)))glVertex3f(x, y, z)glEnd()class SpiralGL(Base3DGL):name = "多彩螺旋線"def render_scene(self):glBegin(GL_LINE_STRIP)for idx, t in enumerate(np.linspace(0, 6*math.pi, 120)):r = 1.1 + 0.2*math.sin(t*6)x = math.cos(t)*ry = math.sin(t)*rz = -1.1 + t/(6*math.pi)*2.2glColor3f(abs(x), abs(y), abs(z))glVertex3f(x, y, z)glEnd()class WaveSurfaceGL(Base3DGL):name = "漸變波浪面"def render_scene(self):N = 20for i in range(N):glBegin(GL_TRIANGLE_STRIP)for j in range(N+1):x = -2 + 4*i/Ny = -2 + 4*j/Nz1 = math.sin(x*3+y*3+self.angle_x*0.05)*0.5z2 = math.sin((x+4/N)*3+y*3+self.angle_y*0.06)*0.5glColor3f(0.5+0.5*j/N,0.5+0.5*i/N,0.5+0.25*(i+j)/N)glVertex3f(x, y, z1)glVertex3f(x+4/N, y, z2)glEnd()# ----------- 第2頁(函數曲面,特殊線型等) -----------
class HeartSurfaceGL(Base3DGL):name = "心形面"def render_scene(self):glBegin(GL_POINTS)for i in range(0, 90, 1):for j in range(0, 360, 3):theta = math.radians(i)phi = math.radians(j)x = 16 * math.sin(theta)**3y = 13 * math.cos(theta) - 5 * math.cos(2*theta) - 2 * math.cos(3*theta) - math.cos(4*theta)z = 16 * math.sin(theta)**3 * math.sin(phi) / 4glColor3f(abs(math.sin(theta)), abs(math.cos(phi)), abs(math.sin(phi)))glVertex3f(x * 0.07, y * 0.07, z * 0.09)glEnd()class SineWaveGL(Base3DGL):name = "三色正弦波曲面"def render_scene(self):N = 40for i in range(N):glBegin(GL_TRIANGLE_STRIP)for j in range(N+1):x = -2 + 4*i/Ny = -2 + 4*j/Nz1 = math.sin(x*4+y*4)*0.7z2 = math.sin((x+4/N)*4+y*4)*0.7glColor3f(abs(math.sin(x)), abs(math.cos(y)), abs(z1))glVertex3f(x, y, z1)glVertex3f(x+4/N, y, z2)glEnd()class SaddleGL(Base3DGL):name = "馬鞍曲面"def render_scene(self):N = 25for i in range(N):glBegin(GL_TRIANGLE_STRIP)for j in range(N+1):x = -2 + 4*i/Ny = -2 + 4*j/Nz1 = (x**2 - y**2)/4z2 = ((x+4/N)**2 - y**2)/4glColor3f(abs(z1), abs(x/2), abs(y/2))glVertex3f(x, y, z1)glVertex3f(x+4/N, y, z2)glEnd()class EggShapeGL(Base3DGL):name = "蛋形曲面"def render_scene(self):N = 24for i in range(N):lat0 = math.pi * (-0.5 + float(i) / N)z0 = math.sin(lat0)*1.2 + 0.4*math.sin(lat0)**3zr0 = math.cos(lat0)lat1 = math.pi * (-0.5 + float(i+1) / N)z1 = math.sin(lat1)*1.2 + 0.4*math.sin(lat1)**3zr1 = math.cos(lat1)glBegin(GL_QUAD_STRIP)for j in range(N+1):lng = 2 * math.pi * float(j) / Nx = math.cos(lng)y = math.sin(lng)glColor3f((j%3)/2, (i%5)/4, (j%7)/6)glVertex3f(x * zr0, y * zr0, z0)glVertex3f(x * zr1, y * zr1, z1)glEnd()class KleinBottleGL(Base3DGL):name = "克萊因瓶-彩色"def render_scene(self):N = 32for i in range(N):glBegin(GL_QUAD_STRIP)for j in range(N+1):u = 2*math.pi*i/Nv = 2*math.pi*j/Nx = (2/15)*(3+5*math.cos(u))*math.sin(u) + (2/15)*2*math.cos(u)*math.sin(v)y = (2/15)*(3+5*math.cos(u))*math.cos(u) + (2/15)*2*math.sin(u)*math.sin(v)z = (2/15)*2*math.cos(v)glColor3f(abs(math.sin(u)), abs(math.sin(v)), abs(math.cos(u)))glVertex3f(x, y, z)glEnd()class StarGL(Base3DGL):name = "星形體-三色"def render_scene(self):glBegin(GL_TRIANGLE_FAN)glColor3f(1,0,0)glVertex3f(0,0,1.1)for i in range(13):ang = i/12*2*math.pir = 1.2 if i%2==0 else 0.6glColor3f((i%3)/2,(i%4)/3,(i%5)/4)glVertex3f(r*math.cos(ang), r*math.sin(ang), -0.7)glEnd()class MobiusGL(Base3DGL):name = "莫比烏斯環"def render_scene(self):N = 60w = 0.2for i in range(N):glBegin(GL_QUAD_STRIP)for j in range(2):phi = 2*math.pi*i/Nt = -w + 2*w*jx = math.cos(phi) + t*math.cos(phi/2)*math.cos(phi)y = math.sin(phi) + t*math.cos(phi/2)*math.sin(phi)z = t*math.sin(phi/2)glColor3f(abs(math.cos(phi)), abs(math.sin(phi)), abs(t))glVertex3f(x, y, z)glEnd()class RippleGL(Base3DGL):name = "漣漪"def render_scene(self):N = 30for i in range(N):glBegin(GL_LINE_STRIP)for j in range(N+1):r = 0.2 + 1.6 * i/Ntheta = 2*math.pi*j/Nz = math.sin(r*4-theta*2)*0.3glColor3f(abs(math.sin(r)), abs(math.cos(theta)), abs(z))glVertex3f(r*math.cos(theta), r*math.sin(theta), z)glEnd()class RoseGL(Base3DGL):name = "玫瑰線"def render_scene(self):glBegin(GL_LINE_STRIP)for i in range(600):theta = i/100 * math.pir = math.sin(3*theta)*1.5x = r*math.cos(theta)y = r*math.sin(theta)z = math.cos(5*theta)glColor3f(abs(math.sin(theta)), abs(math.cos(theta)), abs(z))glVertex3f(x, y, z)glEnd()class TrefoilGL(Base3DGL):name = "三葉結"def render_scene(self):glBegin(GL_LINE_STRIP)for i in range(400):t = 2*math.pi*i/400x = math.sin(t) + 2*math.sin(2*t)y = math.cos(t) - 2*math.cos(2*t)z = -math.sin(3*t)glColor3f(abs(math.sin(t)), abs(math.cos(t)), abs(z))glVertex3f(x, y, z)glEnd()# ----------- 第3頁(動態變體/動畫) -----------
class BubbleGL(Base3DGL):name = "泡泡球"def render_scene(self):t = time.time()for i in range(12, 40, 3):glBegin(GL_LINE_LOOP)r = 1+0.2*math.sin(t+i)for j in range(32):ang = 2*math.pi*j/32x, y, z = r*math.sin(i)*math.cos(ang), r*math.sin(i)*math.sin(ang), r*math.cos(i)glColor3f(abs(math.sin(ang)), abs(math.cos(i)), abs(math.cos(ang)))glVertex3f(x/15, y/15, z/15)glEnd()class AnimatedWaveGL(Base3DGL):name = "動態波浪"def render_scene(self):t = time.time()N = 22for i in range(N):glBegin(GL_TRIANGLE_STRIP)for j in range(N+1):x = -2 + 4*i/Ny = -2 + 4*j/Nz1 = math.sin(x*2+y*2+t*2)*0.6z2 = math.sin((x+4/N)*2+y*2+t*2)*0.6glColor3f(0.5+0.5*math.sin(t+i), 0.6+0.4*math.cos(t+j), 0.6+0.4*math.cos(i+j))glVertex3f(x, y, z1)glVertex3f(x+4/N, y, z2)glEnd()class AnimatedSpiralGL(Base3DGL):name = "動畫螺旋"def render_scene(self):t = time.time()glBegin(GL_LINE_STRIP)for idx in range(120):ang = idx/20 + tr = 1.1 + 0.2*math.sin(idx*6+t)x = math.cos(ang)*ry = math.sin(ang)*rz = math.sin(t + idx/24)*0.6glColor3f(abs(math.sin(ang)), abs(math.cos(idx)), abs(z))glVertex3f(x, y, z)glEnd()class AnimatedWaveSurfaceGL(Base3DGL):name = "動畫波浪面"def render_scene(self):t = time.time()N = 18for i in range(N):glBegin(GL_TRIANGLE_STRIP)for j in range(N+1):x = -2 + 4*i/Ny = -2 + 4*j/Nz1 = math.sin(x*3+y*3+t)*0.5z2 = math.sin((x+4/N)*3+y*3+t)*0.5glColor3f(abs(math.sin(t+x)), abs(math.cos(t+y)), abs(z1))glVertex3f(x, y, z1)glVertex3f(x+4/N, y, z2)glEnd()class AnimatedTwistGL(Base3DGL):name = "動態扭曲體"def render_scene(self):t = time.time()N = 20for i in range(N):glBegin(GL_TRIANGLE_STRIP)for j in range(N+1):x = -2 + 4*i/Ny = -2 + 4*j/Nz1 = math.sin(x*3+y*3+t*1.5+i*0.2+j*0.2)*0.3z2 = math.sin((x+4/N)*3+y*3+t*1.5+i*0.2+j*0.2)*0.3glColor3f(0.5+0.5*math.sin(t+i), 0.6+0.4*math.cos(t+j), 0.8+0.2*math.cos(i+j))glVertex3f(x, y, z1)glVertex3f(x+4/N, y, z2)glEnd()class AnimatedSphereGL(Base3DGL):name = "動態呼吸球"def render_scene(self):t = time.time()for i in range(30):lat0 = math.pi * (-0.5 + float(i) / 30)z0 = math.sin(lat0)zr0 = math.cos(lat0)lat1 = math.pi * (-0.5 + float(i + 1) / 30)z1 = math.sin(lat1)zr1 = math.cos(lat1)glBegin(GL_QUAD_STRIP)for j in range(32):lng = 2 * math.pi * float(j) / 32x = math.cos(lng)y = math.sin(lng)s = 1.1 + 0.25*math.sin(t+j*0.13+i*0.11)glColor3f(abs(x), abs(y), abs(z0))glVertex3f(x * zr0 * s, y * zr0 * s, z0 * s)glVertex3f(x * zr1 * s, y * zr1 * s, z1 * s)glEnd()class AnimatedTwistTorusGL(Base3DGL):name = "動態扭曲圓環"def render_scene(self):t = time.time()R, r = 1.0, 0.36N, M = 32, 18for i in range(N):glBegin(GL_QUAD_STRIP)for j in range(M+1):for k in [0, 1]:s = 2 * math.pi * (i + k) / Nt1 = 2 * math.pi * j / M + 0.5*math.sin(t+s)x = (R + r * math.cos(t1)) * math.cos(s)y = (R + r * math.cos(t1)) * math.sin(s)z = r * math.sin(t1)glColor3f(abs(math.cos(s)), abs(math.sin(t1)), abs(math.sin(s)))glVertex3f(x, y, z)glEnd()class AnimatedExplosionGL(Base3DGL):name = "動態爆炸球"def render_scene(self):t = time.time()for i in range(20, 30):lat0 = math.pi * (-0.5 + float(i) / 30)z0 = math.sin(lat0)zr0 = math.cos(lat0)lat1 = math.pi * (-0.5 + float(i+1) / 30)z1 = math.sin(lat1)zr1 = math.cos(lat1)glBegin(GL_LINE_STRIP)for j in range(32):lng = 2 * math.pi * float(j) / 32x = math.cos(lng)y = math.sin(lng)f = 1.0+0.6*math.sin(t*2+i+j)glColor3f(abs(x*f), abs(y*f), abs(z0*f))glVertex3f(x * zr0*f, y * zr0*f, z0*f)glEnd()class AnimatedEggGL(Base3DGL):name = "動態蛋形"def render_scene(self):t = time.time()N = 24for i in range(N):lat0 = math.pi * (-0.5 + float(i) / N)z0 = math.sin(lat0)*1.2 + 0.4*math.sin(lat0+t)**3zr0 = math.cos(lat0)lat1 = math.pi * (-0.5 + float(i+1) / N)z1 = math.sin(lat1)*1.2 + 0.4*math.sin(lat1+t)**3zr1 = math.cos(lat1)glBegin(GL_QUAD_STRIP)for j in range(N+1):lng = 2 * math.pi * float(j) / Nx = math.cos(lng)y = math.sin(lng)glColor3f((j%3)/2, (i%5)/4, (j%7)/6)glVertex3f(x * zr0, y * zr0, z0)glVertex3f(x * zr1, y * zr1, z1)glEnd()class AnimatedRippleGL(Base3DGL):name = "動畫漣漪"def render_scene(self):t = time.time()N = 30for i in range(N):glBegin(GL_LINE_STRIP)for j in range(N+1):r = 0.2 + 1.6 * i/Ntheta = 2*math.pi*j/Nz = math.sin(r*4-theta*2+t*2)*0.3glColor3f(abs(math.sin(r+t)), abs(math.cos(theta)), abs(z))glVertex3f(r*math.cos(theta), r*math.sin(theta), z)glEnd()# ----------- 第4頁(極坐標/分形/特殊體) -----------
class HelixGL(Base3DGL):name = "三色螺旋彈簧"def render_scene(self):glBegin(GL_LINE_STRIP)for i in range(300):t = i/50x = math.cos(t)*1.2y = math.sin(t)*1.2z = t/4glColor3f(abs(math.sin(t)), abs(math.cos(t)), abs(z)%1)glVertex3f(x, y, z)glEnd()class HyperboloidGL(Base3DGL):name = "雙曲面"def render_scene(self):N = 30for i in range(N):glBegin(GL_LINE_LOOP)for j in range(N):u = i*2*math.pi/Nv = j*2*math.pi/Nx = math.cosh(v)*math.cos(u)y = math.cosh(v)*math.sin(u)z = math.sinh(v)glColor3f(abs(math.sin(u)), abs(math.cos(v)), abs(z)%1)glVertex3f(x/6, y/6, z/6)glEnd()class ParaboloidGL(Base3DGL):name = "拋物面"def render_scene(self):N = 30for i in range(N):glBegin(GL_LINE_LOOP)for j in range(N):u = i*2*math.pi/Nv = j*2/Nx = v*math.cos(u)y = v*math.sin(u)z = v**2glColor3f(abs(math.sin(u)), abs(math.cos(v)), abs(z)%1)glVertex3f(x, y, z/4)glEnd()class AstroidGL(Base3DGL):name = "阿斯托洛伊德"def render_scene(self):glBegin(GL_LINE_STRIP)for i in range(400):t = 2 * math.pi * i / 400x = math.cos(t)**3y = math.sin(t)**3z = math.cos(3*t)glColor3f(abs(x), abs(y), abs(z))glVertex3f(x, y, z/2)glEnd()class SuperquadricGL(Base3DGL):name = "超二次曲面"def render_scene(self):N = 32e = 0.5for i in range(N):u = -math.pi/2 + i*math.pi/Nu2 = -math.pi/2 + (i+1)*math.pi/NglBegin(GL_QUAD_STRIP)for j in range(N+1):v = -math.pi + 2*j*math.pi/Nx1 = math.copysign(abs(math.cos(u))**e, math.cos(u))*math.copysign(abs(math.cos(v))**e, math.cos(v))y1 = math.copysign(abs(math.cos(u))**e, math.cos(u))*math.copysign(abs(math.sin(v))**e, math.sin(v))z1 = math.copysign(abs(math.sin(u))**e, math.sin(u))x2 = math.copysign(abs(math.cos(u2))**e, math.cos(u2))*math.copysign(abs(math.cos(v))**e, math.cos(v))y2 = math.copysign(abs(math.cos(u2))**e, math.cos(u2))*math.copysign(abs(math.sin(v))**e, math.sin(v))z2 = math.copysign(abs(math.sin(u2))**e, math.sin(u2))glColor3f(abs(x1), abs(y1), abs(z1))glVertex3f(x1, y1, z1)glColor3f(abs(x2), abs(y2), abs(z2))glVertex3f(x2, y2, z2)glEnd()class ButterflyGL(Base3DGL):name = "蝴蝶線"def render_scene(self):glBegin(GL_LINE_STRIP)for i in range(800):t = i/50x = math.sin(t)*(math.exp(math.cos(t)) - 2*math.cos(4*t) - math.sin(t/12)**5)y = math.cos(t)*(math.exp(math.cos(t)) - 2*math.cos(4*t) - math.sin(t/12)**5)z = math.sin(3*t)glColor3f(abs(x)%1, abs(y)%1, abs(z)%1)glVertex3f(x/3, y/3, z/2)glEnd()class LissajousGL(Base3DGL):name = "利薩茹空間曲線"def render_scene(self):glBegin(GL_LINE_STRIP)for i in range(800):t = i/100x = math.sin(3*t + math.pi/2)y = math.sin(4*t)z = math.sin(5*t)glColor3f(abs(x), abs(y), abs(z))glVertex3f(x, y, z)glEnd()class VivianiGL(Base3DGL):name = "維維亞尼曲線"def render_scene(self):glBegin(GL_LINE_STRIP)for i in range(800):t = 2*math.pi*i/800x = 1 + math.cos(t)y = math.sin(t)z = 2*math.sin(t/2)glColor3f(abs(x), abs(y), abs(z/2))glVertex3f(x/2, y/2, z/2)glEnd()class HypocycloidGL(Base3DGL):name = "內擺線"def render_scene(self):glBegin(GL_LINE_STRIP)for i in range(800):t = 2*math.pi*i/800x = 2*math.cos(t) + math.cos(2*t)y = 2*math.sin(t) - math.sin(2*t)z = math.sin(3*t)glColor3f(abs(x/2), abs(y/2), abs(z/2))glVertex3f(x/2, y/2, z/2)glEnd()class EpicycloidGL(Base3DGL):name = "外擺線"def render_scene(self):glBegin(GL_LINE_STRIP)for i in range(800):t = 2*math.pi*i/800x = 2*math.cos(t) - math.cos(2*t)y = 2*math.sin(t) - math.sin(2*t)z = math.cos(3*t)glColor3f(abs(x/2), abs(y/2), abs(z/2))glVertex3f(x/2, y/2, z/2)glEnd()# ----------- 第5頁(分形/變幻/多樣體) -----------
class FernGL(Base3DGL):name = "分形蕨葉"def render_scene(self):points = []x, y = 0, 0for i in range(5000):r = np.random.random()if r < 0.01:x, y = 0, 0.16*yelif r < 0.86:x, y = 0.85*x + 0.04*y, -0.04*x + 0.85*y + 1.6elif r < 0.93:x, y = 0.2*x - 0.26*y, 0.23*x + 0.22*y + 1.6else:x, y = -0.15*x + 0.28*y, 0.26*x + 0.24*y + 0.44points.append((x, y))glBegin(GL_POINTS)for px, py in points:glColor3f(0, 0.6+0.3*px, 0.2+0.5*py)glVertex3f((px-2)*0.5, (py-3)*0.5, 0)glEnd()class SierpinskiGL(Base3DGL):name = "謝爾賓斯基地毯"def render_scene(self):def draw_carpet(x, y, s, depth):if depth == 0:glColor3f(1,0.6,0.2)glVertex3f(x, y, 0)returns /= 3for dx in [-s, 0, s]:for dy in [-s, 0, s]:if dx != 0 or dy != 0:draw_carpet(x+dx, y+dy, s, depth-1)glBegin(GL_POINTS)draw_carpet(0,0,1.0,4)glEnd()class KochCurveGL(Base3DGL):name = "科赫雪花"def render_scene(self):def koch(p1, p2, depth):if depth == 0:glColor3f(0.2,0.5,1)glVertex3f(*p1)glVertex3f(*p2)else:p3 = ((2*p1[0]+p2[0])/3, (2*p1[1]+p2[1])/3, 0)p4 = ((p1[0]+2*p2[0])/3, (p1[1]+2*p2[1])/3, 0)ang = math.atan2(p2[1]-p1[1], p2[0]-p1[0]) - math.pi/3px = p3[0] + math.cos(ang)*(abs(p4[0]-p3[0]))py = p3[1] + math.sin(ang)*(abs(p4[0]-p3[0]))p5 = (px, py, 0)koch(p1, p3, depth-1)koch(p3, p5, depth-1)koch(p5, p4, depth-1)koch(p4, p2, depth-1)glBegin(GL_LINES)koch((-0.8,0.5,0), (0.8,0.5,0), 3)koch((0.8,0.5,0), (0,-0.8,0), 3)koch((0,-0.8,0), (-0.8,0.5,0), 3)glEnd()class FractalTreeGL(Base3DGL):name = "分形樹"def render_scene(self):def draw_tree(x, y, angle, depth):if depth == 0: returnx2 = x + math.cos(angle)*depth*0.11y2 = y + math.sin(angle)*depth*0.11glColor3f(0.3,0.2+0.08*depth,0.1+0.03*depth)glVertex3f(x, y, 0)glVertex3f(x2, y2, 0)draw_tree(x2, y2, angle-math.pi/6, depth-1)draw_tree(x2, y2, angle+math.pi/6, depth-1)glBegin(GL_LINES)draw_tree(0,-0.7,math.pi/2,6)glEnd()class DragonCurveGL(Base3DGL):name = "龍曲線"def render_scene(self):def dragon(p1, p2, depth):if depth == 0:glColor3f(0.7,0.2,1)glVertex3f(*p1)glVertex3f(*p2)else:mx = (p1[0]+p2[0])/2 + (p2[1]-p1[1])/2my = (p1[1]+p2[1])/2 - (p2[0]-p1[0])/2m = (mx,my,0)dragon(p1, m, depth-1)dragon(p2, m, depth-1)glBegin(GL_LINES)dragon((-0.7,0,0), (0.7,0,0), 12)glEnd()class JuliaGL(Base3DGL):name = "Julia分形"def render_scene(self):glBegin(GL_POINTS)for ix in range(120):for iy in range(120):x = (ix-60)/40y = (iy-60)/40zx, zy = x, ycX, cY = -0.7, 0.27015n, max_n = 0, 30while zx*zx + zy*zy < 4 and n < max_n:tmp = zx*zx - zy*zy + cXzy, zx = 2*zx*zy + cY, tmpn += 1glColor3f(n/max_n, 0.2+0.6*n/max_n, 1-n/max_n)glVertex3f(x, y, 0)glEnd()class MandelbrotGL(Base3DGL):name = "Mandelbrot分形"def render_scene(self):glBegin(GL_POINTS)for ix in range(120):for iy in range(120):x0 = (ix-60)/40y0 = (iy-60)/40x, y = 0, 0n, max_n = 0, 30while x*x + y*y < 4 and n < max_n:xt = x*x - y*y + x0y = 2*x*y + y0x = xtn += 1glColor3f(n/max_n, 1-n/max_n, 0.7*n/max_n)glVertex3f(x0, y0, 0)glEnd()class PeanoGL(Base3DGL):name = "皮亞諾曲線"def render_scene(self):def peano(x, y, dx, dy, depth):if depth == 0:glColor3f(0.3+0.6*x,0.7-0.3*y,0.5+0.3*y)glVertex3f(x, y, 0)returnfor i in [0,1,2]:for j in [0,1,2]:peano(x+i*dx/3, y+j*dy/3, dx/3, dy/3, depth-1)glBegin(GL_POINTS)peano(-0.7,-0.7,1.4,1.4,3)glEnd()class CantorGL(Base3DGL):name = "康托三分集"def render_scene(self):def cantor(x, y, l, depth):if depth == 0:glColor3f(0.8,0.8,0.2)glVertex3f(x, y, 0)glVertex3f(x+l, y, 0)returnglColor3f(0.8,0.5,0.1+0.1*depth)glVertex3f(x, y, 0)glVertex3f(x+l, y, 0)cantor(x, y-0.1, l/3, depth-1)cantor(x+2*l/3, y-0.1, l/3, depth-1)glBegin(GL_LINES)cantor(-0.8, 0.8, 1.6, 6)glEnd()class PolygonFanGL(Base3DGL):name = "漸變扇形多邊形"def render_scene(self):glBegin(GL_TRIANGLE_FAN)glColor3f(1,1,1)glVertex3f(0,0,0)for i in range(31):ang = 2*math.pi*i/30glColor3f(abs(math.sin(ang)), abs(math.cos(ang)), 0.5+0.5*math.sin(ang*3))glVertex3f(math.cos(ang), math.sin(ang), 0)glEnd()# ========== 工廠函數 ==========
def get_3d_widget_by_index(idx):page1 = [SphereGL, CubeGL, OctahedronGL, IcosahedronGL, DodecahedronGL,CylinderGL, ConeGL, TorusGL, SpiralGL, WaveSurfaceGL]page2 = [HeartSurfaceGL, SineWaveGL, SaddleGL, EggShapeGL, KleinBottleGL,StarGL, MobiusGL, RippleGL, RoseGL, TrefoilGL]page3 = [BubbleGL, AnimatedWaveGL, AnimatedSpiralGL, AnimatedWaveSurfaceGL, AnimatedTwistGL,AnimatedSphereGL, AnimatedTwistTorusGL, AnimatedExplosionGL, AnimatedEggGL, AnimatedRippleGL]page4 = [HelixGL, HyperboloidGL, ParaboloidGL, AstroidGL, SuperquadricGL,ButterflyGL, LissajousGL, VivianiGL, HypocycloidGL, EpicycloidGL]page5 = [FernGL, SierpinskiGL, KochCurveGL, FractalTreeGL, DragonCurveGL,JuliaGL, MandelbrotGL, PeanoGL, CantorGL, PolygonFanGL]allcls = page1 + page2 + page3 + page4 + page5return allcls[idx]()# ========== 主窗口 ==========
class All3DEffectsGLDemo(QMainWindow):def __init__(self):super().__init__()self.setWindowTitle("50種3D效果合集(GPU+FPS+鼠標旋轉)")self.setGeometry(100, 60, 1600, 900)self.init_ui()def init_ui(self):widget = QWidget()vbox = QVBoxLayout(widget)self.setCentralWidget(widget)title = QLabel("🌈 50種3D效果演示 (OpenGL+FPS實時) 🌈")title.setFont(QFont("微軟雅黑", 24, QFont.Bold))title.setAlignment(Qt.AlignCenter)title.setStyleSheet("""color:#43e97b; background: #191a25;border-radius:14px; margin:10px; padding:20px;border: 2px solid #647dee;""")vbox.addWidget(title)tabs = QTabWidget()tabs.setTabPosition(QTabWidget.West)tabs.setStyleSheet("""QTabBar::tab {background: #232338;color: #a3e0ff;font: 16px "微軟雅黑";border: 2px solid #647dee;border-radius: 12px;margin: 6px;min-width: 110px;min-height: 50px;padding: 8px 18px;}QTabBar::tab:selected {background: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #43e97b, stop:1 #38f9d7);color: #161623;font: bold 18px "微軟雅黑";border: 3px solid #43e97b;}QTabBar::tab:hover {background: #304674;color: #fff;}QTabWidget::pane {border: 2px solid #647dee;border-radius: 16px;margin: 8px;}""")vbox.addWidget(tabs)self.widget_list = []for page in range(5):tab = QWidget()grid = QGridLayout(tab)for i in range(10):idx = page*10 + iframe = QFrame()frame.setFrameShape(QFrame.StyledPanel)frame.setStyleSheet("background:#22242e; border-radius:18px;")vlay = QVBoxLayout(frame)w = get_3d_widget_by_index(idx)self.widget_list.append(w)vlay.setContentsMargins(2,2,2,2)vlay.addWidget(w)fps_label = QLabel()fps_label.setFont(QFont("微軟雅黑", 10))fps_label.setStyleSheet("color:#43e97b; margin-left:3px;")fps_label.setAlignment(Qt.AlignLeft)vlay.addWidget(fps_label)frame.fps_label = fps_labelframe.widget = wgrid.addWidget(frame, i//5, i%5)tabs.addTab(tab, f"第{page+1}頁")for i in range(5): grid.setColumnStretch(i, 1)for i in range(2): grid.setRowStretch(i, 1)self.fps_timer = QTimer(self)self.fps_timer.timeout.connect(self.update_fps_labels)self.fps_timer.start(400)def update_fps_labels(self):for tab_index in range(5):tab = self.centralWidget().layout().itemAt(1).widget().widget(tab_index)grid = tab.layout()for i in range(10):frame = grid.itemAt(i).widget()w = frame.widgetframe.fps_label.setText(f"{w.name}\nFPS: {w.fps:.1f}")if __name__ == '__main__':app = QApplication(sys.argv)app.setStyle("Fusion")palette = QPalette()palette.setColor(QPalette.Window, QColor("#191a25"))palette.setColor(QPalette.WindowText, QColor("#e0eafc"))app.setPalette(palette)win = All3DEffectsGLDemo()win.show()sys.exit(app.exec_())

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/84913.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/84913.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/84913.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Java大模型開發入門 (6/15):對話的靈魂 - 深入理解LangChain4j中的模型、提示和解析器

前言 在上一篇文章中&#xff0c;我們見證了AiService注解的驚人威力。僅僅通過定義一個Java接口&#xff0c;我們就實現了一個功能完備的AI聊天服務。這感覺就像魔法一樣&#xff01; 但作為專業的工程師&#xff0c;我們知道“任何足夠先進的技術&#xff0c;都與魔法無異”…

用Rust如何構建高性能爬蟲

習慣了使用Python來寫爬蟲&#xff0c;如果使用Rust需要有哪些考量&#xff1f; 根據我了解的Rust 在性能、資源效率和并發處理方面完勝 Python&#xff0c;但是 Python 在開發速度和生態成熟度上占優。所以說&#xff0c;具體用那種模式&#xff0c;結合你項目特點做個詳細的…

CentOS7報錯:Cannot find a valid baseurl for repo: base/7/x86_64

這個錯誤通常出現在 CentOS/RHEL 7 系統中&#xff0c;當你嘗試運行 yum update 或 yum install 時&#xff0c;系統無法連接到默認的軟件倉庫&#xff08;repository&#xff09;。 可能的原因 網絡連接問題&#xff1a;系統無法訪問互聯網或倉庫服務器。錯誤的倉庫配置&…

云平臺|Linux部分指令

目錄 云平臺 操作系統&#xff08;鏡像&#xff09; 管理應用實例 遠程連接 遠程連接工具 linux相關命令&#xff08;重點&#xff09; 云平臺 1、阿里云&#xff08;學生免費&#xff0c;不包流量 流量0.8---1G&#xff09; 2、騰訊云&#xff08;搶&#xff09; 3、華…

AI首次自主發現人工生命

轉&#xff1a; 近日&#xff0c;人工智能領域迎來了一項革命性的突破。Transformer 論文作者之一的 Llion Jones 與前谷歌研究人員 David Ha 共同創立的人工智能公司 Sakana AI&#xff0c;聯合MIT、OpenAI、瑞士AI實驗室IDSIA等機構的研究人員&#xff0c;共同提出了一種名為…

Day.31

變量類型&#xff1a; name: str "Alice" age: int 30 height: float 1.75 is_student: bool False 注解&#xff1a; def add(a: int, b: int) -> int: return a b def greet(name: str) -> None: print(f"Hello, {name}") 定義矩形類&a…

光譜數據分析的方法有哪些?

光譜數據分析是通過特征光譜識別物質結構與成分的核心技術&#xff0c;其標準化流程如下&#xff1a; ?一、數據預處理?&#xff08;消除干擾噪聲&#xff09; ?去噪平滑? Savitzky-Golay濾波&#xff1a;保留光譜特征峰形&#xff0c;消除高頻噪聲。 移動平均法&#…

RabbitMQ的使用--Spring AMQP(更新中)

1.首先是創建項目 在一個父工程 mq_demo 的基礎上建立兩個子模塊&#xff0c;生產者模塊publisher&#xff0c;消費者模塊 consumer 創建項目&#xff1a; 建立成功&#xff1a; 刪除多余文件 創建子模塊1&#xff1a;publisher&#xff08;生產者模塊&#xff09; 右鍵---…

DAY 31 文件的規范拆分和寫法

浙大疏錦行 今日的示例代碼包含2個部分 notebook文件夾內的ipynb文件&#xff0c;介紹下今天的思路項目文件夾中其他部分&#xff1a;拆分后的信貸項目&#xff0c;學習下如何拆分的&#xff0c;未來你看到的很多大項目都是類似的拆分方法 知識點回顧 規范的文件命名規范的文件…

EtherCAT至TCP/IP異構網絡互聯:施耐德M580 PLC對接倍福CX5140解決方案

一、項目背景與需求 某智能工廠致力于打造高度自動化的生產流水線&#xff0c;其中部分核心設備采用EtherCAT協議進行通信&#xff0c;以實現高速、高精度的控制&#xff0c;例如基于EtherCAT總線的倍福&#xff08;Beckhoff&#xff09;CX5140PLC&#xff0c;它能夠快速響應設…

[學習] FIR多項濾波器的數學原理詳解:從多相分解到高效實現(完整仿真代碼)

FIR多項濾波器的數學原理詳解&#xff1a;從多相分解到高效實現 文章目錄 FIR多項濾波器的數學原理詳解&#xff1a;從多相分解到高效實現引言一、FIR濾波器基礎與多相分解原理1.1 FIR濾波器數學模型1.2 多相分解的數學推導1.3 多相分解的物理意義 二、插值應用中的數學原理2.1…

Java并發編程實戰 Day 22:高性能無鎖編程技術

【Java并發編程實戰 Day 22】高性能無鎖編程技術 文章簡述 在高并發場景下&#xff0c;傳統的鎖機制&#xff08;如synchronized、ReentrantLock&#xff09;雖然能夠保證線程安全&#xff0c;但在高競爭環境下容易引發性能瓶頸。本文深入探討無鎖編程技術&#xff0c;重點介紹…

打破語言壁壘!DHTMLX Gantt 與 Scheduler 文檔正式上線中文等多語言版本!

你還在為英文技術文檔望而卻步嗎&#xff1f;現在好消息來了&#xff01;DHTMLX 團隊宣布&#xff0c;其兩款明星組件——DHTMLX Gantt&#xff08;甘特圖&#xff09;與 DHTMLX Scheduler&#xff08;日程排程器&#xff09;的官方文檔&#xff0c;現已全面支持中文、德語、韓…

無監督 vs 有監督的本質區別

一、無監督 vs 有監督的本質區別 1. 無監督學習 定義&#xff1a;數據中沒有人為標注的 “正確答案”&#xff08;如類別標簽、目標值&#xff09;&#xff0c;模型需自己發現數據中的模式。任務目標&#xff1a;學習數據的分布規律、結構或生成邏輯。例子&#xff1a; 文本續…

【Linux】初見,進程概念

前言&#xff1a; 上文我們講到了Linux下的第一個程序&#xff1a;進度條 【Linux】LInux下第一個程序&#xff1a;進度條-CSDN博客 本文我們來講一講Linux中下一個非常重要的東西&#xff1a;進程 1.馮諾依曼體系結構 我們所見的大部分計算機都是遵循的馮諾依曼體系結構…

Linux進程間通信(IPC)詳解:從入門到理解

引言 作為一名C開發初學者&#xff0c;理解Linux下的進程間通信&#xff08;Inter-Process Communication&#xff0c;簡稱IPC&#xff09;機制是非常重要的一步。本文將用通俗易懂的語言&#xff0c;配合直觀的圖示&#xff0c;幫助你理解Linux進程間通信的基本概念和各種實現…

SQL進階之旅 Day 27:存儲過程與函數高級應用

【SQL進階之旅 Day 27】存儲過程與函數高級應用 文章簡述 在數據庫開發中&#xff0c;存儲過程和函數是實現復雜業務邏輯、提高代碼復用性和提升系統性能的重要工具。本文作為“SQL進階之旅”系列的第27天&#xff0c;深入探討存儲過程與函數的高級應用&#xff0c;涵蓋其設計…

泰國零售巨頭 CJ Express 借助 SAP 內存數據庫實現高效數據管理

泰國 CJ Express 運用 SAP 內存數據庫有效控制數據增長案例 “Datavard Outboard 操作簡便、配置輕松&#xff0c;我們得以在生產系統上完成數據歸檔&#xff0c;成功將約 730GB 數據遷移至 Hadoop 集群。”——K. Jak&#xff0c;J Express 技術服務經理 關于 CJ Express …

ImageSharp.Web 使用指南:高效處理ASP.NET Core中的圖像

文章目錄 前言一、ImageSharp.Web簡介二、安裝與配置1. 安裝NuGet包2. 基本配置3. 高級配置 三、核心功能與使用示例1. 基本圖像處理2. 處理模式詳解3. 自定義處理命令 四、緩存策略1. 物理文件系統緩存2. 分布式緩存3. 自定義緩存 五、性能優化建議六、常見問題解決1. 圖像處理…

使用R進行數字信號處理:嬰兒哭聲分析深度解析

音頻信號處理將原始聲音數據轉化為有意義的洞見&#xff0c;適用于語音分析、生物聲學和醫學診斷等領域。使用R語言&#xff0c;我們可以處理音頻文件、可視化頻率內容&#xff0c;并生成如聲譜圖等詳細圖表。本指南將展示如何使用R包tuneR、seewave和rpanel分析嬰兒哭聲音頻文…