3 #include "shaders/model_character_view.h"
8 struct npc npc_gumpa
, npc_slowmo
, npc_volc_flight
;
9 static struct skeleton_anim
*gumpa_idle
;
10 static struct skeleton_anim
*slowmo_momentum
, *slowmo_slide
, *slowmo_rewind
,
12 static float slowmo_opacity
= 0.0f
;
13 static f64 volc_start_preview
= 0.0;
15 void npc_load_model( struct npc
*npc
, const char *path
)
17 vg_linear_clear( vg_mem
.scratch
);
19 mdl_context
*meta
= &npc
->meta
;
20 mdl_open( meta
, path
, vg_mem
.rtmemory
);
21 mdl_load_metadata_block( meta
, vg_mem
.rtmemory
);
22 mdl_load_animation_block( meta
, vg_mem
.rtmemory
);
24 struct skeleton
*sk
= &npc
->skeleton
;
25 skeleton_setup( sk
, vg_mem
.rtmemory
, meta
);
27 u32 mtx_size
= sizeof(m4x3f
)*sk
->bone_count
;
28 npc
->final_mtx
= vg_linear_alloc( vg_mem
.rtmemory
, mtx_size
);
30 if( mdl_arrcount( &meta
->textures
) )
32 mdl_texture
*tex0
= mdl_arritm( &meta
->textures
, 0 );
33 void *data
= vg_linear_alloc( vg_mem
.scratch
, tex0
->file
.pack_size
);
34 mdl_fread_pack_file( meta
, &tex0
->file
, data
);
36 vg_tex2d_load_qoi_async( data
, tex0
->file
.pack_size
,
37 VG_TEX2D_NEAREST
|VG_TEX2D_CLAMP
,
42 npc
->texture
= vg
.tex_missing
;
45 mdl_async_load_glmesh( meta
, &npc
->mesh
, NULL
);
51 npc_load_model( &npc_gumpa
, "models/gumpa.mdl" );
52 gumpa_idle
= skeleton_get_anim( &npc_gumpa
.skeleton
, "gumpa_idle" );
54 npc_load_model( &npc_slowmo
, "models/slowmos.mdl" );
56 skeleton_get_anim( &npc_slowmo
.skeleton
, "slowmo_momentum" );
57 slowmo_slide
= skeleton_get_anim( &npc_slowmo
.skeleton
, "slowmo_slide" );
58 slowmo_rewind
= skeleton_get_anim( &npc_slowmo
.skeleton
, "slowmo_rewind" );
60 npc_load_model( &npc_volc_flight
, "models/volc_flight.mdl" );
62 skeleton_get_anim( &npc_volc_flight
.skeleton
, "tutorial" );
65 static struct npc
*npc_resolve( u32 id
)
67 if( id
== 1 ) return &npc_gumpa
;
68 else if( id
== 2 ) return &npc_slowmo
;
69 else if( id
== 3 ) return &npc_volc_flight
;
73 static entity_call_result
npc_slowmo_call( ent_npc
*npc
, ent_call
*call
)
75 if( call
->function
== 0 )
80 if( npc
->context
== 2 )
82 if( gui_new_helper( input_axis_list
[k_sraxis_grab
], &text
))
83 vg_strcat( &text
, "Crouch (store energy)" );
84 if( gui_new_helper( input_joy_list
[k_srjoystick_steer
], &text
))
85 vg_strcat( &text
, "Slide" );
87 else if( npc
->context
== 1 )
89 if( gui_new_helper( input_axis_list
[k_sraxis_grab
], &text
))
90 vg_strcat( &text
, "Crouch (store energy)" );
92 else if( npc
->context
== 3 )
94 if( gui_new_helper( input_button_list
[k_srbind_reset
], &text
))
95 vg_strcat( &text
, "Rewind time" );
96 if( gui_new_helper( input_button_list
[k_srbind_replay_resume
], &text
))
97 vg_strcat( &text
, "Resume" );
99 return k_entity_call_result_OK
;
101 else if( call
->function
== -1 )
103 world_entity_clear_focus();
105 return k_entity_call_result_OK
;
108 return k_entity_call_result_unhandled
;
111 entity_call_result
ent_npc_call( world_instance
*world
, ent_call
*call
)
113 u32 index
= mdl_entity_id_id( call
->id
);
114 ent_npc
*npc
= mdl_arritm( &world
->ent_npc
, index
);
118 return npc_slowmo_call( npc
, call
);
120 else if( npc
->id
== 3 )
122 if( call
->function
== 0 )
124 world_entity_set_focus( call
->id
);
127 if( gui_new_helper( input_button_list
[k_srbind_maccept
], &text
))
128 vg_strcat( &text
, "Preview course" );
129 return k_entity_call_result_OK
;
131 else if( call
->function
== -1 )
133 world_entity_clear_focus();
135 return k_entity_call_result_OK
;
138 return k_entity_call_result_unhandled
;
140 else if( npc
->id
== 4 )
142 if( call
->function
== 0 )
146 if( gui_new_helper( input_button_list
[k_srbind_camera
], &text
))
147 vg_strcat( &text
, "First/Thirdperson" );
148 return k_entity_call_result_OK
;
150 else if( call
->function
== -1 )
153 return k_entity_call_result_OK
;
156 return k_entity_call_result_unhandled
;
160 if( call
->function
== 0 )
162 world_entity_set_focus( call
->id
);
165 if( gui_new_helper( input_button_list
[k_srbind_maccept
], &text
))
166 vg_strcat( &text
, "Talk to ???" );
167 return k_entity_call_result_OK
;
169 else if( call
->function
== -1 )
171 world_entity_clear_focus();
173 return k_entity_call_result_OK
;
176 return k_entity_call_result_unhandled
;
180 void ent_npc_preupdate( ent_focus_context
*ctx
)
182 world_instance
*world
= ctx
->world
;
183 ent_npc
*ent
= mdl_arritm( &world
->ent_npc
, ctx
->index
);
187 if( button_down(k_srbind_maccept
) )
189 world_entity_focus_modal();
192 if( gui_new_helper( input_button_list
[k_srbind_mback
], &text
))
193 vg_strcat( &text
, "leave" );
195 volc_start_preview
= vg
.time
;
204 struct skeleton
*sk
= &npc_volc_flight
.skeleton
;
206 f64 t
= (vg
.time
- volc_start_preview
) * 0.5;
207 skeleton_sample_anim_clamped( sk
, anim_tutorial_cam
, t
, pose
.keyframes
);
209 ent_camera
*cam
= mdl_arritm( &world
->ent_camera
,
210 mdl_entity_id_id(ent
->camera
) );
211 v3_copy( pose
.keyframes
[0].co
, cam
->transform
.co
);
214 q_axis_angle( qp
, (v3f
){1,0,0}, VG_TAUf
*0.25f
);
215 q_mul( pose
.keyframes
[0].q
, qp
, cam
->transform
.q
);
216 q_normalize( cam
->transform
.q
);
218 v3_add( ent
->transform
.co
, cam
->transform
.co
, cam
->transform
.co
);
221 world_entity_focus_camera( world
, ent
->camera
);
223 if( button_down( k_srbind_mback
) )
225 world_entity_exit_modal();
226 world_entity_clear_focus();
231 void npc_update( ent_npc
*ent
)
233 if( ent
->id
== 3 ) return;
234 if( ent
->id
== 4 ) return;
236 struct npc
*npc_def
= npc_resolve( ent
->id
);
237 VG_ASSERT( npc_def
);
240 struct skeleton
*sk
= &npc_def
->skeleton
;
241 pose
.type
= k_player_pose_type_ik
;
242 pose
.board
.lean
= 0.0f
;
246 skeleton_sample_anim( sk
, gumpa_idle
, vg
.time
, pose
.keyframes
);
248 else if( ent
->id
== 2 )
250 struct skeleton_anim
*anim
= NULL
;
251 if( ent
->context
== 1 ) anim
= slowmo_momentum
;
252 else if( ent
->context
== 2 ) anim
= slowmo_slide
;
253 else if( ent
->context
== 3 ) anim
= slowmo_rewind
;
257 f32 t
= vg
.time
*0.5f
,
258 animtime
= fmodf( t
*anim
->rate
, anim
->length
),
259 lt
= animtime
/ (f32
)anim
->length
;
260 skeleton_sample_anim( sk
, anim
, t
, pose
.keyframes
);
261 slowmo_opacity
= vg_clampf(fabsf(lt
-0.5f
)*9.0f
-3.0f
,0,1);
264 v3_copy( ent
->transform
.co
, pose
.root_co
);
265 v4_copy( ent
->transform
.q
, pose
.root_q
);
266 apply_full_skeleton_pose( &npc_def
->skeleton
, &pose
, npc_def
->final_mtx
);
269 void npc_render( ent_npc
*ent
, world_instance
*world
, vg_camera
*cam
)
271 if( ent
->id
== 3 ) return;
272 if( ent
->id
== 4 ) return;
274 struct npc
*npc_def
= npc_resolve( ent
->id
);
275 VG_ASSERT( npc_def
);
277 shader_model_character_view_use();
279 glActiveTexture( GL_TEXTURE0
);
280 glBindTexture( GL_TEXTURE_2D
, npc_def
->texture
);
281 shader_model_character_view_uTexMain( 0 );
282 shader_model_character_view_uCamera( cam
->transform
[3] );
283 shader_model_character_view_uPv( cam
->mtx
.pv
);
287 shader_model_character_view_uDepthMode( 2 );
288 shader_model_character_view_uDitherCutoff( slowmo_opacity
);
292 shader_model_character_view_uDepthMode( 0 );
295 WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world
, model_character_view
);
297 glUniformMatrix4x3fv( _uniform_model_character_view_uTransforms
,
298 npc_def
->skeleton
.bone_count
,
300 (const GLfloat
*)npc_def
->final_mtx
);
302 mesh_bind( &npc_def
->mesh
);
303 mesh_draw( &npc_def
->mesh
);