#define MAIN_INCLUDE
#include <vhelper.h>
#include <gp/coord.h>
#include <gp/pstring.h>
#include <gp/misc.h>
#include <gp/colors.h>
#include <vutil-texture.h>
#include <vutil-pipeline.h>
#include "shapes.h"
struct Uni_Light_Simple {
vec4 position;
vec4 color;
};
struct Uni_Misc {
ivec4 opt_tryout;
ivec4 opt_assign;
float opt_tryoutf;
};
constexpr int ncolors = 10;
struct HW05_Uniform {
pColor front[ncolors], back[ncolors];
mat4 local_from_object;
int s_sides, s_levels, n_sides, n_levels;
float n_sides_inv, n_levels_inv;
};
struct Hyperboloid_Info {
pCoor bot_ctr_pos, top_ctr_pos;
pCoor line_0_bot_pos;
pVect line_0_dir;
int n_sides_constructed;
int serial;
};
class World {
public:
World(pVulkan_Helper &vh)
:vh(vh),ff_state(vh.qs),frame_timer(vh.frame_timer),shapes(ff_state),
transform(vh.qs){}
void setup_and_run();
void render(vk::CommandBuffer& cb);
void keyboard_handle();
pVulkan_Helper& vh;
VFixed_Function_State_Manager ff_state;
pFrame_Timer& frame_timer;
Shapes shapes;
pVariable_Control variable_control;
pCoor light_location;
float opt_light_intensity;
enum { MI_Eye, MI_Light, MI_Ball, MI_Ball_V, MI_COUNT } opt_move_item;
pCoor eye_location, eye_initial_location;
pVect eye_direction;
pNorm eye_initial_direction;
VTransform transform;
VBufferV<Uni_Light_Simple> uni_light_simple;
VBufferV<Uni_Misc> uni_misc;
VPipeline pipe_plain;
VVertex_Buffer_Set bset_plain;
bool opt_tryout1, opt_tryout2, opt_tryout3;
void scene_setup_1();
void scene_setup_2();
double world_time, time_last_update;
bool opt_pause;
VBufferV<HW05_Uniform> uni_hw05;
enum Pipeline_Variant { PV_Individ, PV_Strip, PV_Points, PV_SIZE };
int pipeline_variant;
Hyperboloid_Info hyperb_info;
void hyperb_setup(bool r);
VPipeline pipe_hyperb;
VPipeline pipe_hyperb_strip;
VVertex_Buffer_Set bset_hyperb;
int hyperb_serial;
int hyperb_setup_n;
int opt_n_sides;
VBufferVV<vec4> sto_hyperb_coords;
VBufferVV<vec4> sto_hyperb_norms;
VPipeline pipe_hyperb_points;
vk::Sampler sampler;
VTexture texture_id_syllabus;
bool opt_texture;
};
const char* const pipeline_variant_str[] =
{ "INDIVID", "STRIP", "POINTS" };
void
World::scene_setup_1()
{
hyperb_setup(false);
}
void
World::scene_setup_2()
{
hyperb_setup(true);
}
float
prand(float max)
{
double r = random() * (1.0 / RAND_MAX );
return r * max;
}
float
prand(float min, float max)
{
assert( min <= max );
return min + prand( max - min );
}
pVect
norm_rand()
{
double theta = prand(2*M_PI);
double eta = prand(2*M_PI);
pVect az(0,0,1);
pVect a = pMatrix_Rotation(az,theta) * pVect(1,0,0);
pVect a2 = cross(az,a);
pVect b = pMatrix_Rotation(a2,eta) * a;
float l = b.mag();
assert( fabs(l-1) < 0.0001 );
return b;
}
pVect vec_rand(float r1) { return prand(r1) * norm_rand(); }
pVect vec_rand(float r1, float r2) { return prand(r1,r2) * norm_rand(); }
pVect vec_rand(float rmin, float rmax, pVect axis)
{
pNorm v = pMatrix_Rotation(axis.normal(),prand(2*M_PI)) * axis.orthogonal();
return prand(rmin,rmax) * v;
}
void
World::hyperb_setup(bool reset)
{
world_time = 0;
time_last_update = time_wall_fp();
if ( reset ) hyperb_setup_n = 0;
hyperb_setup_n++;
Hyperboloid_Info& h = hyperb_info;
float s = 0.6;
h.n_sides_constructed = 0;
switch ( hyperb_setup_n ) {
case 1:
h.top_ctr_pos = pCoor(2.78,0.83,0.89);
h.bot_ctr_pos = pCoor(2.68,-1.03,0.52);
h.line_0_bot_pos = pCoor(2.82,-0.35,-2.95);
h.line_0_dir = pNorm(0.67,0.27,0.69);
break;
case 2:
h.top_ctr_pos = pCoor(2.95,0.42,-0.31);
h.bot_ctr_pos = pCoor(2.96,-0.85,-0.42);
h.line_0_bot_pos = pCoor(2.20,-0.68,-2.47);
h.line_0_dir = pNorm(0.69,0.18,0.70);
break;
default:
hyperb_info.bot_ctr_pos = pCoor(3,-1,0) + vec_rand(1);
h.top_ctr_pos =
h.bot_ctr_pos + pVect(0,prand(1*s,5*s),0) + vec_rand(0,s,pVect(0,1,0));
pVect vz(h.bot_ctr_pos,h.top_ctr_pos);
h.line_0_bot_pos = h.bot_ctr_pos + vec_rand(2*s,6*s,vz);
pCoor line_0_top_pos = hyperb_info.top_ctr_pos + vec_rand(2*s,6*s,vz);
hyperb_info.line_0_dir = pNorm(h.line_0_bot_pos,line_0_top_pos);
break;
}
printf("h.top_ctr_pos = pCoor(%.2f,%.2f,%.2f);\n",
h.top_ctr_pos.x, h.top_ctr_pos.y,h.top_ctr_pos.z);
printf("h.bot_ctr_pos = pCoor(%.2f,%.2f,%.2f);\n",
h.bot_ctr_pos.x, h.bot_ctr_pos.y,h.bot_ctr_pos.z);
printf("h.line_0_bot_pos = pCoor(%.2f,%.2f,%.2f);\n",
h.line_0_bot_pos.x, h.line_0_bot_pos.y,h.line_0_bot_pos.z);
printf("h.line_0_dir = pNorm(%.2f,%.2f,%.2f);\n",
h.line_0_dir.x, h.line_0_dir.y,h.line_0_dir.z);
}
void
World::setup_and_run()
{
vh.init();
vh.display_cb_set([&](){});
vh.cbs_cmd_record.push_back( [&](vk::CommandBuffer& cb){ render(cb); });
pipeline_variant = 0;
opt_tryout1 = opt_tryout2 = opt_tryout3 = false;
uni_misc->opt_tryout.w = 1;
uni_misc->opt_tryoutf = 1;
eye_initial_location = pCoor( 3, .5, 8.6) ;
eye_location = eye_initial_location;
eye_initial_direction = pVect(0,0,-1);
eye_direction = eye_initial_direction;
opt_light_intensity = 22;
light_location = pCoor( -6.6, 8.0, 2.5 );
opt_move_item = MI_Eye;
sto_hyperb_coords.init(vh.qs,vk::BufferUsageFlagBits::eStorageBuffer );
sto_hyperb_norms.init(vh.qs,vk::BufferUsageFlagBits::eStorageBuffer );
opt_texture = true;
sampler = vh.qs.dev.createSampler
( { {},
vk::Filter::eLinear, vk::Filter::eLinear,
vk::SamplerMipmapMode::eLinear,
vk::SamplerAddressMode::eRepeat,
vk::SamplerAddressMode::eRepeat,
vk::SamplerAddressMode::eRepeat,
0.0f,
true, 16.0f,
false,
vk::CompareOp::eNever,
0.0f, VK_LOD_CLAMP_NONE, vk::BorderColor::eFloatOpaqueBlack } );
texture_id_syllabus.init
(vh.qs, P_Image_Read("../../../../vulkan/gpup.png",255) );
uni_misc.init(vh.qs,vk::BufferUsageFlagBits::eUniformBuffer);
uni_misc->opt_tryout =
ivec4(opt_tryout1,opt_tryout2,opt_tryout3, uni_misc->opt_tryout.w);
uni_misc->opt_assign = ivec4(opt_texture,0,0,0);
uni_light_simple.init(vh.qs,vk::BufferUsageFlagBits::eUniformBuffer);
uni_hw05.init(vh.qs,vk::BufferUsageFlagBits::eUniformBuffer);
hyperb_info.serial = 0;
hyperb_serial = -1;
hyperb_setup_n = 0;
opt_n_sides = 81;
variable_control.insert(opt_n_sides,"n_sides",1,3);
variable_control.insert(opt_light_intensity,"Light Intensity");
variable_control.insert(uni_misc->opt_tryout.w,"opt_tryouti");
variable_control.insert(uni_misc->opt_tryoutf,"opt_tryoutf");
opt_pause = false;
scene_setup_1();
vh.message_loop_spin();
uni_light_simple.destroy();
uni_misc.destroy();
pipe_plain.destroy();
bset_plain.destroy();
shapes.destroy();
transform.destroy();
uni_hw05.destroy();
pipe_hyperb.destroy();
pipe_hyperb_strip.destroy();
bset_hyperb.destroy();
pipe_hyperb_points.destroy();
texture_id_syllabus.destroy();
vh.dev.destroySampler(sampler);
sto_hyperb_coords.destroy();
sto_hyperb_norms.destroy();
vh.finish();
}
void
World::render(vk::CommandBuffer& cb)
{
keyboard_handle();
vh.fbprintf("%s\n",frame_timer.frame_rate_text_get());
const double time_now = time_wall_fp();
const bool blink_visible = int64_t(time_now*2) & 1;
# define BLINK(txt,pad) ( blink_visible ? txt : pad )
vh.fbprintf
("Compiled: %s\n",
#ifdef __OPTIMIZE__
"WITH OPTIMIZATION"
#else
BLINK("WITHOUT OPTIMIZATION","")
#endif
);
vh.fbprintf
("Eye location: [%5.1f, %5.1f, %5.1f] "
"Eye direction: [%+.2f, %+.2f, %+.2f]\n",
eye_location.x, eye_location.y, eye_location.z,
eye_direction.x, eye_direction.y, eye_direction.z);
vh.fbprintf
("Texture: %s ('t') Light location: [%5.1f, %5.1f, %5.1f]\n",
opt_texture ? "ON " : BLINK("OFF"," "),
light_location.x, light_location.y, light_location.z);
vh.fbprintf
("Pipeline Variant: %s ('v') Tryout 1: %s ('y') "
"Tryout 2: %s ('Y') Tryout 3: %s ('z')\n",
pipeline_variant_str[pipeline_variant],
opt_tryout1 ? BLINK("ON "," ") : "OFF",
opt_tryout2 ? BLINK("ON "," ") : "OFF",
opt_tryout3 ? BLINK("ON "," ") : "OFF");
pVariable_Control_Elt* const cvar = variable_control.current;
vh.fbprintf("VAR %s = %.5f (TAB or '`' to change, +/- to adjust)\n",
cvar->name,cvar->get_val());
pMatrix eye_from_global =
pMatrix_Rotation(eye_direction,pVect(0,0,-1))
* pMatrix_Translate(-eye_location);
transform.eye_from_global_set( eye_from_global );
const int win_width = vh.s_extent.width;
const int win_height = vh.s_extent.height;
const float aspect = float(win_width) / win_height;
const float n_dist = 0.01;
const float xr = .8 * n_dist;
transform.clip_from_eye_set
( pMatrix_Frustum( -xr, xr, -xr/aspect, xr/aspect, n_dist, 5000 ) );
uni_light_simple->color = color_white * opt_light_intensity;
uni_light_simple->position = transform.eye_from_global * light_location;
uni_light_simple.to_dev();
uni_misc->opt_tryoutf += 0;
uni_misc.to_dev();
if ( !pipe_plain )
pipe_plain
.init( vh.qs )
.ds_uniform_use( "BIND_LIGHT_SIMPLE", uni_light_simple )
.ds_uniform_use( "BIND_MISC", uni_misc )
.ds_use( sampler, texture_id_syllabus )
.shader_inputs_info_set<pCoor,pNorm,pColor,pTCoor>()
.shader_code_set
("demo-03-shdr.cc", "vs_main();", nullptr, "fs_main();")
.topology_set( vk::PrimitiveTopology::eTriangleList )
.create();
bset_plain.reset(pipe_plain);
pCoor p0 = { 0, 0, 0 };
pCoor p1 = { 9, 6, -9 };
pCoor p2 = { 0, 5, -5 };
pNorm tri_norm = cross( p0, p1, p2 );
pColor color_tri( .2, .900, .1 );
bset_plain << p0 << p1 << p2;
bset_plain << pTCoor(0,0) << pTCoor(1,1) << pTCoor(0,1);
bset_plain << color_tri << color_red << color_blue;
bset_plain << tri_norm << tri_norm << tri_norm;
bset_plain << pCoor(-1,-1,-2) << pCoor(-5,3,-2) << pCoor(-5,-1,-2);
bset_plain << color_light_gray << color_light_gray << color_light_gray;
bset_plain << pTCoor(1,1) << pTCoor(0,0) << pTCoor(0,1);
bset_plain << pCoor(-1,-1,-2) << pCoor(-1,3,-2) << pCoor(-5,3,-2);
bset_plain << color_green << color_green << color_green;
bset_plain << pTCoor(1,1) << pTCoor(1,0) << pTCoor(0,0);
pNorm snorm = cross( pCoor(-4,0,-2), pCoor(-4,2,-2), pCoor(-2,0,-2) );
bset_plain << snorm << snorm << snorm << snorm << snorm << snorm;
bset_plain.to_dev();
pipe_plain.ds_set( transform );
pipe_plain.record_draw(cb, bset_plain);
if ( !opt_pause ) world_time += time_now - time_last_update;
time_last_update = time_now;
const float omega = 1;
const float theta_0 = world_time * omega;
Hyperboloid_Info& h = hyperb_info;
if ( true )
{
uni_hw05->front[0] = color_red;
uni_hw05->back[0] = color_red;
uni_hw05->front[1] = color_lsu_spirit_gold;
uni_hw05->back[1] = color_lsu_spirit_purple;
uni_hw05->front[2] = color_lsu_business_purple;
uni_hw05->back[2] = color_gold;
uni_hw05->front[3] = color_salmon;
uni_hw05->back[3] = color_rosy_brown;
uni_hw05->front[4] = color_aquamarine;
uni_hw05->back[4] = color_peru;;
uni_hw05->front[5] = color_navajo_white;
uni_hw05->back[5] = color_white;
uni_hw05.to_dev();
}
if ( !pipe_hyperb )
pipe_hyperb
.init( vh.qs )
.ds_uniform_use( "BIND_LIGHT_SIMPLE", uni_light_simple )
.ds_uniform_use( "BIND_MISC", uni_misc )
.ds_uniform_use( "BIND_HW05", uni_hw05 )
.ds_use( sampler, texture_id_syllabus )
.shader_inputs_info_set<pCoor,pNorm,int,pTCoor>()
.shader_code_set
("hw04-shdr.cc", "vs_main();", "gs_main();", "fs_main();")
.topology_set( vk::PrimitiveTopology::eTriangleList )
.create();
if ( !pipe_hyperb_strip )
pipe_hyperb_strip
.init( vh.qs )
.ds_uniform_use( "BIND_LIGHT_SIMPLE", uni_light_simple )
.ds_uniform_use( "BIND_MISC", uni_misc )
.ds_uniform_use( "BIND_HW05", uni_hw05 )
.ds_use( sampler, texture_id_syllabus )
.shader_inputs_info_set<pCoor,pNorm,int,pTCoor>()
.shader_code_set
("hw04-shdr.cc", "vs_main();", "gs_main();", "fs_main();")
.topology_set( vk::PrimitiveTopology::eTriangleStrip )
.create();
if ( !pipe_hyperb_points )
pipe_hyperb_points
.init( vh.qs )
.ds_uniform_use( "BIND_LIGHT_SIMPLE", uni_light_simple )
.ds_uniform_use( "BIND_MISC", uni_misc )
.ds_uniform_use( "BIND_HW05", uni_hw05 )
.ds_storage_follow( "BIND_HYPERB_COORDS", sto_hyperb_coords )
.ds_storage_follow( "BIND_HYPERB_NORMS", sto_hyperb_norms )
.ds_use( sampler, texture_id_syllabus )
.shader_inputs_info_set()
.shader_code_set
("hw05-shdr-sol.cc", "vs_points();", "gs_points();", "fs_points();")
.topology_set( vk::PrimitiveTopology::ePointList )
.create();
if ( h.n_sides_constructed != opt_n_sides ) h.serial++;
pCoor bot_ctr = h.bot_ctr_pos;
pCoor top_ctr = h.top_ctr_pos;
pCoor line_0_bot_pos = h.line_0_bot_pos;
pVect line_0_dir = hyperb_info.line_0_dir;
pVect hyperb_vz(bot_ctr,top_ctr);
pNorm hyperb_az(hyperb_vz);
pVect bot_vx(bot_ctr,line_0_bot_pos);
pMatrix_Rotation rot(hyperb_az,theta_0);
pMatrix trot =
pMatrix_Translate( bot_ctr ) * rot * pMatrix_Translate( -bot_ctr );
int n_levels = opt_n_sides/3;
int n_sides = opt_n_sides;
if ( !bset_hyperb || hyperb_serial != h.serial )
{
hyperb_serial = h.serial;
h.n_sides_constructed = n_sides;
pCoor line_0_top_pos =
line_0_bot_pos
+ hyperb_az.magnitude / dot( hyperb_az, line_0_dir ) * line_0_dir;
float delta_theta = 2 * M_PI / n_sides;
pVect delta_z = (1.0/n_levels ) * hyperb_vz;
pVect line_v(line_0_bot_pos,line_0_top_pos);
pVect line_dv = (1.0/n_levels) * line_v;
pMatrix_Translate trans_to_hyp_local(-bot_ctr);
pNorm hyperb_ax( bot_vx );
pNorm hyperb_ay = cross( hyperb_az, hyperb_ax );
pMatrix_Rows rot_to_hyp_local(hyperb_ax,hyperb_ay,hyperb_az);
pMatrix hyperb_local_from_object = rot_to_hyp_local * trans_to_hyp_local;
const int s_levels = n_levels + 1;
const int s_sides = n_sides + 1;
const float n_levels_inv = 1.0 / n_levels;
const float n_sides_inv = 1.0 / n_sides;
uni_hw05->s_sides = s_sides;
uni_hw05->s_levels = s_levels;
uni_hw05->n_sides = n_sides;
uni_hw05->n_levels = n_levels;
uni_hw05->n_sides_inv = n_sides_inv;
uni_hw05->n_levels_inv = n_levels_inv;
uni_hw05->local_from_object = hyperb_local_from_object;
uni_hw05.to_dev();
auto idxf = [&](int lev, int side) { return lev + side * s_levels; };
sto_hyperb_coords.resize( s_levels * s_sides );
sto_hyperb_norms.resize( s_levels * s_sides );
vector<vec4>& coords = sto_hyperb_coords.vals;
vector<vec4>& norms = sto_hyperb_norms.vals;
pVect top_vx(top_ctr,line_0_top_pos);
for ( int side = 0; side <= n_sides; side++ )
{
float theta = side * delta_theta;
pMatrix_Rotation rot(hyperb_az,theta);
pCoor line_bot_pos = bot_ctr + rot * bot_vx;
pVect l_dv = rot * line_dv;
for ( int lev = 0; lev <= n_levels; lev++ )
{
pCoor p_line = line_bot_pos + lev * l_dv;
coords[ idxf(lev,side) ] = p_line;
pCoor ctr = bot_ctr + lev * delta_z;
pVect tc = cross(hyperb_az,pVect(ctr,p_line));
pNorm n = cross(tc,l_dv);
norms[ idxf(lev,side) ] = n;
}
}
sto_hyperb_coords.to_dev();
sto_hyperb_norms.to_dev();
switch ( pipeline_variant ) {
case PV_Individ:
bset_hyperb.reset(pipe_hyperb);
for ( int side = 0; side < n_sides; side++ )
for ( int lev = 0; lev < n_levels; lev++ )
{
pCoor p00 = coords[ idxf( lev, side ) ];
pCoor p01 = coords[ idxf( lev, side+1 ) ];
pCoor p10 = coords[ idxf( lev+1, side ) ];
pCoor p11 = coords[ idxf( lev+1, side+1 ) ];
bset_hyperb << p00 << p01 << p10;
bset_hyperb << p01 << p11 << p10;
bset_hyperb << pTCoor(0,0) << pTCoor(0,1) << pTCoor(1,0);
bset_hyperb << pTCoor(0,1) << pTCoor(1,1) << pTCoor(1,0);
pNorm n00 = norms[ idxf( lev, side ) ];
pNorm n01 = norms[ idxf( lev, side+1 ) ];
pNorm n10 = norms[ idxf( lev+1, side ) ];
pNorm n11 = norms[ idxf( lev+1, side+1 ) ];
bset_hyperb << n00 << n01 << n10;
bset_hyperb << n01 << n11 << n10;
int c1 = side == 0 ? ( lev%2 ? 5 : 2 ) : 1;
int c2 = side == 0 ? ( lev%2 ? 3 : 4 ) : 1;
bset_hyperb << c1 << c1 << c1 << c2 << c2 << c2;
}
break;
case PV_Strip:
bset_hyperb.reset(pipe_hyperb_strip);
for ( int side = 0; side < n_sides; side++ )
for ( int lev = 0; lev <= n_levels; lev++ )
{
pCoor p00 = coords[ idxf( lev, side ) ];
pCoor p01 = coords[ idxf( lev, side + 1 ) ];
bset_hyperb << p00 << p01;
float tex_y = 1 - lev * n_levels_inv;
pCoor p00_l = hyperb_local_from_object * p00;
pCoor p01_l = hyperb_local_from_object * p01;
float theta0 = atan2f( p00_l.y, p00_l.x );
float theta1 = atan2f( p01_l.y, p01_l.x );
float tex_x_scale_factor = 1.5;
float tex_x0 = theta0 * tex_x_scale_factor;
float tex_x1 = theta1 * tex_x_scale_factor;
bset_hyperb
<< pTCoor( tex_x0, tex_y ) << pTCoor( tex_x1, tex_y );
pNorm n00 = norms[ idxf( lev, side ) ];
pNorm n01 = norms[ idxf( lev, side + 1 ) ];
bset_hyperb << n00 << n01;
int c1 = lev == 0 ? 0 : side == 0 ? ( (lev+1)%2 ? 5 : 2 ) : 1;
int c2 = lev == 0 ? 0 : side == 0 ? ( (lev+1)%2 ? 3 : 4 ) : 1;
bset_hyperb << c1 << c2;
}
break;
case PV_Points:
break;
default: assert( false );
}
bset_hyperb.to_dev();
}
switch ( pipeline_variant ) {
case PV_Individ:
pipe_hyperb.ds_set( transform * trot );
pipe_hyperb.record_draw(cb, bset_hyperb);
break;
case PV_Strip:
pipe_hyperb_strip.ds_set( transform * trot );
pipe_hyperb_strip.record_draw(cb, bset_hyperb);
break;
case PV_Points:
{
const int n_vtx = n_levels * n_sides;
pipe_hyperb_points.ds_set( transform * trot );
pipe_hyperb_points.record_draw(cb, n_vtx );
}
break;
default: assert( false );
}
shapes.record_tetrahedron(cb,transform,light_location,0.2);
}
void
World::keyboard_handle()
{
const int key = vh.keyboard_key_get();
if ( !key ) return;
pVect adjustment(0,0,0);
pVect user_rot_axis(0,0,0);
const bool kb_mod_s = vh.keyboard_shift;
const bool kb_mod_c = vh.keyboard_control;
const float move_amt = kb_mod_s ? 2.0 : kb_mod_c ? 0.08 : 0.4;
switch ( key ) {
case FB_KEY_LEFT: adjustment.x = -move_amt; break;
case FB_KEY_RIGHT: adjustment.x = move_amt; break;
case FB_KEY_PAGE_UP: adjustment.y = move_amt; break;
case FB_KEY_PAGE_DOWN: adjustment.y = -move_amt; break;
case FB_KEY_DOWN: adjustment.z = move_amt; break;
case FB_KEY_UP: adjustment.z = -move_amt; break;
case FB_KEY_DELETE: user_rot_axis.y = 1; break;
case FB_KEY_INSERT: user_rot_axis.y = -1; break;
case FB_KEY_HOME: user_rot_axis.x = 1; break;
case FB_KEY_END: user_rot_axis.x = -1; break;
case 'n': bset_hyperb.reset(); break;
case '1': scene_setup_1(); break;
case '2': scene_setup_2(); break;
case 'b': case 'B': opt_move_item = MI_Ball; break;
case 'e': case 'E': opt_move_item = MI_Eye; break;
case 'l': case 'L': opt_move_item = MI_Light; break;
case 'p': case 'P': opt_pause = !opt_pause; break;
case 't': case 'T': opt_texture = !opt_texture;
uni_misc->opt_assign.x = int(opt_texture);
break;
case 'v': case 'V':
hyperb_info.serial++;
if ( ++pipeline_variant >= PV_SIZE ) pipeline_variant = 0;
break;
case 'y': opt_tryout1 = !opt_tryout1;
uni_misc->opt_tryout.x = int(opt_tryout1);
break;
case 'Y': opt_tryout2 = !opt_tryout2;
uni_misc->opt_tryout.y = int(opt_tryout2);
break;
case 'z': opt_tryout3 = !opt_tryout3;
uni_misc->opt_tryout.z = int(opt_tryout3);
break;
case FB_KEY_TAB:
if ( !kb_mod_s ) { variable_control.switch_var_right(); break; }
case 96: variable_control.switch_var_left(); break;
case '-':case '_': variable_control.adjust_lower(); break;
case '+':case '=': variable_control.adjust_higher(); break;
default: printf("Unknown key, %d\n",key); break;
}
if ( user_rot_axis.x || user_rot_axis.y )
{
pMatrix_Rotation rotall(eye_direction,pVect(0,0,-1));
user_rot_axis *= invert(rotall);
eye_direction *= pMatrix_Rotation(user_rot_axis, M_PI * 0.03);
}
if ( adjustment.x || adjustment.y || adjustment.z )
{
const double angle =
fabs(eye_direction.y) > 0.99
? 0 : atan2(eye_direction.x,-eye_direction.z);
pMatrix_Rotation rotall(pVect(0,1,0),-angle);
adjustment *= rotall;
switch ( opt_move_item ){
case MI_Light: light_location += adjustment; break;
case MI_Eye: eye_location += adjustment; break;
default: break;
}
}
}
int
main(int argv, char **argc)
{
pVulkan_Helper pvulkan_helper(argv,argc);
World world(pvulkan_helper);
world.setup_and_run();
return 0;
}