#if 0
:Def: Primitive Topology (in Vulkan) vk::PrimitiveTopology::ePointList
vk::PrimitiveTopology::eLineList
vk::PrimitiveTopology::eLineStrip
vk::PrimitiveTopology::eTriangleList
vk::PrimitiveTopology::eTriangleStrip
vk::PrimitiveTopology::eTriangleFan
vk::PrimitiveTopology::eLineListWithAdjacency
vk::PrimitiveTopology::eLineStripWithAdjacency
vk::PrimitiveTopology::eTriangleListWithAdjacency
vk::PrimitiveTopology::eTriangleStripWithAdjacency
vk::PrimitiveTopology::ePatchList
:Def: Vertex Attribute bset << pCoor(1,2,3); glVertex3fv( pCoor(1,2,3) );
bset << color_orange; glColor3fv(color_orange); bset << pVect(1,0,0); glNormal(1,0,0);
GL_MAX_VERTEX_ATTRIBS;
#endif
#define MAIN_INCLUDE
#include <vhelper.h>
#include <vstroke.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"
array tops
{ vk::PrimitiveTopology::eTriangleList,
vk::PrimitiveTopology::eTriangleStrip,
vk::PrimitiveTopology::eLineStrip,
vk::PrimitiveTopology::eLineList
};
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 cb_keyboard();
pVulkan_Helper& vh;
VFixed_Function_State_Manager ff_state;
pFrame_Timer& frame_timer;
Shapes shapes;
pVariable_Control variable_control;
size_t opt_primitive;
pCoor light_location;
float opt_light_intensity;
enum { MI_Eye, MI_Light, MI_Ball, MI_Ball_V, MI_COUNT } opt_move_item;
bool opt_2_color;
int slices; pCoor sphere_location;
float sphere_size;
pCoor eye_location;
pVect eye_direction;
bool global_transform_stale;
VTransform transform;
VBufferV<Uni_Lighting> uni_light;
VPipeline pipe_lonely;
VPipeline pipe_sphere;
VVertex_Buffer_Set bset_lonely, bset_sphere;
};
void
World::setup_and_run()
{
vh.init();
vh.display_cb_set([&](){});
vh.cbs_cmd_record.push_back( [&](vk::CommandBuffer& cb){ render(cb); });
eye_location = pCoor(1,0.5,3);
eye_location = pCoor(1,.5,10.2);
eye_direction = pVect(0,0,-1);
opt_light_intensity = 4.3;
light_location = pCoor(6.2,0.0,3.7);
opt_2_color = false;
sphere_location = pCoor(0,0,-0.5);
sphere_size = 2;
slices = 20;
variable_control.insert(slices,"Slices in Sphere",1,2);
variable_control.insert(opt_light_intensity,"Light Intensity");
variable_control.insert(sphere_size,"Sphere Size");
opt_move_item = MI_Eye;
opt_primitive = 0;
uni_light.init(vh.dev_phys,vh.dev,vk::BufferUsageFlagBits::eUniformBuffer);
pColor black(0,0,0,0);
uni_light->cgl_LightModel.ambient = pColor(.4,.4,.4,1);
uni_light->cgl_LightSource[0].position = light_location;
uni_light->cgl_LightSource[0].diffuse = pColor(1,1,1,1);
uni_light->cgl_LightSource[0].ambient = black;
uni_light->cgl_LightSource[0].specular = black;
uni_light->cgl_LightSource[0].constantAttenuation = .5;
uni_light->cgl_LightSource[0].linearAttenuation = 1.0;
uni_light->cgl_LightSource[0].quadraticAttenuation = 0;
vh.message_loop_spin();
uni_light.destroy();
pipe_lonely.destroy();
pipe_sphere.destroy();
bset_lonely.destroy();
bset_sphere.destroy();
shapes.destroy();
transform.destroy();
vh.finish();
}
void
World::render(vk::CommandBuffer& cb)
{
cb_keyboard();
vh.fbprintf("%s\n",frame_timer.frame_rate_text_get());
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
("Light location: [%5.1f, %5.1f, %5.1f] Render Using: ('n') %s "
"Use %s colors ('c')\n",
light_location.x, light_location.y, light_location.z,
vk::to_string(tops[opt_primitive]).c_str(),
opt_2_color ? "TWO" : "ONE" );
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());
transform.eye_from_global_set
( pMatrix_Rotation(eye_direction,pVect(0,0,-1))
* pMatrix_Translate(-eye_location) );
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->cgl_LightSource[0].diffuse = color_white * opt_light_intensity;
uni_light->cgl_LightSource[0].position =
transform.eye_from_global * light_location;
uni_light.to_dev();
if ( !pipe_lonely )
pipe_lonely
.init( vh.qs )
.ds_follow( transform )
.ds_use( uni_light )
.ds_set_material_back( color_red )
.shader_lighting_on()
.topology_set( vk::PrimitiveTopology::eTriangleList )
.create();
bset_lonely.reset(pipe_lonely);
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( .470, .553, .965 );
bset_lonely << p0 << p1 << p2;
bset_lonely << color_tri << color_tri << color_tri;
bset_lonely << tri_norm << tri_norm << tri_norm;
bset_lonely.to_dev();
pipe_lonely.record_draw(cb, bset_lonely);
auto prim_want = tops[opt_primitive];
if ( pipe_sphere.p_in_asm_ci.topology != prim_want && vh.frame_serial_need() )
pipe_sphere.destroy();
if ( !pipe_sphere )
pipe_sphere
.init( vh.qs )
.ds_use( uni_light )
.ds_set_material_back( color_red )
.shader_lighting_on()
.topology_set( prim_want )
.create();
const pColor lsu_spirit_purple(0x580da6);
const pColor lsu_spirit_gold(0xf9b237);
pColor color = lsu_spirit_gold;
pColor color2 = opt_2_color ? lsu_spirit_purple : color;
const float delta_eta = M_PI / slices;
const float delta_theta = delta_eta;
bset_sphere.reset(pipe_sphere);
switch ( prim_want ) {
case vk::PrimitiveTopology::eTriangleList: case vk::PrimitiveTopology::eLineList: case vk::PrimitiveTopology::eLineStrip: for ( int slice = 0; slice < slices; slice++ )
{
const float eta0 = slice * delta_eta, eta1 = eta0 + delta_eta;
const float y0 = cosf(eta0), y1 = cosf(eta1);
const float slice_r0 = sinf(eta0), slice_r1 = sinf(eta1);
for ( int j=0; j<=2*slices; j++ )
{
const float theta0 = j * delta_theta;
const float theta1 = theta0 + delta_theta;
bset_sphere
<< color
<< pNorm( slice_r1 * cosf(theta0), y1, slice_r1 * sinf(theta0) )
<< pCoor( slice_r1 * cosf(theta0), y1, slice_r1 * sinf(theta0) )
<< color
<< pNorm( slice_r0 * cosf(theta0), y0, slice_r0 * sinf(theta0) )
<< pCoor( slice_r0 * cosf(theta0), y0, slice_r0 * sinf(theta0) )
<< color
<< pNorm( slice_r1 * cosf(theta1), y1, slice_r1 * sinf(theta1) )
<< pCoor( slice_r1 * cosf(theta1), y1, slice_r1 * sinf(theta1) )
<< color2
<< pNorm( slice_r1 * cosf(theta1), y1, slice_r1 * sinf(theta1) )
<< pCoor( slice_r1 * cosf(theta1), y1, slice_r1 * sinf(theta1) )
<< color2
<< pNorm( slice_r0 * cosf(theta0), y0, slice_r0 * sinf(theta0) )
<< pCoor( slice_r0 * cosf(theta0), y0, slice_r0 * sinf(theta0) )
<< color2
<< pNorm( slice_r0 * cosf(theta1), y0, slice_r0 * sinf(theta1) )
<< pCoor( slice_r0 * cosf(theta1), y0, slice_r0 * sinf(theta1) );
}
}
break;
case vk::PrimitiveTopology::eTriangleStrip:
for ( int i=0; i<slices; i++ )
{
const float eta0 = i * delta_eta;
const float eta1 = eta0 + delta_eta;
const float y0 = cosf(eta0), y1 = cosf(eta1);
const float slice_r0 = sinf(eta0), slice_r1 = max(0.0f,sinf(eta1));
const float delta_theta = delta_eta;
for ( int j=0; j <= 2*slices; j++ )
{
const float theta = j * delta_theta;
const float theta1 = theta + delta_theta;
pVect n0( slice_r0 * sinf(theta1), y0, slice_r0 * cosf(theta1) );
bset_sphere << n0 << pCoor(n0) << color;
pVect n1( slice_r1 * sinf(theta1), y1, slice_r1 * cosf(theta1) );
bset_sphere << n1 << pCoor(n1) << color2;
}
}
break;
default: assert( false );
}
bset_sphere.to_dev();
pipe_sphere
.ds_set( transform
* pMatrix_Translate( sphere_location )
* pMatrix_Scale(sphere_size) )
.record_draw(cb, bset_sphere);
shapes.record_tetrahedron(cb,transform,light_location,0.2);
}
void
World::cb_keyboard()
{
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 'b': case 'B': opt_move_item = MI_Ball; break;
case 'c': case 'C': opt_2_color = !opt_2_color; break;
case 'e': case 'E': opt_move_item = MI_Eye; break;
case 'l': case 'L': opt_move_item = MI_Light; break;
case 'n':
opt_primitive++;
if ( opt_primitive == tops.size() ) opt_primitive = 0;
break;
case 'N':
if ( !opt_primitive ) opt_primitive = tops.size();
opt_primitive--;
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 )
{
if ( opt_move_item != MI_Ball && opt_move_item != MI_Ball_V )
global_transform_stale = true;
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;
case MI_Ball: sphere_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;
}