removed clang-format and clang_complete files from the repo
[dosdemo] / src / scr / cybersun.c
1 #include <stdio.h>
2 #include <math.h>
3 #include <assert.h>
4 #include "demo.h"
5 #include "3dgfx.h"
6 #include "screen.h"
7 #include "gfxutil.h"
8 #include "mesh.h"
9 #include "image.h"
10 #include "util.h"
11 #include "cgmath/cgmath.h"
12
13 #define TM_RIPPLE_START         1.0f
14 #define TM_RIPPLE_TRANS_LEN     3.0f
15
16 #define VFOV    50.0f
17 #define HFOV    (VFOV * 1.333333f)
18
19 static int init(void);
20 static void destroy(void);
21 static void start(long trans_time);
22 static void draw(void);
23 static void draw_mountains(void);
24
25 static struct screen scr = {
26         "cybersun",
27         init,
28         destroy,
29         start,
30         0,
31         draw
32 };
33
34 static float cam_theta = 0, cam_phi = 0;
35 static float cam_dist = 0;
36
37 static struct g3d_mesh gmesh;
38 #define GMESH_GRIDSZ    25
39 #define GMESH_SIZE              128
40 static struct image gtex;
41
42 #define MOUNTIMG_WIDTH  512
43 #define MOUNTIMG_HEIGHT 64
44 static struct image mountimg;
45 static int mountimg_skip[MOUNTIMG_WIDTH];
46
47 static long part_start;
48
49
50 struct screen *cybersun_screen(void)
51 {
52         return &scr;
53 }
54
55 static int init(void)
56 {
57         int i, j;
58
59         if(gen_plane_mesh(&gmesh, GMESH_SIZE, GMESH_SIZE, GMESH_GRIDSZ, GMESH_GRIDSZ) == -1) {
60                 return -1;
61         }
62         for(i=0; i<gmesh.vcount; i++) {
63                 gmesh.varr[i].u *= GMESH_GRIDSZ;
64                 gmesh.varr[i].v *= GMESH_GRIDSZ;
65         }
66         if(load_image(&gtex, "data/pgrid.png") == -1) {
67                 return -1;
68         }
69         if(load_image(&mountimg, "data/cybmount.png") == -1) {
70                 return -1;
71         }
72         assert(mountimg.width == MOUNTIMG_WIDTH);
73         assert(mountimg.height == MOUNTIMG_HEIGHT);
74
75         for(i=0; i<MOUNTIMG_WIDTH; i++) {
76                 uint16_t *pptr = mountimg.pixels + i;
77                 for(j=0; j<MOUNTIMG_HEIGHT; j++) {
78                         if(*pptr != 0x7e0) {
79                                 mountimg_skip[i] = j;
80                                 break;
81                         }
82                         pptr += MOUNTIMG_WIDTH;
83                 }
84         }
85         destroy_image(&mountimg);
86         mountimg.pixels = 0;
87
88         return 0;
89 }
90
91 static void destroy(void)
92 {
93         destroy_mesh(&gmesh);
94         destroy_image(&gtex);
95 }
96
97 static void start(long trans_time)
98 {
99         g3d_matrix_mode(G3D_PROJECTION);
100         g3d_load_identity();
101         g3d_perspective(VFOV, 1.3333333, 0.5, 500.0);
102
103         g3d_enable(G3D_CULL_FACE);
104
105         g3d_clear_color(85, 70, 136);
106
107         part_start = time_msec;
108 }
109
110 static void update(void)
111 {
112         int i, j;
113         float t = (time_msec - part_start) / 1000.0f;
114         struct g3d_vertex *vptr;
115
116         float ampl = cgm_smoothstep(TM_RIPPLE_START, TM_RIPPLE_START + TM_RIPPLE_TRANS_LEN, t);
117
118         mouse_orbit_update(&cam_theta, &cam_phi, &cam_dist);
119
120         /* update mesh */
121         vptr = gmesh.varr;
122         for(i=0; i<GMESH_GRIDSZ + 1; i++) {
123                 for(j=0; j<GMESH_GRIDSZ + 1; j++) {
124                         float u = (float)j / GMESH_GRIDSZ - 0.5f;
125                         float v = (float)i / GMESH_GRIDSZ - 0.5f;
126                         float x = u * 32.0f;
127                         float y = v * 32.0f;
128                         float r = sqrt(x * x + y * y);
129
130                         vptr->z = sin(x * 0.5 + t) + cos(x * 0.8f) * 0.5f;
131                         vptr->z += cos(y * 0.5 + t);
132                         vptr->z += sin(r + t) * 0.5f;
133                         vptr->z *= r * 0.1f > 1.0f ? 1.0f : r * 0.1f;
134                         vptr->z *= ampl;
135                         vptr++;
136                 }
137         }
138 }
139
140 static void draw(void)
141 {
142         int i;
143
144         update();
145
146         g3d_matrix_mode(G3D_MODELVIEW);
147         g3d_load_identity();
148         g3d_translate(0, -2, -cam_dist);
149         g3d_rotate(cam_phi, 1, 0, 0);
150         g3d_rotate(cam_theta, 0, 1, 0);
151         if(opt.sball) {
152                 g3d_mult_matrix(sball_matrix);
153         }
154
155         g3d_clear(G3D_COLOR_BUFFER_BIT | G3D_DEPTH_BUFFER_BIT);
156         draw_mountains();
157
158         g3d_set_texture(gtex.width, gtex.height, gtex.pixels);
159         g3d_enable(G3D_TEXTURE_2D);
160         g3d_enable(G3D_DEPTH_TEST);
161
162         g3d_push_matrix();
163         g3d_rotate(-90, 1, 0, 0);
164         draw_mesh(&gmesh);
165         g3d_pop_matrix();
166
167         g3d_disable(G3D_DEPTH_TEST);
168         g3d_disable(G3D_TEXTURE_2D);
169
170         swap_buffers(fb_pixels);
171 }
172
173 /* XXX all the sptr calculations assume mountimg.width == 512 */
174 static void draw_mountains(void)
175 {
176         int i, j, horizon_y, y;
177         int32_t x, xstart, xend, dx;
178         uint16_t *dptr, *sptr;
179
180         /* 24.8 fixed point, 512 width, 90deg arc */
181         xstart = cround64(cam_theta * (256.0 * MOUNTIMG_WIDTH / 90.0));
182         xend = cround64((cam_theta + HFOV) * (256.0 * MOUNTIMG_WIDTH / 90.0));
183         dx = (xend - xstart) / FB_WIDTH;
184         x = xstart;
185
186         horizon_y = cround64(-cam_phi * (FB_HEIGHT / 45.0)) + FB_HEIGHT / 2;
187         y = horizon_y - MOUNTIMG_HEIGHT;
188
189         if(y >= FB_HEIGHT) {
190                 /* TODO draw gradient for the sky */
191                 return;
192         }
193         if(horizon_y < 0) {
194                 memset(fb_pixels, 0, FB_WIDTH * FB_HEIGHT * 2);
195                 return;
196         }
197
198         for(i=0; i<FB_WIDTH; i++) {
199                 int skip = mountimg_skip[(x >> 8) & 0x1ff];
200                 int vspan = MOUNTIMG_HEIGHT - skip;
201
202                 dptr = fb_pixels + (y + skip) * FB_WIDTH + i;
203
204                 for(j=0; j<vspan; j++) {
205                         *dptr = 0;      /* black mountains */
206                         dptr += FB_WIDTH;
207                 }
208
209                 x += dx;
210         }
211
212         if(horizon_y < FB_HEIGHT) {
213                 memset(fb_pixels + horizon_y * FB_WIDTH, 0, (FB_HEIGHT - horizon_y) * FB_WIDTH * 2);
214         }
215 }