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 = None
        self.angle_x, self.angle_y = 20, 20
        self.fps = 0
        self._frames = 0
        self._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 += 1
        now = time.time()
        if now - self._last_time > 1.0:
            self.fps = self._frames / (now - self._last_time)
            self._last_time = now
            self._frames = 0
        glClear(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.7
            self.angle_x += dy * 0.7
            self.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) / 32
                x = 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.0
        verts = [
            (-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.6
                glVertex3f(v[0]*s, v[1]*s, v[2]*s)
        glEnd()

class DodecahedronGL(Base3DGL):
    name = "炫彩十二面体"
    def render_scene(self):
        phi = (1 + 5 ** 0.5) / 2
        a, b = 1, 1/phi
        verts = [
            [+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 = 32
        for 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/N
                x = 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/N
                glVertex3f(math.cos(ang), math.sin(ang), z)
            glEnd()

class ConeGL(Base3DGL):
    name = "三色圆锥体"
    def render_scene(self):
        N = 32
        for 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/N
                glVertex3f(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/N
            glVertex3f(math.cos(ang), math.sin(ang), -1)
        glEnd()

class TorusGL(Base3DGL):
    name = "彩虹圆环体"
    def render_scene(self):
        R, r = 1.0, 0.36
        N, M = 32, 18
        for 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) / N
                    t = 2 * math.pi * j / M
                    x = (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)*r
            y = math.sin(t)*r
            z = -1.1 + t/(6*math.pi)*2.2
            glColor3f(abs(x), abs(y), abs(z))
            glVertex3f(x, y, z)
        glEnd()

class WaveSurfaceGL(Base3DGL):
    name = "渐变波浪面"
    def render_scene(self):
        N = 20
        for i in range(N):
            glBegin(GL_TRIANGLE_STRIP)
            for j in range(N+1):
                x = -2 + 4*i/N
                y = -2 + 4*j/N
                z1 = math.sin(x*3+y*3+self.angle_x*0.05)*0.5
                z2 = math.sin((x+4/N)*3+y*3+self.angle_y*0.06)*0.5
                glColor3f(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)**3
                y = 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) / 4
                glColor3f(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 = 40
        for i in range(N):
            glBegin(GL_TRIANGLE_STRIP)
            for j in range(N+1):
                x = -2 + 4*i/N
                y = -2 + 4*j/N
                z1 = math.sin(x*4+y*4)*0.7
                z2 = math.sin((x+4/N)*4+y*4)*0.7
                glColor3f(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 = 25
        for i in range(N):
            glBegin(GL_TRIANGLE_STRIP)
            for j in range(N+1):
                x = -2 + 4*i/N
                y = -2 + 4*j/N
                z1 = (x**2 - y**2)/4
                z2 = ((x+4/N)**2 - y**2)/4
                glColor3f(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 = 24
        for i in range(N):
            lat0 = math.pi * (-0.5 + float(i) / N)
            z0 = math.sin(lat0)*1.2 + 0.4*math.sin(lat0)**3
            zr0 = math.cos(lat0)
            lat1 = math.pi * (-0.5 + float(i+1) / N)
            z1 = math.sin(lat1)*1.2 + 0.4*math.sin(lat1)**3
            zr1 = math.cos(lat1)
            glBegin(GL_QUAD_STRIP)
            for j in range(N+1):
                lng = 2 * math.pi * float(j) / N
                x = 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 = 32
        for i in range(N):
            glBegin(GL_QUAD_STRIP)
            for j in range(N+1):
                u = 2*math.pi*i/N
                v = 2*math.pi*j/N
                x = (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.pi
            r = 1.2 if i%2==0 else 0.6
            glColor3f((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 = 60
        w = 0.2
        for i in range(N):
            glBegin(GL_QUAD_STRIP)
            for j in range(2):
                phi = 2*math.pi*i/N
                t = -w + 2*w*j
                x = 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 = 30
        for i in range(N):
            glBegin(GL_LINE_STRIP)
            for j in range(N+1):
                r = 0.2 + 1.6 * i/N
                theta = 2*math.pi*j/N
                z = math.sin(r*4-theta*2)*0.3
                glColor3f(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.pi
            r = math.sin(3*theta)*1.5
            x = 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/400
            x = 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/32
                x, 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 = 22
        for i in range(N):
            glBegin(GL_TRIANGLE_STRIP)
            for j in range(N+1):
                x = -2 + 4*i/N
                y = -2 + 4*j/N
                z1 = math.sin(x*2+y*2+t*2)*0.6
                z2 = math.sin((x+4/N)*2+y*2+t*2)*0.6
                glColor3f(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 + t
            r = 1.1 + 0.2*math.sin(idx*6+t)
            x = math.cos(ang)*r
            y = math.sin(ang)*r
            z = math.sin(t + idx/24)*0.6
            glColor3f(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 = 18
        for i in range(N):
            glBegin(GL_TRIANGLE_STRIP)
            for j in range(N+1):
                x = -2 + 4*i/N
                y = -2 + 4*j/N
                z1 = math.sin(x*3+y*3+t)*0.5
                z2 = math.sin((x+4/N)*3+y*3+t)*0.5
                glColor3f(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 = 20
        for i in range(N):
            glBegin(GL_TRIANGLE_STRIP)
            for j in range(N+1):
                x = -2 + 4*i/N
                y = -2 + 4*j/N
                z1 = math.sin(x*3+y*3+t*1.5+i*0.2+j*0.2)*0.3
                z2 = math.sin((x+4/N)*3+y*3+t*1.5+i*0.2+j*0.2)*0.3
                glColor3f(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) / 32
                x = 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.36
        N, M = 32, 18
        for 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) / N
                    t1 = 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) / 32
                x = 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 = 24
        for i in range(N):
            lat0 = math.pi * (-0.5 + float(i) / N)
            z0 = math.sin(lat0)*1.2 + 0.4*math.sin(lat0+t)**3
            zr0 = math.cos(lat0)
            lat1 = math.pi * (-0.5 + float(i+1) / N)
            z1 = math.sin(lat1)*1.2 + 0.4*math.sin(lat1+t)**3
            zr1 = math.cos(lat1)
            glBegin(GL_QUAD_STRIP)
            for j in range(N+1):
                lng = 2 * math.pi * float(j) / N
                x = 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 = 30
        for i in range(N):
            glBegin(GL_LINE_STRIP)
            for j in range(N+1):
                r = 0.2 + 1.6 * i/N
                theta = 2*math.pi*j/N
                z = math.sin(r*4-theta*2+t*2)*0.3
                glColor3f(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/50
            x = math.cos(t)*1.2
            y = math.sin(t)*1.2
            z = t/4
            glColor3f(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 = 30
        for i in range(N):
            glBegin(GL_LINE_LOOP)
            for j in range(N):
                u = i*2*math.pi/N
                v = j*2*math.pi/N
                x = 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 = 30
        for i in range(N):
            glBegin(GL_LINE_LOOP)
            for j in range(N):
                u = i*2*math.pi/N
                v = j*2/N
                x = v*math.cos(u)
                y = v*math.sin(u)
                z = v**2
                glColor3f(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 / 400
            x = math.cos(t)**3
            y = math.sin(t)**3
            z = 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 = 32
        e = 0.5
        for i in range(N):
            u = -math.pi/2 + i*math.pi/N
            u2 = -math.pi/2 + (i+1)*math.pi/N
            glBegin(GL_QUAD_STRIP)
            for j in range(N+1):
                v = -math.pi + 2*j*math.pi/N
                x1 = 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/50
            x = 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/100
            x = 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/800
            x = 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/800
            x = 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/800
            x = 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, 0
        for i in range(5000):
            r = np.random.random()
            if r < 0.01:
                x, y = 0, 0.16*y
            elif r < 0.86:
                x, y = 0.85*x + 0.04*y, -0.04*x + 0.85*y + 1.6
            elif r < 0.93:
                x, y = 0.2*x - 0.26*y, 0.23*x + 0.22*y + 1.6
            else:
                x, y = -0.15*x + 0.28*y, 0.26*x + 0.24*y + 0.44
            points.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)
                return
            s /= 3
            for 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/3
                px = 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: return
            x2 = x + math.cos(angle)*depth*0.11
            y2 = y + math.sin(angle)*depth*0.11
            glColor3f(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])/2
                my = (p1[1]+p2[1])/2 - (p2[0]-p1[0])/2
                m = (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)/40
                y = (iy-60)/40
                zx, zy = x, y
                cX, cY = -0.7, 0.27015
                n, max_n = 0, 30
                while zx*zx + zy*zy < 4 and n < max_n:
                    tmp = zx*zx - zy*zy + cX
                    zy, zx = 2*zx*zy + cY, tmp
                    n += 1
                glColor3f(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)/40
                y0 = (iy-60)/40
                x, y = 0, 0
                n, max_n = 0, 30
                while x*x + y*y < 4 and n < max_n:
                    xt = x*x - y*y + x0
                    y = 2*x*y + y0
                    x = xt
                    n += 1
                glColor3f(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)
                return
            for 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)
                return
            glColor3f(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/30
            glColor3f(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 + page5
    return 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 + i
                frame = 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_label
                frame.widget = w
                grid.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.widget
                frame.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_())
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值