everything
[carveJwlIkooP6JGAAIwe30JlM.git] / gate.h
1 #ifndef GATE_H
2 #define GATE_H
3
4 #define VG_3D
5 #include "vg/vg.h"
6 #include "model.h"
7 #include "render.h"
8 #include "shaders/gate.h"
9
10 typedef struct teleport_gate teleport_gate;
11
12 static struct
13 {
14 GLuint fb, rgb, rb;
15 glmesh mdl;
16 }
17 grender;
18
19 struct teleport_gate
20 {
21 v3f co[2];
22 v4f q[2];
23 v2f dims;
24
25 m4x3f to_world, recv_to_world, transport;
26 };
27
28 static void gate_transform_update( teleport_gate *gate )
29 {
30 m4x3f to_local;
31
32 q_m3x3( gate->q[0], gate->to_world );
33 v3_copy( gate->co[0], gate->to_world[3] );
34
35 m4x3_invert_affine( gate->to_world, to_local );
36
37 q_m3x3( gate->q[1], gate->recv_to_world );
38 v3_copy( gate->co[1], gate->recv_to_world[3] );
39 m4x3_mul( gate->recv_to_world, to_local, gate->transport );
40 }
41
42 static void gate_register(void)
43 {
44 shader_gate_register();
45 }
46
47 static void gate_init(void)
48 {
49 create_renderbuffer_std( &grender.fb, &grender.rgb, &grender.rb );
50
51 model *mgate = vg_asset_read( "models/rs_gate.mdl" );
52 model_unpack( mgate, &grender.mdl );
53 free( mgate );
54 }
55
56 static void gate_fb_resize(void)
57 {
58 resize_renderbuffer_std( &grender.fb, &grender.rgb, &grender.rb );
59 }
60
61 static void render_gate( teleport_gate *gate, m4x3f camera )
62 {
63 v3f viewpos, viewdir, gatedir;
64 v3_copy( camera[3], viewpos );
65 m3x3_mulv( camera, (v3f){0.0f,0.0f,-1.0f}, viewdir );
66 m3x3_mulv( gate->to_world, (v3f){0.0f,0.0f,-1.0f}, gatedir );
67
68 v3f v0;
69 v3_sub( viewpos, gate->co[0], v0 );
70 if( v3_dot(v0, gatedir) >= 0.0f )
71 return;
72
73 v3f a,b,c,d;
74
75 float sx = gate->dims[0],
76 sy = gate->dims[1];
77 m4x3_mulv( gate->to_world, (v3f){-sx,-sy,0.0f}, a );
78 m4x3_mulv( gate->to_world, (v3f){ sx,-sy,0.0f}, b );
79 m4x3_mulv( gate->to_world, (v3f){ sx, sy,0.0f}, c );
80 m4x3_mulv( gate->to_world, (v3f){-sx, sy,0.0f}, d );
81
82 vg_line( a,b, 0xffffa000 );
83 vg_line( b,c, 0xffffa000 );
84 vg_line( c,d, 0xffffa000 );
85 vg_line( d,a, 0xffffa000 );
86
87 vg_line2( gate->co[0], gate->co[1], 0xff0000ff, 0x00000000 );
88
89 m4x3f cam_new;
90 m4x3_mul( gate->transport, camera, cam_new );
91
92 vg_line_pt3( cam_new[3], 0.3f, 0xff00ff00 );
93
94 glBindFramebuffer( GL_FRAMEBUFFER, grender.fb );
95 glClearColor( 0.11f, 0.35f, 0.37f, 1.0f );
96 glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT );
97
98 m4x3f inverse;
99 m4x3_invert_affine( cam_new, inverse );
100
101 m4x4f view;
102 m4x3_expand( inverse, view );
103
104 v4f surface;
105 m3x3_mulv( gate->recv_to_world, (v3f){0.0f,0.0f,-1.0f}, surface );
106 surface[3] = v3_dot( surface, gate->co[1] );
107
108 m4x4f projection;
109 pipeline_projection( projection, 0.1f, 900.0f );
110
111
112 m4x3_mulp( inverse, surface, surface );
113 surface[3] = -fabsf(surface[3]);
114 plane_clip_projection( projection, surface );
115
116 m4x4_mul( projection, view, projection );
117
118 render_world( projection, cam_new );
119 render_water_texture( cam_new );
120 glBindFramebuffer( GL_FRAMEBUFFER, grender.fb );
121 render_water_surface( projection );
122 glBindFramebuffer( GL_FRAMEBUFFER, 0 );
123
124 shader_gate_use();
125
126 m4x3f full;
127 m4x3_copy( gate->to_world, full );
128 m4x3_scalev( full, (v3f){ gate->dims[0], gate->dims[1], 1.0f } );
129
130 shader_gate_uPv( vg_pv );
131 shader_gate_uMdl( full );
132
133 glActiveTexture( GL_TEXTURE0 );
134 glBindTexture( GL_TEXTURE_2D, grender.rgb );
135 shader_gate_uCam( viewpos );
136 shader_gate_uTexMain( 0 );
137 shader_gate_uTexWater( 1 );
138 shader_gate_uTime( vg_time*0.25f );
139 shader_gate_uInvRes( (v2f){
140 1.0f / (float)vg_window_x,
141 1.0f / (float)vg_window_y });
142
143 glEnable(GL_BLEND);
144 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
145 glBlendEquation(GL_FUNC_ADD);
146
147 mesh_bind( &grender.mdl );
148 mesh_draw( &grender.mdl );
149
150 glDisable(GL_BLEND);
151 }
152
153 static int gate_intersect( teleport_gate *gate, v3f pos, v3f last )
154 {
155 v4f surface;
156 m3x3_mulv( gate->to_world, (v3f){0.0f,0.0f,-1.0f}, surface );
157 surface[3] = v3_dot( surface, gate->co[0] );
158
159 v3f v0, c, delta, p0;
160 v3_sub( pos, last, v0 );
161 float l = v3_length( v0 );
162 v3_divs( v0, l, v0 );
163
164 v3_muls( surface, surface[3], c );
165 v3_sub( c, last, delta );
166
167 float d = v3_dot(surface, v0);
168
169 if( fabsf(d) > 0.00001f )
170 {
171 float t = v3_dot(delta, surface) / d;
172 if( t >= 0.0f && t <= l )
173 {
174 v3f local, rel;
175 v3_muladds( last, v0, t, local );
176 v3_sub( gate->co[0], local, rel );
177
178 v3f vup, vside;
179 m3x3_mulv( gate->to_world, (v3f){0.0f,1.0f,0.0f}, vup );
180 m3x3_mulv( gate->to_world, (v3f){1.0f,0.0f,0.0f}, vside );
181
182 v2f xy = { v3_dot( rel, vside ), v3_dot( rel, vup ) };
183
184 if( fabsf(xy[0]) <= gate->dims[0] && fabsf(xy[1]) <= gate->dims[1] )
185 {
186 return 1;
187 }
188 }
189 }
190
191 return 0;
192 }
193
194 #endif