opengl3d.py 5.2 KB

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