2021-03-31 16:04:02 +00:00
// compile with:
// ./mymake -O3 inner-maps
2021-03-31 16:04:34 +00:00
// used in: https://twitter.com/zenorogue/status/1212408644941295619
2021-03-31 16:04:02 +00:00
// run with:
// ./hyper -innner-map -noscr -canvas r -canvas i -wsh 0 -smart 4 -shott 0 -alpha 1
# include "rogueviz.h"
namespace hr {
namespace inner {
bool out = true ;
EX struct renderbuffer * buf1 , * buf2 ;
map < cell * , basic_textureinfo > lti ;
ld mdist ;
bool for_klein = false ;
ld alpha = - .7 ;
cell * rendercenter ;
shiftmatrix rendercenterV ;
bool auto_move = false ;
ld texture_alpha = 1 ;
ld inner_alpha = 1 ;
bool dense = false ;
// should do 30x -- temporarily disabled
ld iterations = 1 ;
ld iterations_bank ;
void gentexture ( ) {
if ( out ) iterations_bank + = iterations ;
while ( iterations_bank > = 1 ) {
iterations_bank - = 1 ;
println ( hlog , " # = " , isize ( lti ) ) ;
dynamicval < bool > b ( out , false ) ;
dynamicval < ld > va ( pconf . alpha , texture_alpha ) ;
if ( ! buf1 ) {
buf1 = new renderbuffer ( rug : : texturesize , rug : : texturesize , true ) ;
buf2 = new renderbuffer ( rug : : texturesize , rug : : texturesize , true ) ;
}
resetbuffer rb ;
rug : : calcparam_rug ( ) ;
models : : configure ( ) ;
buf1 - > enable ( ) ;
buf1 - > clear ( 0 ) ;
buf2 - > use_as_texture ( ) ;
draw_boundary ( 0 ) ;
draw_boundary ( 1 ) ;
draw_model_elements ( ) ;
drawthemap ( ) ;
drawqueue ( ) ;
calcparam ( ) ;
rb . reset ( ) ;
swap ( buf1 , buf2 ) ;
rendercenter = centerover ;
rendercenterV = gmatrix [ centerover ] ;
}
}
void frame ( ) {
gentexture ( ) ;
if ( auto_move ) {
color_t col = minf [ moReptile ] . color ;
drawMonsterType ( moReptile , NULL , shiftless ( spin ( alpha ) ) , col , mdist , col ) ;
mapeditor : : drawplayer = false ;
}
}
bool done ;
hpcshape edgeshape ;
hpcshape circ ;
ld crad = dense ? .5 : 1.82 ;
ld ceps = .02 ;
ld crad_p ;
void need_redo ( ) {
done = false ;
}
void make_shape ( ) {
if ( done ) return ;
done = true ;
cgi . bshape ( circ , PPR : : WALL ) ;
circ . flags | = POLY_TRIANGLES ;
int k = for_klein ? 1 : 2 ;
int maxz = for_klein ? 120 : 30 ;
for ( int z = 0 ; z < maxz ; z + + ) {
ld ra = ( z + 0. ) / maxz * crad , rb = ( z + 1. ) / maxz * crad ;
for ( int i = 0 ; i < 360 ; i + = k ) {
ld a = i * degree ;
ld b = ( i + k ) * degree ;
cgi . hpcpush ( xspinpush0 ( a , ra ) ) ;
cgi . hpcpush ( xspinpush0 ( a , rb ) ) ;
cgi . hpcpush ( xspinpush0 ( b , rb ) ) ;
if ( z ) {
cgi . hpcpush ( xspinpush0 ( a , ra ) ) ;
cgi . hpcpush ( xspinpush0 ( b , ra ) ) ;
cgi . hpcpush ( xspinpush0 ( b , rb ) ) ;
}
}
}
cgi . finishshape ( ) ;
println ( hlog , " circ vertices = " , circ . e - circ . s ) ;
cgi . bshape ( edgeshape , PPR : : WALL ) ;
for ( int i = 0 ; i < = 360 ; i + = k ) {
ld a = i * degree ;
cgi . hpcpush ( xspinpush0 ( a , crad - ceps ) ) ;
}
for ( int i = 0 ; i < = 360 ; i + = k ) {
ld a = i * degree ;
cgi . hpcpush ( xspinpush0 ( a , crad + ceps ) ) ;
}
cgi . finishshape ( ) ;
cgi . extra_vertices ( ) ;
hyperpoint ph = xspinpush0 ( 0 , crad ) ;
ph / = ( inner_alpha + ph [ 2 ] ) ;
crad_p = ph [ 0 ] ;
}
set < cell * > gs ;
bool render ( cell * c , const shiftmatrix & V ) {
if ( ! buf1 | | ! buf2 | | ! rendercenter ) return false ;
make_shape ( ) ;
if ( false & & ! gs . count ( c ) ) {
gs . insert ( c ) ;
c - > mondir = hrand ( c - > type ) ;
dont_face_pc = true ;
switch ( hrand ( 100 ) ) {
case 0 :
c - > monst = moOrangeDog ;
break ;
case 1 :
c - > item = itHell ;
break ;
case 2 :
c - > monst = moSalamander ;
break ;
case 3 :
c - > monst = moButterfly ;
break ;
case 4 :
c - > monst = moSparrowhawk ;
break ;
}
}
if ( dense ? pseudohept ( c ) : cdist50 ( c ) = = 0 ) {
dynamicval < color_t > po ( poly_outline , 0x000000FF ) ;
auto & p = lti [ c ] ;
p . texture_id = buf2 - > renderedTexture ;
p . tvertices . clear ( ) ;
/*inner_alpha = anyshiftclick ? 1 : 0;
hyperpoint ph = xspinpush0 ( 0 , crad ) ;
ph / = ( inner_alpha + ph [ 2 ] ) ;
crad_p = ph [ 0 ] ;
*/
for ( int i = circ . s ; i < circ . e ; i + + ) {
hyperpoint h = cgi . hpc [ i ] ;
// hyperboloid to Poincare
h / = ( inner_alpha + h [ 2 ] ) ;
// scale up
h / = crad_p ;
h * = .99999999 ;
// Poincare to hyperboloid
h = perspective_to_space ( h , inner_alpha , cgclass ) ;
/*
ld hr = sqhypot_d ( 2 , h ) ;
ld hz = ( 1 + hr ) / ( 1 - hr ) ;
h [ 0 ] * = ( hz + 1 ) ;
h [ 1 ] * = ( hz + 1 ) ;
h [ 2 ] = hz ;
*/
// move according to V
h = rendercenterV . T * inverse ( ggmatrix ( rendercenter ) . T ) * V . T * h ;
// texture coordinates
// hyperpoint scr;
// dynamicval<ld> b(pconf.alpha, anyshiftclick ? pconf.alpha : texture_alpha);
// applymodel(h, scr);
hyperpoint scr = h / ( texture_alpha + h [ 2 ] ) ;
p . tvertices . push_back ( glhr : : makevertex ( .5 + .5 * scr [ 0 ] , .5 - .5 * scr [ 1 ] , 0 ) ) ;
}
queuepoly ( V , circ , 0xFFFFFFFF ) . tinf = & p ;
queuepoly ( V , edgeshape , darkena ( c - > landparam , 0 , 0xFF ) ) ;
}
return false ;
}
void shift ( ) {
if ( auto_move ) {
centerover = currentmap - > gamestart ( ) ;
mdist = ( ticks % 10000 ) * 6 / 10000. ;
View = spin ( alpha ) * xpush ( - mdist ) * spin ( - alpha ) ;
anims : : moved ( ) ;
centerover - > monst = moNone ;
forCellEx ( c1 , centerover ) c1 - > monst = moNone ;
}
}
void show ( ) {
cmode = sm : : SIDE | sm : : MAYDARK ;
2022-07-05 14:03:12 +00:00
gamescreen ( ) ;
2021-03-31 16:04:02 +00:00
dialog : : init ( XLAT ( " inner maps " ) , 0xFFFFFFFF , 150 , 0 ) ;
add_edit ( texture_alpha ) ;
add_edit ( inner_alpha ) ;
add_edit ( dense ) ;
add_edit ( crad ) ;
add_edit ( ceps ) ;
add_edit ( auto_move ) ;
add_edit ( iterations ) ;
dialog : : addBack ( ) ;
dialog : : display ( ) ;
}
2021-04-07 16:01:03 +00:00
void enable ( ) {
2021-03-31 16:04:02 +00:00
using rogueviz : : rv_hook ;
rv_hook ( hooks_frame , 100 , frame ) ;
rv_hook ( hooks_drawcell , 100 , render ) ;
rv_hook ( anims : : hooks_anim , 100 , shift ) ;
rv_hook ( hooks_o_key , 80 , [ ] ( o_funcs & v ) { v . push_back ( named_dialog ( " inner maps " , show ) ) ; } ) ;
2021-04-07 16:01:03 +00:00
}
auto hook = arg : : add3 ( " -inner-map " , enable )
2021-03-31 16:04:02 +00:00
+ addHook ( hooks_configfile , 100 , [ ] {
param_f ( texture_alpha , " inner_talpha " )
- > editable ( 0 , 5 , .1 , " texture projection distance " , " " , ' t ' ) ;
param_f ( inner_alpha , " inner_ialpha " )
- > editable ( 0 , 5 , .1 , " inner projection distance " , " " , ' i ' )
- > set_reaction ( need_redo ) ;
param_b ( dense , " inner_dense " )
- > editable ( " densely packed maps " , ' d ' ) ;
param_f ( crad , " inner_crad " )
- > editable ( 0 , 10 , .1 , " radii of the inner maps " , " " , ' r ' )
- > set_reaction ( need_redo ) ;
param_f ( ceps , " inner_ceps " )
- > editable ( 0 , 0.1 , .001 , " map frame size " , " " , ' f ' )
- > set_reaction ( need_redo ) ;
param_b ( auto_move , " auto_move " )
- > editable ( " animate " , ' a ' ) ;
param_f ( iterations , " inner_iterations " )
- > editable ( 0 , 30 , 0.2 , " iterations per frame " ,
" How many times per frame should we re-render the map " ,
' i ' )
- > set_reaction ( need_redo ) ;
2021-04-07 16:01:03 +00:00
} )
2021-06-25 11:53:23 +00:00
+ addHook_rvslides ( 52 , [ ] ( string s , vector < tour : : slide > & v ) {
2021-04-07 16:01:03 +00:00
if ( s ! = " projections " ) return ;
using namespace tour ;
v . push_back ( slide {
" projections/hyperbolic to hyperbolic " , 10 , LEGAL : : NONE | QUICKGEO ,
" We can also project a hyperbolic plane to a hyperbolic plane of different curvature. \n \n "
2021-04-16 17:41:45 +00:00
" Creatures living in the hyperbolic world may use the native Poincaré model to get conformal, circular, and totally useless maps of their whole world. \n \n "
2021-04-07 16:01:03 +00:00
" Press 'o' to change the settings. "
,
[ ] ( presmode mode ) {
slide_url ( mode , ' t ' , " Twitter link (with description) " , " https://twitter.com/zenorogue/status/1212408644941295619 " ) ;
setCanvas ( mode , ' r ' ) ;
if ( mode = = pmStart ) {
if ( ! shmup : : on ) restart_game ( rg : : shmup ) ;
slide_backup ( mapeditor : : drawplayer , true ) ;
enable ( ) ;
start_game ( ) ;
}
} } ) ;
} ) ;
2021-03-31 16:04:02 +00:00
}
}