opengl3d-demo.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. import time
  2. import pygame
  3. import math
  4. import os
  5. from pygame.locals import *
  6. from OpenGL.GL import *
  7. from OpenGL.GLU import *
  8. # 初始化 Pygame
  9. pygame.init()
  10. # 设置窗口大小
  11. width, height = 800, 600
  12. display = pygame.display.set_mode((width, height), DOUBLEBUF | OPENGL)
  13. pygame.display.set_caption('3D Sphere')
  14. # 初始化剪贴板系统
  15. pygame.scrap.init()
  16. # 启用深度测试
  17. glEnable(GL_DEPTH_TEST)
  18. # 设置光照
  19. glEnable(GL_LIGHTING)
  20. glEnable(GL_LIGHT0)
  21. # 设置光源位置
  22. light_position = [1.0, 1.0, 1.0, 0.0] # directional light
  23. glLightfv(GL_LIGHT0, GL_POSITION, light_position)
  24. # 设置材质属性
  25. material_ambient = [0.3, 0.7, 0.3, 1.0]
  26. material_diffuse = [0.0, 1.0, 0.0, 1.0]
  27. material_specular = [0.3, 0.7, 0.3, 1.0]
  28. material_shininess = [50.0]
  29. glMaterialfv(GL_FRONT, GL_AMBIENT, material_ambient)
  30. glMaterialfv(GL_FRONT, GL_DIFFUSE, material_diffuse)
  31. glMaterialfv(GL_FRONT, GL_SPECULAR, material_specular)
  32. glMaterialfv(GL_FRONT, GL_SHININESS, material_shininess)
  33. # 设置视角
  34. gluPerspective(45, (width/height), 0.1, 50.0)
  35. # 移动相机
  36. glTranslatef(0.0, 0.0, -5)
  37. # 文件夹结构
  38. folder_structure = []
  39. show_structure = False
  40. # 检查剪贴板内容
  41. def check_clipboard():
  42. clipboard = pygame.scrap.get('text/plain')
  43. if clipboard:
  44. path = clipboard.decode('utf-8').strip()
  45. if os.path.exists(path) and os.path.isdir(path):
  46. return path
  47. return None
  48. # 扫描文件夹函数(递归)
  49. def scan_folder(path, parent_distance=2, parent_angle=0, depth=0, max_depth=3):
  50. structure = []
  51. if depth >= max_depth:
  52. return structure
  53. if os.path.exists(path) and os.path.isdir(path):
  54. items = os.listdir(path)
  55. for i, item in enumerate(items):
  56. item_path = os.path.join(path, item)
  57. is_dir = os.path.isdir(item_path)
  58. # 计算位置
  59. angle = parent_angle + (i / len(items)) * 360
  60. distance = parent_distance + 1
  61. radius = 0.2 if is_dir else 0.1
  62. # 添加当前项目
  63. structure.append({
  64. 'name': item,
  65. 'path': item_path,
  66. 'is_dir': is_dir,
  67. 'angle': angle,
  68. 'distance': distance,
  69. 'radius': radius,
  70. 'parent_distance': parent_distance,
  71. 'parent_angle': parent_angle
  72. })
  73. # 递归扫描子文件夹
  74. if is_dir:
  75. structure.extend(scan_folder(item_path, distance, angle, depth + 1, max_depth))
  76. return structure
  77. # 使用默认路径 E:\myaliyun\IamHere
  78. default_path = "E:\\myaliyun\\IamHere"
  79. if os.path.exists(default_path) and os.path.isdir(default_path):
  80. folder_structure = scan_folder(default_path)
  81. show_structure = True
  82. else:
  83. # 启动时检查剪贴板
  84. clipboard_path = check_clipboard()
  85. if clipboard_path:
  86. folder_structure = scan_folder(clipboard_path)
  87. show_structure = True
  88. # 主循环
  89. running = True
  90. while running:
  91. # time.sleep(100)
  92. # 处理事件
  93. for event in pygame.event.get():
  94. if event.type == pygame.QUIT:
  95. running = False
  96. # 清除屏幕
  97. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
  98. # 旋转大球
  99. glRotatef(1, 3, 1, 1)
  100. # 绘制大球
  101. quad = gluNewQuadric()
  102. gluQuadricNormals(quad, GLU_SMOOTH)
  103. gluSphere(quad, 1, 32, 32)
  104. gluDeleteQuadric(quad)
  105. print(folder_structure)
  106. # 绘制文件夹结构
  107. if show_structure:
  108. for item in folder_structure:
  109. # 计算当前项目位置
  110. angle_rad = math.radians(item['angle'])
  111. x = item['distance'] * math.cos(angle_rad)
  112. y = item['distance'] * math.sin(angle_rad)
  113. z = 0
  114. # 计算父项目位置
  115. parent_angle_rad = math.radians(item['parent_angle'])
  116. parent_x = item['parent_distance'] * math.cos(parent_angle_rad)
  117. parent_y = item['parent_distance'] * math.sin(parent_angle_rad)
  118. parent_z = 0
  119. # 绘制连线(连接到父项目)
  120. glBegin(GL_LINES)
  121. glVertex3f(parent_x, parent_y, parent_z) # 父项目位置
  122. glVertex3f(x, y, z) # 当前项目位置
  123. glEnd()
  124. # 保存当前矩阵
  125. glPushMatrix()
  126. # 移动到当前项目位置
  127. glTranslatef(x, y, z)
  128. # 设置材质颜色(文件夹为绿色,文件为蓝色)
  129. if item['is_dir']:
  130. glMaterialfv(GL_FRONT, GL_DIFFUSE, [0.0, 1.0, 0.0, 1.0])
  131. else:
  132. glMaterialfv(GL_FRONT, GL_DIFFUSE, [0.0, 0.0, 1.0, 1.0])
  133. # 绘制小球
  134. quad = gluNewQuadric()
  135. gluQuadricNormals(quad, GLU_SMOOTH)
  136. gluSphere(quad, item['radius'], 16, 16)
  137. gluDeleteQuadric(quad)
  138. # 恢复材质颜色
  139. glMaterialfv(GL_FRONT, GL_DIFFUSE, material_diffuse)
  140. # 恢复矩阵
  141. glPopMatrix()
  142. # 更新角度
  143. item['angle'] = (item['angle'] + 1) % 360
  144. # 交换缓冲区
  145. pygame.display.flip()
  146. # 控制帧率
  147. pygame.time.wait(10)
  148. # 退出 Pygame
  149. pygame.quit()