2 * Copyright (C) 2021-2022 Mt.ZERO Software, Harry Godden - All Rights Reserved
13 #include "shaders/model_gate.h"
14 #include "world_water.h"
16 VG_STATIC
void gate_transform_update( teleport_gate
*gate
)
18 m4x3f to_local
, recv_to_world
;
20 q_m3x3( gate
->q
[0], gate
->to_world
);
21 v3_copy( gate
->co
[0], gate
->to_world
[3] );
23 m4x3_invert_affine( gate
->to_world
, to_local
);
25 q_m3x3( gate
->q
[1], recv_to_world
);
26 v3_copy( gate
->co
[1], recv_to_world
[3] );
27 m4x3_mul( recv_to_world
, to_local
, gate
->transport
);
29 m4x3_scalev( gate
->to_world
, (v3f
){ gate
->dims
[0], gate
->dims
[1], 1.0f
} );
32 VG_STATIC
void world_gates_init(void)
34 vg_info( "world_gates_init\n" );
36 shader_model_gate_register();
38 vg_linear_clear( vg_mem
.scratch
);
39 mdl_context
*mgate
= mdl_load_full( vg_mem
.scratch
, "models/rs_gate.mdl" );
41 vg_acquire_thread_sync();
43 mdl_unpack_glmesh( mgate
, &world_global
.mesh_gate_surface
);
45 vg_release_thread_sync();
48 VG_STATIC
int render_gate( world_instance
*world_inside
,
49 teleport_gate
*gate
, camera
*cam
)
52 m3x3_mulv( cam
->transform
, (v3f
){0.0f
,0.0f
,-1.0f
}, viewdir
);
53 q_mulv( gate
->q
[0], (v3f
){0.0f
,0.0f
,-1.0f
}, gatedir
);
56 v3_sub( cam
->pos
, gate
->co
[0], v0
);
58 float dist
= v3_dot(v0
, gatedir
);
64 if( v3_dist( cam
->pos
, gate
->co
[0] ) > 100.0f
)
70 m4x3_mulv( gate
->to_world
, (v3f
){-1.0f
,-1.0f
,0.0f
}, a
);
71 m4x3_mulv( gate
->to_world
, (v3f
){ 1.0f
,-1.0f
,0.0f
}, b
);
72 m4x3_mulv( gate
->to_world
, (v3f
){ 1.0f
, 1.0f
,0.0f
}, c
);
73 m4x3_mulv( gate
->to_world
, (v3f
){-1.0f
, 1.0f
,0.0f
}, d
);
75 vg_line( a
,b
, 0xffffa000 );
76 vg_line( b
,c
, 0xffffa000 );
77 vg_line( c
,d
, 0xffffa000 );
78 vg_line( d
,a
, 0xffffa000 );
80 vg_line2( gate
->co
[0], gate
->co
[1], 0xff0000ff, 0x00000000 );
83 /* update gate camera */
84 gate_camera
.fov
= cam
->fov
;
85 gate_camera
.nearz
= 0.1f
;
86 gate_camera
.farz
= 2000.0f
;
88 m4x3_mul( gate
->transport
, cam
->transform
, gate_camera
.transform
);
89 camera_update_view( &gate_camera
);
90 camera_update_projection( &gate_camera
);
92 /* Add special clipping plane to projection */
94 q_mulv( gate
->q
[1], (v3f
){0.0f
,0.0f
,-1.0f
}, surface
);
95 surface
[3] = v3_dot( surface
, gate
->co
[1] );
97 m4x3_mulp( gate_camera
.transform_inverse
, surface
, surface
);
98 surface
[3] = -fabsf(surface
[3]);
101 m4x4_clip_projection( gate_camera
.mtx
.p
, surface
);
103 /* Ready to draw with new camrea */
104 camera_finalize( &gate_camera
);
106 vg_line_pt3( gate_camera
.transform
[3], 0.3f
, 0xff00ff00 );
108 shader_model_gate_use();
109 shader_model_gate_uPv( cam
->mtx
.pv
);
110 shader_model_gate_uMdl( gate
->to_world
);
111 shader_model_gate_uCam( cam
->pos
);
112 shader_model_gate_uTime( vg
.time
*0.25f
);
113 shader_model_gate_uInvRes( (v2f
){
114 1.0f
/ (float)vg
.window_x
,
115 1.0f
/ (float)vg
.window_y
});
117 glEnable( GL_STENCIL_TEST
);
118 glStencilOp( GL_KEEP
, GL_KEEP
, GL_REPLACE
);
119 glStencilFunc( GL_ALWAYS
, 1, 0xFF );
120 glStencilMask( 0xFF );
122 mesh_bind( &world_global
.mesh_gate_surface
);
123 mesh_draw( &world_global
.mesh_gate_surface
);
125 glClear( GL_DEPTH_BUFFER_BIT
);
126 glStencilFunc( GL_EQUAL
, 1, 0xFF );
127 glStencilMask( 0x00 );
130 render_world( world_inside
, &gate_camera
);
133 glDisable( GL_STENCIL_TEST
);
135 render_water_texture( world_inside
, &gate_camera
);
136 render_fb_bind( gpipeline
.fb_main
);
138 glEnable( GL_STENCIL_TEST
);
140 render_water_surface( world_inside
, &gate_camera
);
142 glStencilMask( 0xFF );
143 glStencilFunc( GL_ALWAYS
, 1, 0xFF );
144 glDisable( GL_STENCIL_TEST
);
150 VG_STATIC
int gate_intersect_plane( teleport_gate
*gate
, v3f pos
, v3f last
,
154 q_mulv( gate
->q
[0], (v3f
){0.0f
,0.0f
,-1.0f
}, surface
);
155 surface
[3] = v3_dot( surface
, gate
->co
[0] );
157 v3f v0
, c
, delta
, p0
;
158 v3_sub( pos
, last
, v0
);
159 float l
= v3_length( v0
);
164 v3_divs( v0
, l
, v0
);
166 v3_muls( surface
, surface
[3], c
);
167 v3_sub( c
, last
, delta
);
169 float d
= v3_dot( surface
, v0
);
173 float t
= v3_dot(delta
, surface
) / d
;
174 if( t
>= 0.0f
&& t
<= l
)
177 v3_muladds( last
, v0
, t
, local
);
178 v3_sub( gate
->co
[0], local
, rel
);
180 where
[0] = v3_dot( rel
, gate
->to_world
[0] );
181 where
[1] = v3_dot( rel
, gate
->to_world
[1] );
183 where
[0] /= v3_dot( gate
->to_world
[0], gate
->to_world
[0] );
184 where
[1] /= v3_dot( gate
->to_world
[1], gate
->to_world
[1] );
193 VG_STATIC
int gate_intersect( teleport_gate
*gate
, v3f pos
, v3f last
)
197 if( gate_intersect_plane( gate
, pos
, last
, xy
) )
199 if( fabsf(xy
[0]) <= 1.0f
&& fabsf(xy
[1]) <= 1.0f
)
210 struct nonlocal_gate
*nonlocal
;
211 struct route_gate
*route
;
216 * Intersect all gates in the world
218 VG_STATIC
int world_intersect_gates( world_instance
*world
,
219 v3f pos
, v3f last
, struct gate_hit
*hit
)
221 for( int i
=0; i
<world
->gate_count
; i
++ )
223 struct route_gate
*rg
= &world
->gates
[i
];
224 teleport_gate
*gate
= &rg
->gate
;
226 if( gate_intersect( gate
, pos
, last
) )
229 hit
->nonlocal
= NULL
;
235 for( int i
=0; i
<world
->nonlocalgate_count
; i
++ )
237 struct nonlocal_gate
*nlg
= &world
->nonlocal_gates
[i
];
238 teleport_gate
*gate
= &nlg
->gate
;
240 if( gate_intersect( gate
, pos
, last
) )
252 #endif /* WORLD_GATE_H */