결과물은 위와 같다.
태양, 지구, 명왕성, 그리고 지구를 회전하는 인공위성이 있다.
인공위성은 공전축이 매 회전마다 조금씩 바뀌고
명왕성은 공전궤도가 타원이다.
왼쪽위부터
태양계 전체를 보는 화면,
태양에서 12시 방향의 우주,
명왕성에서 본 지구,
지구의 한국에서 본 하늘
을 표현하고 있다.
constant.py는 전역변수들을 저장하고 있다.
물론 이것도 과제다.
main.py
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
from constant import *
import math
def drawSatellite():
global satelliteRevolveAxisCount
global satelliteNowX
global satelliteNowY
global satelliteNowZ
glColor3fv(satelliteColor)
distance = satelliteDistance
#인공위성 궤도 그리기
for k in range(0, 6):
glPushMatrix()
glRotate(satelliteRevolveAxisPeriod, 0, 0, 1)
glBegin(GL_LINE_STRIP)
for i in range(0, 361):
theta = 2.0 * 3.141592 * i / 360.0
x = distance * math.cos(theta)
y = distance * math.sin(theta)
#z = 2.0 * math.pi * satelliteRevolveAxisPeriod * theta / 360.0
glVertex3f(x, 0, y)
glEnd()
for k in range(0,6) : glPopMatrix()
if(satelliteRevolveAngle >= satelliteRevolveAxisCount * math.pi * 2):
satelliteRevolveAxisCount += 1
glPushMatrix()
theta = satelliteRevolveAxisPeriod * (satelliteRevolveAxisCount - 1)
glRotate(theta , 0, 0, 1)
nowx = distance * math.cos(satelliteRevolveAngle + startingAngle / 2)
nowz = distance * math.sin(satelliteRevolveAngle + startingAngle / 2)
glTranslatef(nowx, 0, nowz)
glRotate(90.0, 0,0,1)
glScale(0.5,0.5,0.5)
glutSolidTetrahedron()
glPopMatrix()
def drawPluto():
global plutoNowX
global plutoNowZ
global plutoYear
global plutoDay
glColor3fv(plutoColor)
glBegin(GL_LINE_STRIP)
for i in range(0, 361):
theta = 2.0 * 3.141592 * i / 360.0
x = plutoDistance_b * math.cos(theta)
y = plutoDistance_a * math.sin(theta)
glVertex3f(x, 0, y)
glEnd()
nowx = plutoDistance_b * math.cos(math.pi * 2 - plutoRevolveAngle + startingAngle)
nowz = plutoDistance_a * math.sin(math.pi * 2 - plutoRevolveAngle + startingAngle)
glPushMatrix()
glTranslatef(nowx, 0, nowz) #공전 위치로 이동
glRotate(plutoRotateAngle, 0, 1, 0) #자전
if(plutoRotateAngle >= 360 * (plutoDay+1)):
plutoDay += 1
if(plutoRevolveAngle >= math.pi * 2 * (plutoYear +1)):
plutoYear +=1
glutSolidDodecahedron()
glPopMatrix()
plutoNowX = nowx
plutoNowZ = nowz
def drawEarth(earthRevolveAngle, earthRotationAngle):
global earthNowX
global earthNowZ
global earthYear
global earthDay
distance = earthDistance
glColor3fv(earthColor)
glBegin(GL_LINE_STRIP)
for i in range(0, 361):
theta = 2.0 * 3.141592 * i / 360.0
x = distance * math.cos(theta)
y = distance * math.sin(theta)
glVertex3f(x, 0, y)
glEnd()
nowx = distance * math.cos(math.pi * 2 - earthRevolveAngle + startingAngle) #math.pi를 더하는 이유는 오른쪽에서 시작하기 위해서.
nowz = distance * math.sin(math.pi * 2 - earthRevolveAngle + startingAngle)
glPushMatrix()
glTranslatef(nowx, 0, nowz) #공전 위치로 이동
glPushMatrix()
drawSatellite() #인공위성 그리기
glPopMatrix()
glRotatef(earthRotationAxis, 0, 0, 1) #자전축만큼 기욺
glRotatef(earthRotationAngle, 0, 1, 0) #자전 시행
glColor3fv(earthColor)
glutSolidCube(earthRadius)
if(earthRotationAngle >= 360 * (earthDay+1)):
earthDay += 1
if(earthRevolveAngle >= math.pi * 2 * (earthYear +1)):
earthYear +=1
glPopMatrix()
earthNowX = nowx
earthNowZ = nowz
def drawScene():
# drawing
# sun
glColor3f(1, 0, 0)
glutSolidSphere(sunRadius, 20, 20)
# earth
drawEarth(earthRevolveAngle, earthRotationAngle)
#pluto
drawPluto()
def disp(): # reset buffer
global earthRevolveAngle
global earthRotationAngle
global satelliteRevolveAngle
global satelliteRevolveAxisCount
global plutoRevolveAngle
global plutoRotateAngle
global satelliteNowZ
global satelliteNowY
global satelliteNowX
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
startTime = 0.0
endTime = 0.0
startTime = glutGet(GLUT_ELAPSED_TIME)
while(True):
endTime = glutGet(GLUT_ELAPSED_TIME)
if(pause): break
if(endTime - startTime >= 10):
earthRevolveAngle += earthRevolveSpeed / 100
earthRotationAngle += earthRotationSpeed / 100
satelliteRevolveAngle += satelliteRevolveSpeed / 100
plutoRevolveAngle += plutoRevolveSpeed / 100
plutoRotateAngle += plutoRotateSpeed / 100
break;
glClear(GL_COLOR_BUFFER_BIT)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(30, 1.0, 0.1, 1000)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
korea = math.pi / 12
xD = math.cos(earthRotationAngle / angleSpeedConstant) * math.cos(korea) * earthRadius
yD = math.sin(korea) * earthRadius
zD = math.sin(earthRotationAngle / angleSpeedConstant) * math.cos(korea) * earthRadius
xDelta = xD * math.cos(earthRotationAxis / angleSpeedConstant) - yD * math.sin(earthRotationAxis / angleSpeedConstant)
yDelta = xD * math.sin(earthRotationAxis / angleSpeedConstant) + yD * math.cos(earthRotationAxis / angleSpeedConstant)
zDelta = zD
camToX = earthNowX + xDelta * 2
camToY = yDelta * 2
camToZ = earthNowZ + zDelta * 2
cameraX = earthNowX + xDelta
cameraY = yDelta
cameraZ = earthNowZ + zDelta
theta = satelliteRevolveAxisPeriod * (satelliteRevolveAxisCount - 1)
satelliteNowX = 0.0
satelliteNowY = 0.0
satelliteNowZ = 0.0
satelliteNowX = satelliteDistance * math.cos(satelliteRevolveAngle + startingAngle / 2)
satelliteNowZ = satelliteDistance * math.sin(satelliteRevolveAngle + startingAngle / 2)
xD = satelliteNowX * math.cos(theta / angleSpeedConstant) - satelliteNowY * math.sin(theta / angleSpeedConstant)
yD = satelliteNowX * math.sin(theta / angleSpeedConstant) + satelliteNowY * math.cos(theta / angleSpeedConstant)
satelliteNowX = xD
satelliteNowY = yD
satelliteNowX += earthNowX
satelliteNowZ += earthNowZ
#2사분면
glViewport(WINDOW_POSITION_X, WINDOW_POSITION_Y + int(WINDOW_HEIGHT / 2), int(WINDOW_WIDTH / 2), int(WINDOW_HEIGHT / 2))
glPushMatrix()
gluLookAt(0, 120 * ViewDist, -170 * ViewDist, 0, 0, 0, 0, 1, 0)
drawScene()
earthText = "Eyear = " + str(earthYear) + " , Eday = " + str(earthDay)
plutoText = "Pyear = " + str(plutoYear) + " , Pday = " + str(plutoDay)
displayText(45*ViewDist, 50*ViewDist, 0, earthText)
displayText(0*ViewDist, 50*ViewDist, 0, plutoText)
glPopMatrix()
#1사분면
glViewport(int(WINDOW_POSITION_X + WINDOW_WIDTH / 2), WINDOW_POSITION_Y + int(WINDOW_HEIGHT / 2), int(WINDOW_WIDTH / 2), int(WINDOW_HEIGHT / 2))
glPushMatrix()
gluLookAt(0, 0, sunRadius + 0.1, 0, 0, 100, 0, 1, 0)
drawScene()
glPopMatrix()
#3사분면
glViewport(WINDOW_POSITION_X, WINDOW_POSITION_Y, int(WINDOW_WIDTH / 2), int(WINDOW_HEIGHT / 2))
glPushMatrix()
gluLookAt(plutoNowX, plutoRadius, plutoNowZ, earthNowX, 0, earthNowZ, 0, 1, 0)
drawScene()
glPopMatrix()
#4사분면
glViewport(int(WINDOW_POSITION_X + WINDOW_WIDTH / 2), WINDOW_POSITION_Y, int(WINDOW_WIDTH / 2), int(WINDOW_HEIGHT / 2))
glPushMatrix()
if(LookToEarth):
gluLookAt(satelliteNowX, satelliteNowY+1, satelliteNowZ, earthNowX, 0, earthNowZ, 0, 1, 0)
else:
gluLookAt(cameraX, cameraY, cameraZ, camToX, camToY, camToZ, 0, 1, 0)
drawScene()
glPopMatrix()
glFlush()
def keyboardEvent(key, x, y):
global pause
global globalSpeed
global LookToEarth
global ViewDist
if(key == b'h' or key == b'H'):
pause = ~pause
if(key == b'q' or key == b'Q'):
exit()
if(key == b't' or key == b'T'):
LookToEarth = ~LookToEarth
if(key == b'-'):
if(ViewDist <= 3.0):
ViewDist += 0.1
if(key == b'+'):
if(ViewDist >= 0.2):
ViewDist -= 0.1
def displayText(x,y,z, str) :
glRasterPos3f(x,y,z)
for ch in str:
glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, ord(ch))
# windowing
glutInit(sys.argv)
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB)
glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT)
glutInitWindowPosition(WINDOW_POSITION_X, WINDOW_POSITION_Y)
glutCreateWindow(b"Simple Solar")
glClearColor(0, 0.0, 0.0, 0)
glEnable(GL_DEPTH_TEST)
# register callbacks
glutDisplayFunc(disp)
glutIdleFunc(disp)
glutKeyboardFunc(keyboardEvent)
# enter main infinite-loop
glutMainLoop()
constant.py
import math
WINDOW_WIDTH = 1000
WINDOW_HEIGHT = 1000
WINDOW_POSITION_X = 0
WINDOW_POSITION_Y = 0
pause = False
LookToEarth = False
angleSpeedConstant = 360.0 / math.pi / 2
globalSpeed = 2 #배속
startingAngle = math.pi
sunRadius = 2.0
ViewDist = 1.0
#earth
earthRevolveAngle = 0.0 #공전
earthRevolveSpeed = 90.0 / angleSpeedConstant * globalSpeed #초당 변화할 angle #4초에 한바퀴
earthRotationAngle = 0.0 #자전
earthRotationSpeed = 360.0 * globalSpeed
earthRotationAxis = 15.0 #자전축
earthRadius = 1.5
earthDistance = 20.0
earthColor = [0, 0.5, 1.0]
earthNowZ = 0.0
earthNowX = 0.0
earthYear = 0
earthDay = 0
#satellite
satelliteRadius = 1
satelliteDistance = 5.0
satelliteColor = [0,1,0]
satelliteRevolveAxisPeriod = 30
satelliteRevolveAxisCount = 0
satelliteRevolveAngle = 0.0 #공전
satelliteRevolveSpeed = 180.0 / angleSpeedConstant * globalSpeed
satelliteNowX = 0.0
satelliteNowY = 0.0
satelliteNowZ = 0.0
#pluto
plutoRadius = 2.0
plutoDistance_a = 35.0
plutoDistance_b = 45.0
plutoRevolveAngle = 0.0
plutoRevolveSpeed = earthRevolveSpeed / 4
plutoRotateAngle = 0.0
plutoRotateSpeed = 180.0 * globalSpeed
plutoColor = [1,1,0]
plutoNowZ = 0.0
plutoNowX = 0.0
plutoYear = 0
plutoDay = 0
'코딩 > 잡다한 코딩' 카테고리의 다른 글
Git : 내 컴퓨터에도 필요하고 원격에도 필요한데 변경사항을 반영하기 싫을 때 (0) | 2019.03.28 |
---|---|
Webstorm 이용한 Spring boot + Vue.js 연동 (0) | 2018.11.26 |
intellij idea + spring boot lombok이 안먹힐 때 (0) | 2018.11.25 |
[openGL][python3] 미니멀 당구 (0) | 2018.01.03 |
[하드웨어] STM32를 이용한 방공시스템 제작 (0) | 2018.01.01 |