-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathstars.f90
359 lines (309 loc) · 7.89 KB
/
stars.f90
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
module stars_mod
use opengl_gl
use opengl_glu
use opengl_glut
implicit none
real(gldouble), parameter :: M_PI = 3.14159265358979323846_gldouble
integer(glenum), parameter :: &
NORMAL = 0, &
WEIRD = 1
integer(glenum), parameter :: &
STREAK = 0, &
CIRCLE = 1
integer, parameter :: MAXSTARS = 400
integer, parameter :: MAXPOS = 10000
integer, parameter :: MAXWARP = 10
integer, parameter :: MAXANGLES = 6000
type starRec
integer(GLint) type
real x(0:1), y(0:1), z(0:1)
real offsetX, offsetY, offsetR, rotation
end type starRec
integer(GLenum) doubleBuffer
integer(GLint) :: windW = 300, windH = 300
integer(GLenum) :: flag = NORMAL
integer(GLint) :: starCount = MAXSTARS / 2
real :: speed = 1.0
integer(GLint) :: nitro = 0
type(starRec) :: stars(0:MAXSTARS)
real :: sinTable(0:MAXANGLES)
contains
function mySin(angle)
real, intent(in) :: angle
real mySin
mySin = sinTable(mod(int(angle),MAXANGLES))
return
end function mySin
function myCos(angle)
real, intent(in) :: angle
real myCos
myCos = sinTable(mod(int(angle) + (MAXANGLES / 4),MAXANGLES))
return
end function myCos
subroutine NewStar(n, d)
integer(glint), intent(in) :: n,d
if (mod(rand(),4) == 0) then
stars(n)%type = CIRCLE
else
stars(n)%type = STREAK
end if
stars(n)%x(0) = mod(rand(), MAXPOS) - MAXPOS / 2
stars(n)%y(0) = mod(rand(), MAXPOS) - MAXPOS / 2
stars(n)%z(0) = mod(rand(), MAXPOS) + d
stars(n)%x(1) = stars(n)%x(0)
stars(n)%y(1) = stars(n)%y(0)
stars(n)%z(1) = stars(n)%z(0)
if (mod(rand(), 4) == 0 .and. flag == WEIRD) then
stars(n)%offsetX = mod(rand(), 100) - 100 / 2
stars(n)%offsetY = mod(rand(), 100) - 100 / 2
stars(n)%offsetR = mod(rand(), 25) - 25 / 2
else
stars(n)%offsetX = 0.0
stars(n)%offsetY = 0.0
stars(n)%offsetR = 0.0
end if
return
end subroutine NewStar
subroutine RotatePoint(x, y, rotation)
real, intent(in out) :: x,y
real, intent(in) :: rotation
real tmpX, tmpY
tmpX = x * myCos(rotation) - y * mySin(rotation)
tmpY = y * myCos(rotation) + x * mySin(rotation)
x = tmpX
y = tmpY
return
end subroutine RotatePoint
subroutine MoveStars()
real offset
integer(GLint) n
offset = speed * 60.0
do n=0,starCount
stars(n)%x(1) = stars(n)%x(0)
stars(n)%y(1) = stars(n)%y(0)
stars(n)%z(1) = stars(n)%z(0)
stars(n)%x(0) = stars(n)%x(0) + stars(n)%offsetX
stars(n)%y(0) = stars(n)%y(0) + stars(n)%offsetY
stars(n)%z(0) = stars(n)%z(0) - offset
stars(n)%rotation = stars(n)%rotation + stars(n)%offsetR
if (stars(n)%rotation >= MAXANGLES) then
stars(n)%rotation = 0.0
end if
end do
return
end subroutine MoveStars
function StarPoint(n)
integer(glint), intent(in) :: n
integer(glenum) :: StarPoint
real x0, y0
x0 = stars(n)%x(0) * windW / stars(n)%z(0)
y0 = stars(n)%y(0) * windH / stars(n)%z(0)
call RotatePoint(x0, y0, stars(n)%rotation)
x0 = x0 + windW / 2.0
y0 = y0 + windH / 2.0
if (x0 >= 0.0 .and. x0 < windW .and. y0 >= 0.0 .and. y0 < windH) then
StarPoint = GL_TRUE
else
StarPoint = GL_FALSE
end if
return
end function StarPoint
subroutine ShowStar(n)
integer(glint), intent(in) :: n
real x0, y0, x1, y1, width, x, y
integer(GLint) i
x0 = stars(n)%x(0) * windW / stars(n)%z(0)
y0 = stars(n)%y(0) * windH / stars(n)%z(0)
call RotatePoint(x0, y0, stars(n)%rotation)
x0 = x0 + windW / 2.0
y0 = y0 + windH / 2.0
if (x0 >= 0.0 .and. x0 < windW .and. y0 >= 0.0 .and. y0 < windH) then
if (stars(n)%type == STREAK) then
x1 = stars(n)%x(1) * windW / stars(n)%z(1)
y1 = stars(n)%y(1) * windH / stars(n)%z(1)
call RotatePoint(x1, y1, stars(n)%rotation)
x1 = x1 + windW / 2.0
y1 = y1 + windH / 2.0
call glLineWidth(MAXPOS / 100.0 / stars(n)%z(0) + 1.0)
call glColor3f(1.0, (MAXWARP - speed) / MAXWARP, (MAXWARP - speed) / MAXWARP)
if (abs(x0 - x1) < 1.0 .and. abs(y0 - y1) < 1.0) then
call glBegin(GL_POINTS)
call glVertex2f(x0, y0)
call glEnd()
else
call glBegin(GL_LINES)
call glVertex2f(x0, y0)
call glVertex2f(x1, y1)
call glEnd()
end if
else
width = MAXPOS / 10.0 / stars(n)%z(0) + 1.0
call glColor3f(1.0, 0.0, 0.0)
call glBegin(GL_POLYGON)
do i=0,7
x = x0 + width * myCos(i * MAXANGLES / 8.0)
y = y0 + width * mySin(i * MAXANGLES / 8.0)
call glVertex2f(x, y)
end do
call glEnd()
end if
end if
return
end subroutine ShowStar
subroutine UpdateStars()
integer(GLint) n
call glClear(GL_COLOR_BUFFER_BIT)
do n=0,starCount
if (stars(n)%z(0) > speed .or. (stars(n)%z(0) > 0.0 .and. speed < MAXWARP)) then
if (StarPoint(n) == GL_FALSE) then
call NewStar(n, MAXPOS)
end if
else
call NewStar(n, MAXPOS)
end if
end do
return
end subroutine UpdateStars
subroutine ShowStars()
integer(GLint) n
call glClear(GL_COLOR_BUFFER_BIT)
do n=0,starCount
if (stars(n)%z(0) > speed .or. (stars(n)%z(0) > 0.0 .and. speed < MAXWARP)) then
call ShowStar(n)
end if
end do
return
end subroutine ShowStars
subroutine Init()
real angle
integer(GLint) n
call random_seed
do n=0,MAXSTARS
call NewStar(n, 100)
end do
angle = 0.0
do n=0,MAXANGLES
sinTable(n) = sin(angle)
angle = angle + M_PI / (MAXANGLES / 2.0)
end do
call glClearColor(0.0, 0.0, 0.0, 0.0)
call glDisable(GL_DITHER)
return
end subroutine Init
subroutine Reshape(width, height) bind(c)
integer(glcint), value :: width, height
windW = width
windH = height
call glViewport(0_GLint, 0_GLint, windW, windH)
call glMatrixMode(GL_PROJECTION)
call glLoadIdentity()
call gluOrtho2D(-0.5_gldouble, windW + 0.5_gldouble, -0.5_gldouble, windH + 0.5_gldouble)
call glMatrixMode(GL_MODELVIEW)
return
end subroutine Reshape
!/* ARGSUSED1 */
subroutine Key(ikey, x, y) bind(c)
INTEGER(GLbyte), VALUE :: ikey
INTEGER(GLint), VALUE :: x, y
select case(ikey)
case (iachar(' '))
if (flag == NORMAL) then
flag = WEIRD
else
flag = NORMAL
end if
case (iachar('t'))
nitro = 1
case (27)
stop
end select
return
end subroutine key
subroutine Idle() bind(c)
call MoveStars()
call UpdateStars()
if (nitro > 0) then
speed = (nitro / 10.) + 1.0
if (speed > MAXWARP) then
speed = MAXWARP
end if
nitro = nitro + 1
if (nitro > MAXWARP * 10) then
nitro = -nitro
end if
elseif (nitro < 0) then
nitro = nitro + 1
speed = (-nitro / 10.) + 1.0
if (speed > MAXWARP) then
speed = MAXWARP
end if
end if
call glutPostRedisplay()
return
end subroutine Idle
subroutine Display() bind(c)
call ShowStars()
if (doubleBuffer == GL_TRUE) then
call glutSwapBuffers()
else
call glFlush()
end if
return
end subroutine Display
subroutine Visible(state) bind(c)
integer(glcint), value :: state
if (state == GLUT_VISIBLE) then
call glutIdleFunc(Idle)
else
call glutIdleFunc()
end if
return
end subroutine visible
!static void
!Args(int argc, char **argv)
!{
! GLint i;
!
! doubleBuffer = GL_TRUE;
!
! for (i = 1; i < argc; i++) {
! if (strcmp(argv(i), "-sb") == 0) {
! doubleBuffer = GL_FALSE;
! } else if (strcmp(argv(i), "-db") == 0) {
! doubleBuffer = GL_TRUE;
! }
! }
!}
function rand()
integer :: rand
real :: frand
call random_number(frand)
rand = 32768*frand
return
end function rand
end module stars_mod
program stars_prog
use opengl_gl
use opengl_glut
use stars_mod
integer(GLenum) type
integer(glcint) win
call glutInitWindowSize(windW, windH)
call glutInit()
doubleBuffer = GL_TRUE ! Args(argc, argv);
type = GLUT_RGB
if (doubleBuffer == GL_TRUE) then
type = ior(type,GLUT_DOUBLE)
else
type = ior(type,GLUT_SINGLE)
end if
call glutInitDisplayMode(type)
win = glutCreateWindow("Stars")
call Init()
call glutReshapeFunc(Reshape)
call glutKeyboardFunc(Key)
call glutVisibilityFunc(Visible)
call glutDisplayFunc(Display)
call glutMainLoop()
stop
end program stars_prog