2019-10-21 22:37:57 +00:00
// Hyperbolic Rogue -- raycaster
// Copyright (C) 2011-2019 Zeno Rogue, see 'hyper.cpp' for details
/** \file raycaster.cpp
* \ brief A raycaster to draw walls .
*/
# include "hyper.h"
namespace hr {
2020-03-27 20:49:20 +00:00
/** \brief raycaster */
2019-10-25 12:50:48 +00:00
EX namespace ray {
2020-03-21 09:49:07 +00:00
# if CAP_RAY
2019-11-03 13:19:11 +00:00
2019-10-25 12:50:48 +00:00
/** texture IDs */
2019-10-26 08:32:44 +00:00
GLuint txConnections = 0 , txWallcolor = 0 , txTextureMap = 0 ;
2019-10-21 22:37:57 +00:00
2019-10-25 12:50:48 +00:00
EX bool in_use ;
EX bool comparison_mode ;
/** 0 - never use, 2 - always use, 1 = smart selection */
EX int want_use = 1 ;
2019-10-25 13:05:17 +00:00
EX ld exp_start = 1 , exp_decay_exp = 4 , exp_decay_poly = 10 ;
2020-04-11 22:40:15 +00:00
EX ld maxstep_sol = .05 ;
2019-10-25 22:43:15 +00:00
EX ld maxstep_nil = .1 ;
EX ld minstep = .001 ;
2019-10-27 00:23:20 +00:00
EX ld reflect_val = 0 ;
2019-11-08 13:59:19 +00:00
static const int NO_LIMIT = 999999 ;
EX ld hard_limit = NO_LIMIT ;
2019-10-25 13:18:31 +00:00
EX int max_iter_sol = 600 , max_iter_iso = 60 ;
2019-10-26 16:25:14 +00:00
EX int max_cells = 2048 ;
2019-10-25 22:12:30 +00:00
EX bool rays_generate = true ;
2019-11-08 13:58:46 +00:00
EX ld & exp_decay_current ( ) {
2020-05-09 08:41:15 +00:00
return ( sn : : in ( ) | | hyperbolic | | sl2 ) ? exp_decay_exp : exp_decay_poly ;
2019-10-25 21:24:31 +00:00
}
2019-11-08 13:58:46 +00:00
EX int & max_iter_current ( ) {
2020-05-09 08:41:15 +00:00
if ( nonisotropic | | stretch : : in ( ) ) return max_iter_sol ;
2019-10-25 21:24:31 +00:00
else return max_iter_iso ;
}
2019-10-25 22:43:15 +00:00
ld & maxstep_current ( ) {
2020-05-09 08:41:15 +00:00
if ( sn : : in ( ) | | stretch : : in ( ) ) return maxstep_sol ;
2019-10-25 22:43:15 +00:00
else return maxstep_nil ;
}
2019-10-21 22:37:57 +00:00
# define IN_ODS 0
2019-10-26 15:03:10 +00:00
eGeometry last_geometry ;
2019-10-25 12:50:48 +00:00
/** is the raycaster available? */
EX bool available ( ) {
2019-11-09 10:18:52 +00:00
if ( noGUI ) return false ;
if ( ! vid . usingGL ) return false ;
2019-10-25 12:50:48 +00:00
if ( WDIM = = 2 ) return false ;
2019-12-14 11:12:24 +00:00
if ( hyperbolic & & pmodel = = mdPerspective & & ! kite : : in ( ) )
2019-10-25 12:50:48 +00:00
return true ;
2020-05-08 19:18:47 +00:00
if ( sphere & & pmodel = = mdPerspective & & ! rotspace )
return true ;
2019-11-23 19:39:38 +00:00
if ( nil & & S7 = = 8 )
return false ;
2020-05-09 08:41:15 +00:00
if ( ( sn : : in ( ) | | nil | | sl2 ) & & pmodel = = mdGeodesic )
2019-10-25 12:50:48 +00:00
return true ;
2019-12-14 11:05:01 +00:00
if ( euclid & & pmodel = = mdPerspective & & ! bt : : in ( ) )
2019-10-25 12:50:48 +00:00
return true ;
2020-05-08 19:18:47 +00:00
if ( prod & & ( PURE | | BITRUNCATED ) )
return true ;
2020-05-09 08:41:15 +00:00
if ( pmodel = = mdPerspective & & stretch : : in ( ) )
2019-10-28 16:33:17 +00:00
return true ;
2019-10-25 12:50:48 +00:00
return false ;
}
/** do we want to use the raycaster? */
EX bool requested ( ) {
2020-03-29 15:35:42 +00:00
if ( cgflags & qRAYONLY ) return true ;
2020-05-09 08:41:15 +00:00
if ( stretch : : in ( ) ) return true ;
2019-10-25 12:50:48 +00:00
if ( ! want_use ) return false ;
2019-11-03 13:20:24 +00:00
# if CAP_TEXTURE
2019-11-03 10:00:47 +00:00
if ( texture : : config . tstate = = texture : : tsActive ) return false ;
2019-11-03 13:20:24 +00:00
# endif
2019-10-25 12:50:48 +00:00
if ( ! available ( ) ) return false ;
if ( want_use = = 2 ) return true ;
2020-05-09 08:41:15 +00:00
if ( sphere ) return false ; /* currently incompatible with primitives */
2019-10-25 12:50:48 +00:00
return racing : : on | | quotient ;
}
2020-03-29 15:35:42 +00:00
# if HDR
2019-10-21 22:37:57 +00:00
struct raycaster : glhr : : GLprogram {
2019-11-16 02:04:01 +00:00
GLint uStart , uStartid , uM , uLength , uFovX , uFovY , uIPD , uShift ;
2019-10-22 10:07:38 +00:00
GLint uWallstart , uWallX , uWallY ;
2019-10-26 08:32:44 +00:00
GLint tConnections , tWallcolor , tTextureMap ;
2019-11-09 11:12:16 +00:00
GLint uBinaryWidth , uPLevel , uLP , uStraighten , uReflectX , uReflectY ;
2019-10-25 13:05:17 +00:00
GLint uLinearSightRange , uExpStart , uExpDecay ;
2019-11-02 09:40:22 +00:00
GLint uBLevel ;
2020-02-07 18:13:18 +00:00
GLint uPosX , uPosY ;
2020-05-08 19:14:31 +00:00
GLint uWallOffset , uSides ;
2019-10-21 22:37:57 +00:00
2020-03-29 15:35:42 +00:00
raycaster ( string vsh , string fsh ) ;
} ;
# endif
raycaster : : raycaster ( string vsh , string fsh ) : GLprogram ( vsh , fsh ) {
2019-10-21 22:37:57 +00:00
println ( hlog , " assigning " ) ;
uStart = glGetUniformLocation ( _program , " uStart " ) ;
uStartid = glGetUniformLocation ( _program , " uStartid " ) ;
uM = glGetUniformLocation ( _program , " uM " ) ;
uLength = glGetUniformLocation ( _program , " uLength " ) ;
uFovX = glGetUniformLocation ( _program , " uFovX " ) ;
uFovY = glGetUniformLocation ( _program , " uFovY " ) ;
2019-11-16 02:04:01 +00:00
uShift = glGetUniformLocation ( _program , " uShift " ) ;
2019-10-21 22:37:57 +00:00
uIPD = glGetUniformLocation ( _program , " uIPD " ) ;
2019-10-22 10:07:38 +00:00
uWallstart = glGetUniformLocation ( _program , " uWallstart " ) ;
uWallX = glGetUniformLocation ( _program , " uWallX " ) ;
uWallY = glGetUniformLocation ( _program , " uWallY " ) ;
2019-10-22 20:42:48 +00:00
uBinaryWidth = glGetUniformLocation ( _program , " uBinaryWidth " ) ;
2019-11-08 14:01:03 +00:00
uStraighten = glGetUniformLocation ( _program , " uStraighten " ) ;
2019-10-28 16:33:17 +00:00
uPLevel = glGetUniformLocation ( _program , " uPLevel " ) ;
uLP = glGetUniformLocation ( _program , " uLP " ) ;
2019-11-09 11:12:16 +00:00
uReflectX = glGetUniformLocation ( _program , " uReflectX " ) ;
uReflectY = glGetUniformLocation ( _program , " uReflectY " ) ;
2019-10-25 13:05:17 +00:00
uLinearSightRange = glGetUniformLocation ( _program , " uLinearSightRange " ) ;
uExpDecay = glGetUniformLocation ( _program , " uExpDecay " ) ;
uExpStart = glGetUniformLocation ( _program , " uExpStart " ) ;
2019-11-02 09:40:22 +00:00
uBLevel = glGetUniformLocation ( _program , " uBLevel " ) ;
2019-10-21 22:37:57 +00:00
tConnections = glGetUniformLocation ( _program , " tConnections " ) ;
tWallcolor = glGetUniformLocation ( _program , " tWallcolor " ) ;
2019-10-26 08:32:44 +00:00
tTextureMap = glGetUniformLocation ( _program , " tTextureMap " ) ;
2020-02-07 18:13:18 +00:00
2020-05-08 19:14:31 +00:00
uWallOffset = glGetUniformLocation ( _program , " uWallOffset " ) ;
uSides = glGetUniformLocation ( _program , " uSides " ) ;
2020-02-07 18:13:18 +00:00
uPosX = glGetUniformLocation ( _program , " uPosX " ) ;
uPosY = glGetUniformLocation ( _program , " uPosY " ) ;
2019-10-21 22:37:57 +00:00
}
shared_ptr < raycaster > our_raycaster ;
2020-02-23 01:51:27 +00:00
EX void reset_raycaster ( ) { our_raycaster = nullptr ; }
2019-10-25 22:43:15 +00:00
2019-10-28 16:33:17 +00:00
int deg ;
2020-01-15 17:39:35 +00:00
# ifdef GLES_ONLY
void add ( string & tgt , string type , string name , int min_index , int max_index ) {
if ( min_index + 1 = = max_index )
tgt + = " { return " + name + " [ " + its ( min_index ) + " ]; } " ;
else {
int mid = ( min_index + max_index ) / 2 ;
tgt + = " { if(i< " + its ( mid ) + " ) " ;
add ( tgt , type , name , min_index , mid ) ;
tgt + = " else " ;
add ( tgt , type , name , mid , max_index ) ;
tgt + = " } " ;
}
}
string build_getter ( string type , string name , int index ) {
string s = type + " get_ " + name + " (int i) \n " ;
add ( s , type , name , 0 , index ) ;
return s + " \n " ;
}
# define GET(array, index) "get_" array "(" index ")"
# else
# define GET(array, index) array "[" index "]"
# endif
2020-04-11 18:47:14 +00:00
EX hookset < void ( string & , string & ) > hooks_rayshader ;
EX hookset < bool ( shared_ptr < raycaster > ) > hooks_rayset ;
2020-03-29 15:35:42 +00:00
2019-10-21 22:37:57 +00:00
void enable_raycaster ( ) {
2020-05-09 16:30:36 +00:00
using glhr : : to_glsl ;
2020-05-08 19:14:31 +00:00
if ( geometry ! = last_geometry ) {
reset_raycaster ( ) ;
}
deg = 0 ;
2020-05-09 16:32:16 +00:00
auto samples = hybrid : : gen_sample_list ( ) ;
for ( int i = 0 ; i < isize ( samples ) - 1 ; i + + )
deg = max ( deg , samples [ i + 1 ] . first - samples [ i ] . first ) ;
2020-05-08 19:14:31 +00:00
2019-10-26 15:03:10 +00:00
last_geometry = geometry ;
2019-10-21 22:37:57 +00:00
if ( ! our_raycaster ) {
2019-11-08 14:34:51 +00:00
bool asonov = hr : : asonov : : in ( ) ;
2019-11-09 11:12:16 +00:00
bool use_reflect = reflect_val & & ! nil & & ! levellines ;
2020-05-08 19:14:31 +00:00
bool bi = BITRUNCATED ;
2019-10-26 08:55:19 +00:00
2019-10-21 22:37:57 +00:00
string vsh =
2019-11-14 20:21:17 +00:00
" attribute mediump vec4 aPosition; \n "
2020-02-07 18:13:18 +00:00
" uniform mediump float uFovX, uFovY, uPosX, uPosY, uShift; \n "
2019-11-14 20:21:17 +00:00
" varying mediump vec4 at; \n "
2019-10-21 22:37:57 +00:00
" void main() { \n "
2019-11-16 02:04:01 +00:00
" gl_Position = aPosition; at = aPosition; at.x += uShift; \n "
2020-02-07 18:13:18 +00:00
" at[0] += uPosX; at[1] += uPosY; \n "
2019-10-21 22:37:57 +00:00
# if IN_ODS
" at[0] *= PI; at[1] *= PI; \n "
# else
" at[0] *= uFovX; at[1] *= uFovY; \n "
# endif
" } \n " ;
2020-01-15 17:39:35 +00:00
int irays = isize ( cgi . raywall ) ;
string rays = its ( irays ) ;
2019-10-26 22:58:02 +00:00
2019-10-21 22:37:57 +00:00
string fsh =
2019-11-14 20:21:17 +00:00
" varying mediump vec4 at; \n "
" uniform mediump int uLength; \n "
" uniform mediump float uIPD; \n "
" uniform mediump mat4 uStart; \n "
" uniform mediump mat4 uM[84]; \n "
" uniform mediump vec2 uStartid; \n "
" uniform mediump sampler2D tConnections; \n "
" uniform mediump sampler2D tWallcolor; \n "
" uniform mediump sampler2D tTexture; \n "
" uniform mediump sampler2D tTextureMap; \n "
" uniform mediump vec4 uWallX[ " + rays + " ]; \n "
" uniform mediump vec4 uWallY[ " + rays + " ]; \n "
" uniform mediump vec4 uFogColor; \n "
2020-05-08 19:14:31 +00:00
" uniform mediump int uWallstart[ " + its ( isize ( cgi . wallstart ) ) + " ]; \n "
2019-11-14 20:21:17 +00:00
" uniform mediump float uLinearSightRange, uExpStart, uExpDecay; \n " ;
2019-10-22 08:52:17 +00:00
2020-01-15 17:39:35 +00:00
# ifdef GLES_ONLY
fsh + = build_getter ( " mediump vec4 " , " uWallX " , irays ) ;
fsh + = build_getter ( " mediump vec4 " , " uWallY " , irays ) ;
fsh + = build_getter ( " mediump int " , " uWallstart " , deg + 1 ) ;
fsh + = build_getter ( " mediump mat4 " , " uM " , 84 ) ;
# endif
2019-10-28 16:33:17 +00:00
if ( prod ) fsh + =
2019-11-14 20:21:17 +00:00
" uniform mediump float uPLevel; \n "
" uniform mediump mat4 uLP; \n " ;
2019-10-28 16:33:17 +00:00
2020-05-08 19:14:31 +00:00
if ( bi ) fsh + =
" uniform int uWallOffset, uSides; \n " ;
2019-11-02 09:40:22 +00:00
2020-05-08 19:14:31 +00:00
int flat1 = 0 , flat2 = deg ;
if ( prod | | rotspace ) flat2 - = 2 ;
2019-12-14 11:05:01 +00:00
if ( hyperbolic & & bt : : in ( ) ) {
2019-11-14 20:21:17 +00:00
fsh + = " uniform mediump float uBLevel; \n " ;
2019-12-14 11:05:01 +00:00
flat1 = bt : : dirs_outer ( ) ;
flat2 - = bt : : dirs_inner ( ) ;
2019-11-02 09:40:22 +00:00
}
2020-05-08 19:18:47 +00:00
if ( hyperbolic ) fsh + =
2019-10-21 22:37:57 +00:00
2020-01-15 17:39:35 +00:00
" mediump mat4 xpush(float x) { return mat4( "
2019-10-21 22:37:57 +00:00
" cosh(x), 0., 0., sinh(x), \n "
" 0., 1., 0., 0., \n "
" 0., 0., 1., 0., \n "
" sinh(x), 0., 0., cosh(x) "
2019-11-02 09:40:22 +00:00
" );} \n " ;
2020-05-08 19:18:47 +00:00
if ( sphere ) fsh + =
" mediump mat4 xpush(float x) { return mat4( "
" cos(x), 0., 0., sin(x), \n "
" 0., 1., 0., 0., \n "
" 0., 0., 1., 0., \n "
" -sin(x), 0., 0., cos(x) "
" );} \n " ;
2019-11-02 09:40:22 +00:00
if ( IN_ODS ) fsh + =
2019-10-21 22:37:57 +00:00
2020-01-15 17:39:35 +00:00
" mediump mat4 xzspin(float x) { return mat4( "
2019-10-21 22:37:57 +00:00
" cos(x), 0., sin(x), 0., \n "
" 0., 1., 0., 0., \n "
" -sin(x), 0., cos(x), 0., \n "
" 0., 0., 0., 1. "
" );} \n "
2020-01-15 17:39:35 +00:00
" mediump mat4 yzspin(float x) { return mat4( "
2019-10-21 22:37:57 +00:00
" 1., 0., 0., 0., \n "
" 0., cos(x), sin(x), 0., \n "
" 0., -sin(x), cos(x), 0., \n "
" 0., 0., 0., 1. "
2019-10-22 08:52:17 +00:00
" );} \n " ;
2019-10-21 22:37:57 +00:00
2020-05-08 19:18:47 +00:00
if ( bi ) {
fsh + = " int walloffset, sides; \n " ;
}
else {
fsh + = " const int walloffset = 0; \n "
" const int sides = " + its ( centerover - > type ) + " ; \n " ;
}
2019-10-22 10:07:38 +00:00
fsh + =
2020-01-15 17:39:35 +00:00
" mediump vec2 map_texture(mediump vec4 pos, int which) { \n " ;
2019-10-23 16:52:57 +00:00
if ( nil ) fsh + = " if(which == 2 || which == 5) pos.z = 0.; \n " ;
2019-12-14 11:05:01 +00:00
else if ( hyperbolic & & bt : : in ( ) ) fsh + =
2019-11-02 09:40:22 +00:00
" pos = vec4(-log(pos.w-pos.x), pos.y, pos.z, 1); \n "
" pos.yz *= exp(pos.x); \n " ;
2020-05-08 19:18:47 +00:00
else if ( hyperbolic | | sphere ) fsh + =
2019-10-22 10:07:38 +00:00
" pos /= pos.w; \n " ;
2019-10-28 16:33:17 +00:00
else if ( prod ) fsh + =
" pos = vec4(pos.x/pos.z, pos.y/pos.z, pos.w, 0); \n " ;
2019-10-22 10:07:38 +00:00
fsh + =
2020-01-15 17:39:35 +00:00
" int s = " GET ( " uWallstart " , " which " ) " ; \n "
" int e = " GET ( " uWallstart " , " which+1 " ) " ; \n "
2019-11-03 12:36:40 +00:00
" for(int ix=0; ix<16; ix++) { \n "
" int i = s+ix; if(i >= e) break; \n "
2020-01-15 17:39:35 +00:00
" mediump vec2 v = vec2(dot( " GET ( " uWallX " , " i " ) " , pos), dot( " GET ( " uWallY " , " i " ) " , pos)); \n "
2019-10-26 08:32:44 +00:00
" if(v.x >= 0. && v.y >= 0. && v.x + v.y <= 1.) return vec2(v.x+v.y, v.x-v.y); \n "
2019-10-22 10:07:38 +00:00
" } \n "
2019-10-26 08:32:44 +00:00
" return vec2(1, 1); \n "
2019-10-22 10:07:38 +00:00
" } \n " ;
2020-05-08 19:18:47 +00:00
2020-05-09 08:41:15 +00:00
bool stepbased = nonisotropic | | stretch : : in ( ) ;
2019-10-22 10:07:38 +00:00
2019-10-22 08:52:17 +00:00
string fmain = " void main() { \n " ;
2019-10-27 00:23:20 +00:00
if ( use_reflect ) fmain + = " bool depthtoset = true; \n " ;
2019-10-22 08:52:17 +00:00
if ( IN_ODS ) fmain + =
2020-01-15 17:39:35 +00:00
" mediump float lambda = at[0]; \n " // -PI to PI
" mediump float phi; \n "
" mediump float eye; \n "
2019-10-21 22:37:57 +00:00
" if(at.y < 0.) { phi = at.y + PI/2.; eye = uIPD / 2.; } \n " // right
" else { phi = at.y - PI/2.; eye = -uIPD / 2.; } \n "
2020-01-15 17:39:35 +00:00
" mediump mat4 vw = uStart * xzspin(-lambda) * xpush(eye) * yzspin(phi); \n "
" mediump vec4 at0 = vec4(0., 0., 1., 0.); \n " ;
2019-10-22 08:52:17 +00:00
else fmain + =
2020-01-15 17:39:35 +00:00
" mediump mat4 vw = uStart; \n "
" mediump vec4 at0 = at; \n "
2019-10-26 08:54:26 +00:00
" gl_FragColor = vec4(0,0,0,1); \n "
2020-01-15 17:39:35 +00:00
" mediump float left = 1.; \n "
2019-10-22 08:52:17 +00:00
" at0.y = -at.y; \n "
2019-10-21 22:37:57 +00:00
" at0.w = 0.; \n "
2019-10-22 08:52:17 +00:00
" at0.xyz = at0.xyz / length(at0.xyz); \n " ;
2020-01-15 17:39:35 +00:00
if ( hyperbolic ) fsh + = " mediump float len(mediump vec4 x) { return x[3]; } \n " ;
2020-05-08 19:18:47 +00:00
else if ( sphere & & rotspace ) fsh + = " mediump float len(mediump vec4 x) { return 1. + x . x * x . x + x . y * x . y - x . z * x . z - x . w * x . w ; } \ n " ;
2020-05-09 08:41:15 +00:00
else if ( sl2 ) fsh + = " mediump float len(mediump vec4 x) { return 1. + x . x * x . x + x . y * x . y ; } \ n " ;
2020-05-08 19:18:47 +00:00
else if ( sphere ) fsh + = " mediump float len(mediump vec4 x) { return 1. - x [ 3 ] ; } \ n " ;
2020-01-15 17:39:35 +00:00
else fsh + = " mediump float len(mediump vec4 x) { return length(x.xyz); } \n " ;
2019-10-22 08:52:17 +00:00
2020-05-08 19:18:47 +00:00
if ( stepbased ) fmain + =
2020-01-15 17:39:35 +00:00
" const mediump float maxstep = " + fts ( maxstep_current ( ) ) + " ; \n "
" const mediump float minstep = " + fts ( minstep ) + " ; \n "
" mediump float next = maxstep; \n " ;
2019-10-23 16:52:57 +00:00
2019-10-28 16:33:17 +00:00
if ( prod ) {
string sgn = in_h2xe ( ) ? " - " : " + " ;
fmain + =
2020-01-15 17:39:35 +00:00
" mediump vec4 position = vw * vec4(0., 0., 1., 0.); \n "
" mediump vec4 at1 = uLP * at0; \n " ;
2019-11-28 23:50:47 +00:00
if ( in_e2xe ( ) ) fmain + =
2020-01-15 17:39:35 +00:00
" mediump float zpos = log(position.z); \n " ;
2019-11-28 23:50:47 +00:00
else fmain + =
2020-01-15 17:39:35 +00:00
" mediump float zpos = log(position.z*position.z " + sgn + " position.x*position.x " + sgn + " position.y*position.y)/2.; \n " ;
2019-11-28 23:50:47 +00:00
fmain + =
2019-10-28 16:33:17 +00:00
" position *= exp(-zpos); \n "
2020-01-15 17:39:35 +00:00
" mediump float zspeed = at1.z; \n "
" mediump float xspeed = length(at1.xy); \n "
" mediump vec4 tangent = vw * exp(-zpos) * vec4(at1.xy, 0, 0) / xspeed; \n " ;
2019-10-28 16:33:17 +00:00
}
else fmain + =
2020-01-15 17:39:35 +00:00
" mediump vec4 position = vw * vec4(0., 0., 0., 1.); \n "
" mediump vec4 tangent = vw * at0; \n " ;
2020-05-08 19:14:31 +00:00
2020-05-09 08:41:15 +00:00
if ( stretch : : in ( ) ) {
2020-05-08 19:18:47 +00:00
fmain + =
" tangent = s_itranslate(position) * tangent; \n "
2020-05-09 16:30:36 +00:00
" tangent[2] /= " + to_glsl ( stretch : : not_squared ( ) ) + " ; \n "
2020-05-08 19:18:47 +00:00
" tangent = s_translate(position) * tangent; \n " ;
;
}
2020-05-08 19:14:31 +00:00
if ( bi ) fmain + = " walloffset = uWallOffset; sides = uSides; \n " ;
2019-10-28 16:33:17 +00:00
fmain + =
2020-01-15 17:39:35 +00:00
" mediump float go = 0.; \n "
" mediump vec2 cid = uStartid; \n "
2019-10-25 13:18:31 +00:00
" for(int iter=0; iter< " + its ( max_iter_current ( ) ) + " ; iter++) { \n " ;
2019-10-22 20:42:48 +00:00
2019-10-23 16:52:57 +00:00
fmain + =
2020-01-15 17:39:35 +00:00
" mediump float dist = 100.; \n " ;
2019-10-22 20:42:48 +00:00
fmain + =
" int which = -1; \n " ;
2019-11-28 23:50:47 +00:00
if ( in_e2xe ( ) ) fmain + = " tangent.w = position.w = 0.; \n " ;
2019-10-22 20:42:48 +00:00
if ( IN_ODS ) fmain + =
2019-10-21 22:37:57 +00:00
" if(go == 0.) { \n "
2020-01-15 17:39:35 +00:00
" mediump float best = len(position); \n "
2020-05-08 19:14:31 +00:00
" for(int i=0; i<sides; i++) { \n "
2020-01-15 17:39:35 +00:00
" mediump float cand = len(uM[i] * position); \n "
2019-10-21 22:37:57 +00:00
" if(cand < best - .001) { dist = 0.; best = cand; which = i; } \n "
" } \n "
2019-10-22 20:42:48 +00:00
" } \n " ;
2019-10-22 08:52:17 +00:00
2020-05-08 19:18:47 +00:00
if ( ! stepbased ) {
2019-10-22 20:42:48 +00:00
fmain + =
2019-10-28 16:33:17 +00:00
" if(which == -1) { \n " ;
2020-05-08 19:14:31 +00:00
fmain + = " for(int i= " + its ( flat1 ) + " ; i< " + ( prod ? " sides-2 " : its ( flat2 ) ) + " ; i++) { \n " ;
2019-10-22 20:42:48 +00:00
2019-10-28 16:33:17 +00:00
if ( in_h2xe ( ) ) fmain + =
2020-05-08 19:14:31 +00:00
" mediump float v = ((position - uM[walloffset+i] * position)[2] / (uM[walloffset+i] * tangent - tangent)[2]); \n "
2019-10-28 16:33:17 +00:00
" if(v > 1. || v < -1.) continue; \n "
2020-01-15 17:39:35 +00:00
" mediump float d = atanh(v); \n "
" mediump vec4 next_tangent = position * sinh(d) + tangent * cosh(d); \n "
2020-05-08 19:14:31 +00:00
" if(next_tangent[2] < (uM[walloffset+i] * next_tangent)[2]) continue; \n "
2019-10-28 16:33:17 +00:00
" d /= xspeed; \n " ;
else if ( in_s2xe ( ) ) fmain + =
2020-05-08 19:14:31 +00:00
" mediump float v = ((position - uM[walloffset+i] * position)[2] / (uM[walloffset+i] * tangent - tangent)[2]); \n "
2020-01-15 17:39:35 +00:00
" mediump float d = atan(v); \n "
" mediump vec4 next_tangent = tangent * cos(d) - position * sin(d); \n "
2020-05-08 19:14:31 +00:00
" if(next_tangent[2] > (uM[walloffset+i] * next_tangent)[2]) continue; \n "
2019-10-28 16:33:17 +00:00
" d /= xspeed; \n " ;
2019-11-28 23:50:47 +00:00
else if ( in_e2xe ( ) ) fmain + =
2020-05-08 19:14:31 +00:00
" mediump float deno = dot(position, tangent) - dot(uM[walloffset+i]*position, uM[walloffset+i]*tangent); \n "
2019-11-28 23:50:47 +00:00
" if(deno < 1e-6 && deno > -1e-6) continue; \n "
2020-05-08 19:14:31 +00:00
" mediump float d = (dot(uM[walloffset+i]*position, uM[walloffset+i]*position) - dot(position, position)) / 2. / deno; \n "
2019-11-28 23:50:47 +00:00
" if(d < 0.) continue; \n "
2020-01-15 17:39:35 +00:00
" mediump vec4 next_position = position + d * tangent; \n "
2020-05-08 19:14:31 +00:00
" if(dot(next_position, tangent) < dot(uM[walloffset+i]*next_position, uM[walloffset+i]*tangent)) continue; \n "
2019-11-28 23:50:47 +00:00
" d /= xspeed; \n " ;
2019-10-28 16:33:17 +00:00
else if ( hyperbolic ) fmain + =
2020-01-15 17:39:35 +00:00
" mediump float v = ((position - uM[i] * position)[3] / (uM[i] * tangent - tangent)[3]); \n "
2019-10-22 20:42:48 +00:00
" if(v > 1. || v < -1.) continue; \n "
2020-01-15 17:39:35 +00:00
" mediump float d = atanh(v); \n "
" mediump vec4 next_tangent = position * sinh(d) + tangent * cosh(d); \n "
2019-10-22 20:42:48 +00:00
" if(next_tangent[3] < (uM[i] * next_tangent)[3]) continue; \n " ;
2020-05-08 19:18:47 +00:00
else if ( sphere ) fmain + =
" mediump float v = ((position - uM[i] * position)[3] / (uM[i] * tangent - tangent)[3]); \n "
" mediump float d = atan(v); \n "
" mediump vec4 next_tangent = -position * sin(d) + tangent * cos(d); \n "
" if(next_tangent[3] > (uM[i] * next_tangent)[3]) continue; \n " ;
2019-10-22 20:42:48 +00:00
else fmain + =
2020-01-15 17:39:35 +00:00
" mediump float deno = dot(position, tangent) - dot(uM[i]*position, uM[i]*tangent); \n "
2019-10-22 20:42:48 +00:00
" if(deno < 1e-6 && deno > -1e-6) continue; \n "
2020-01-15 17:39:35 +00:00
" mediump float d = (dot(uM[i]*position, uM[i]*position) - dot(position, position)) / 2. / deno; \n "
2019-10-22 20:42:48 +00:00
" if(d < 0.) continue; \n "
2020-01-15 17:39:35 +00:00
" mediump vec4 next_position = position + d * tangent; \n "
2019-10-22 20:42:48 +00:00
" if(dot(next_position, tangent) < dot(uM[i]*next_position, uM[i]*tangent)) continue; \n " ;
fmain + =
" if(d < dist) { dist = d; which = i; } \n "
" } \n " ;
2019-11-02 09:40:22 +00:00
// 20: get to horosphere +uBLevel (take smaller root)
// 21: get to horosphere -uBLevel (take larger root)
2019-12-14 11:05:01 +00:00
if ( hyperbolic & & bt : : in ( ) ) {
2019-11-02 09:40:22 +00:00
fmain + =
" for(int i=20; i<22; i++) { \n "
2020-01-15 17:39:35 +00:00
" mediump float sgn = i == 20 ? -1. : 1.; \n "
" mediump vec4 zpos = xpush(uBLevel*sgn) * position; \n "
" mediump vec4 ztan = xpush(uBLevel*sgn) * tangent; \n "
" mediump float Mp = zpos.w - zpos.x; \n "
" mediump float Mt = ztan.w - ztan.x; \n "
" mediump float a = (Mp*Mp-Mt*Mt); \n "
" mediump float b = Mp/a; \n "
" mediump float c = (1.+Mt*Mt) / a; \n "
2019-11-02 09:40:22 +00:00
" if(b*b < c) continue; \n "
" if(sgn < 0. && Mt > 0.) continue; \n "
2020-01-15 17:39:35 +00:00
" mediump float zsgn = (Mt > 0. ? -sgn : sgn); \n "
" mediump float u = sqrt(b*b-c)*zsgn + b; \n "
" mediump float v = -(Mp*u-1.) / Mt; \n "
" mediump float d = asinh(v); \n "
2019-11-02 09:40:22 +00:00
" if(d < 0. && abs(log(position.w*position.w-position.x*position.x)) < uBLevel) continue; \n "
" if(d < dist) { dist = d; which = i; } \n "
" } \n " ;
}
2019-10-28 16:33:17 +00:00
if ( prod ) fmain + =
2020-05-08 19:14:31 +00:00
" if(zspeed > 0.) { mediump float d = (uPLevel - zpos) / zspeed; if(d < dist) { dist = d; which = sides-1; }} \n "
" if(zspeed < 0.) { mediump float d = (-uPLevel - zpos) / zspeed; if(d < dist) { dist = d; which = sides-2; }} \n " ;
2019-10-28 16:33:17 +00:00
fmain + = " } \n " ;
2019-10-23 16:52:57 +00:00
fmain + =
" if(dist < 0.) { dist = 0.; } \n " ;
fmain + =
2019-10-26 08:54:26 +00:00
" if(which == -1 && dist == 0.) return; " ;
2019-10-22 20:42:48 +00:00
}
2020-05-09 08:41:15 +00:00
2019-10-22 08:52:17 +00:00
// shift d units
2019-10-27 00:23:20 +00:00
if ( use_reflect ) fmain + =
" bool reflect = false; \n " ;
2019-10-28 16:33:17 +00:00
if ( in_h2xe ( ) ) fmain + =
2020-01-15 17:39:35 +00:00
" mediump float ch = cosh(dist*xspeed); mediump float sh = sinh(dist*xspeed); \n "
" mediump vec4 v = position * ch + tangent * sh; \n "
2019-10-28 16:33:17 +00:00
" tangent = tangent * ch + position * sh; \n "
" position = v; \n "
" zpos += dist * zspeed; \n " ;
else if ( in_s2xe ( ) ) fmain + =
2020-01-15 17:39:35 +00:00
" mediump float ch = cos(dist*xspeed); mediump float sh = sin(dist*xspeed); \n "
" mediump vec4 v = position * ch + tangent * sh; \n "
2019-10-28 16:33:17 +00:00
" tangent = tangent * ch - position * sh; \n "
" position = v; \n "
" zpos += dist * zspeed; \n " ;
2019-11-28 23:50:47 +00:00
else if ( in_e2xe ( ) ) fmain + =
" position = position + tangent * dist * xspeed; \n "
" zpos += dist * zspeed; \n " ;
2020-05-08 19:18:47 +00:00
else if ( hyperbolic & & ! stepbased ) fmain + =
2020-01-15 17:39:35 +00:00
" mediump float ch = cosh(dist); mediump float sh = sinh(dist); \n "
" mediump vec4 v = position * ch + tangent * sh; \n "
2019-10-21 22:37:57 +00:00
" tangent = tangent * ch + position * sh; \n "
2019-10-22 08:52:17 +00:00
" position = v; \n " ;
2020-05-08 19:18:47 +00:00
else if ( sphere & & ! stepbased ) fmain + =
" mediump float ch = cos(dist); mediump float sh = sin(dist); \n "
" mediump vec4 v = position * ch + tangent * sh; \n "
" tangent = tangent * ch - position * sh; \n "
" position = v; \n " ;
else if ( stepbased ) {
bool use_christoffel = true ;
2019-10-23 16:52:57 +00:00
2019-11-02 10:51:44 +00:00
if ( sol & & nih ) fsh + =
2020-01-15 17:39:35 +00:00
" mediump vec4 christoffel(mediump vec4 pos, mediump vec4 vel, mediump vec4 tra) { \n "
2019-11-02 10:51:44 +00:00
" return vec4(-(vel.z*tra.x + vel.x*tra.z)*log(2.), (vel.z*tra.y + vel.y * tra.z)*log(3.), vel.x*tra.x * exp(2.*log(2.)*pos.z)*log(2.) - vel.y * tra.y * exp(-2.*log(3.)*pos.z)*log(3.), 0.); \n "
" } \n " ;
else if ( nih ) fsh + =
2020-01-15 17:39:35 +00:00
" mediump vec4 christoffel(mediump vec4 pos, mediump vec4 vel, mediump vec4 tra) { \n "
2019-11-02 10:51:44 +00:00
" return vec4((vel.z*tra.x + vel.x*tra.z)*log(2.), (vel.z*tra.y + vel.y * tra.z)*log(3.), -vel.x*tra.x * exp(-2.*log(2.)*pos.z)*log(2.) - vel.y * tra.y * exp(-2.*log(3.)*pos.z)*log(3.), 0.); \n "
" } \n " ;
else if ( sol ) fsh + =
2020-01-15 17:39:35 +00:00
" mediump vec4 christoffel(mediump vec4 pos, mediump vec4 vel, mediump vec4 tra) { \n "
2019-10-23 16:52:57 +00:00
" return vec4(-vel.z*tra.x - vel.x*tra.z, vel.z*tra.y + vel.y * tra.z, vel.x*tra.x * exp(2.*pos.z) - vel.y * tra.y * exp(-2.*pos.z), 0.); \n "
" } \n " ;
2020-05-08 19:18:47 +00:00
else if ( nil & & false ) fsh + =
2020-01-15 17:39:35 +00:00
" mediump vec4 christoffel(mediump vec4 pos, mediump vec4 vel, mediump vec4 tra) { \n "
" mediump float x = pos.x; \n "
2019-10-23 16:52:57 +00:00
" return vec4(x*vel.y*tra.y - 0.5*dot(vel.yz,tra.zy), -.5*x*dot(vel.yx,tra.xy) + .5 * dot(vel.zx,tra.xz), -.5*(x*x-1.)*dot(vel.yx,tra.xy)+.5*x*dot(vel.zx,tra.xz), 0.); \n "
// " return vec4(0.,0.,0.,0.);\n"
" } \n " ;
2020-05-09 08:41:15 +00:00
else if ( sl2 ) {
fsh + = " mediump mat4 s_translate(vec4 h) { \n "
" return mat4(h.w,h.z,h.y,h.x,-h.z,h.w,-h.x,h.y,h.y,-h.x,h.w,-h.z,h.x,h.y,h.z,h.w); \n "
" } \n " ;
fsh + = " mediump mat4 s_itranslate(vec4 h) { \n "
" h.xyz = -h.xyz; return s_translate(h); \n "
" } \n " ;
fsh + = " mediump vec4 christoffel(mediump vec4 pos, mediump vec4 vel, mediump vec4 tra) { \n "
" vel = s_itranslate(pos) * vel; \n "
" tra = s_itranslate(pos) * tra; \n "
" return s_translate(pos) * vec4( \n "
2020-05-09 16:30:36 +00:00
" (vel.y*tra.z+vel.z*tra.y) * " + to_glsl ( - ( - stretch : : factor - 2 ) ) + " , "
" (vel.x*tra.z+vel.z*tra.x) * " + to_glsl ( - stretch : : factor - 2. ) + " , "
2020-05-09 08:41:15 +00:00
" 0, 0); \n "
" } \n " ;
}
else if ( stretch : : in ( ) ) {
2020-05-08 19:18:47 +00:00
fsh + = " mediump mat4 s_translate(vec4 h) { \n "
" return mat4(h.w,h.z,-h.y,-h.x,-h.z,h.w,h.x,-h.y,h.y,-h.x,h.w,-h.z,h.x,h.y,h.z,h.w); \n "
" } \n " ;
fsh + = " mediump mat4 s_itranslate(vec4 h) { \n "
" h.xyz = -h.xyz; return s_translate(h); \n "
" } \n " ;
fsh + = " mediump vec4 christoffel(mediump vec4 pos, mediump vec4 vel, mediump vec4 tra) { \n "
" vel = s_itranslate(pos) * vel; \n "
" tra = s_itranslate(pos) * tra; \n "
" return s_translate(pos) * vec4( \n "
2020-05-09 16:30:36 +00:00
" (vel.y*tra.z+vel.z*tra.y) * " + to_glsl ( - stretch : : factor ) + " , "
" (vel.x*tra.z+vel.z*tra.x) * " + to_glsl ( stretch : : factor ) + " , "
2020-05-08 19:18:47 +00:00
" 0, 0); \n "
" } \n " ;
}
else use_christoffel = false ;
2020-04-11 22:40:15 +00:00
2020-05-08 19:18:47 +00:00
if ( use_christoffel ) fsh + = " mediump vec4 get_acc(mediump vec4 pos, mediump vec4 vel) { \n "
2020-04-11 22:40:15 +00:00
" return christoffel(pos, vel, vel); \n "
" } \n " ;
2019-10-23 16:52:57 +00:00
2019-12-14 11:28:45 +00:00
if ( sn : : in ( ) & & ! asonov ) fsh + = " uniform mediump float uBinaryWidth; \n " ;
2019-10-23 16:52:57 +00:00
fmain + =
" dist = next < minstep ? 2.*next : next; \n " ;
2019-10-23 21:09:49 +00:00
if ( nil ) fsh + =
2020-01-15 17:39:35 +00:00
" mediump vec4 translate(mediump vec4 a, mediump vec4 b) { \n "
2019-10-23 21:09:49 +00:00
" return vec4(a[0] + b[0], a[1] + b[1], a[2] + b[2] + a[0] * b[1], b[3]); \n "
" } \n "
2020-01-15 17:39:35 +00:00
" mediump vec4 translatev(mediump vec4 a, mediump vec4 t) { \n "
2019-10-23 21:09:49 +00:00
" return vec4(t[0], t[1], t[2] + a[0] * t[1], 0.); \n "
" } \n "
2020-01-15 17:39:35 +00:00
" mediump vec4 itranslate(mediump vec4 a, mediump vec4 b) { \n "
2019-10-23 21:09:49 +00:00
" return vec4(-a[0] + b[0], -a[1] + b[1], -a[2] + b[2] - a[0] * (b[1]-a[1]), b[3]); \n "
" } \n "
2020-01-15 17:39:35 +00:00
" mediump vec4 itranslatev(mediump vec4 a, mediump vec4 t) { \n "
2019-10-23 21:09:49 +00:00
" return vec4(t[0], t[1], t[2] - a[0] * t[1], 0.); \n "
" } \n " ;
if ( nil ) fmain + = " tangent = translate(position, itranslate(position, tangent)); \n " ;
2020-05-08 19:18:47 +00:00
if ( use_christoffel ) fmain + =
2020-04-11 22:40:15 +00:00
" mediump vec4 vel = tangent * dist; \n "
" mediump vec4 acc1 = get_acc(position, vel); \n "
" mediump vec4 acc2 = get_acc(position + vel / 2., vel + acc1/2.); \n "
" mediump vec4 acc3 = get_acc(position + vel / 2. + acc1/4., vel + acc2/2.); \n "
" mediump vec4 acc4 = get_acc(position + vel + acc2/2., vel + acc3/2.); \n "
" mediump vec4 nposition = position + vel + (acc1+acc2+acc3)/6.; \n " ;
2020-05-08 19:18:47 +00:00
2020-05-09 08:41:15 +00:00
if ( sl2 ) fmain + =
" nposition = nposition / sqrt(dot(position.zw, position.zw) - dot(nposition.xy, nposition.xy)); \n " ;
else if ( stretch : : in ( ) ) fmain + =
2020-05-08 19:18:47 +00:00
" nposition = nposition / sqrt(dot(nposition, nposition)); \n " ;
2020-04-11 22:40:15 +00:00
2019-10-23 21:09:49 +00:00
if ( nil ) {
fmain + =
2020-01-15 17:39:35 +00:00
" mediump vec4 xp, xt; \n "
" mediump vec4 back = itranslatev(position, tangent); \n "
2019-10-23 21:09:49 +00:00
" if(back.x == 0. && back.y == 0.) { \n "
" xp = vec4(0., 0., back.z*dist, 1.); \n "
" xt = back; \n "
" } \n "
" else if(abs(back.z) == 0.) { \n "
" xp = vec4(back.x*dist, back.y*dist, back.x*back.y*dist*dist/2., 1.); \n "
" xt = vec4(back.x, back.y, dist*back.x*back.y, 0.); \n "
" } \n "
" else if(abs(back.z) < 1e-1) { \n "
2020-01-15 17:39:35 +00:00
// we use the midpoint method here, because the formulas below cause glitches due to mediump float precision
" mediump vec4 acc = christoffel(vec4(0,0,0,1), back, back); \n "
" mediump vec4 pos2 = back * dist / 2.; \n "
" mediump vec4 tan2 = back + acc * dist / 2.; \n "
" mediump vec4 acc2 = christoffel(pos2, tan2, tan2); \n "
2019-10-23 21:09:49 +00:00
" xp = vec4(0,0,0,1) + back * dist + acc2 / 2. * dist * dist; \n "
" xt = back + acc * dist; \n "
" } \n "
" else { \n "
2020-01-15 17:39:35 +00:00
" mediump float alpha = atan2(back.y, back.x); \n "
" mediump float w = back.z * dist; \n "
" mediump float c = length(back.xy) / back.z; \n "
2019-10-23 21:09:49 +00:00
" xp = vec4(2.*c*sin(w/2.) * cos(w/2.+alpha), 2.*c*sin(w/2.)*sin(w/2.+alpha), w*(1.+(c*c/2.)*((1.-sin(w)/w)+(1.-cos(w))/w * sin(w+2.*alpha))), 1.); \n "
" xt = back.z * vec4( "
" c*cos(alpha+w), "
" c*sin(alpha+w), "
" 1. + c*c*2.*sin(w/2.)*sin(alpha+w)*cos(alpha+w/2.), "
" 0.); \n "
" } \n "
2020-01-15 17:39:35 +00:00
" mediump vec4 nposition = translate(position, xp); \n " ;
2019-10-23 21:09:49 +00:00
}
2019-10-23 16:52:57 +00:00
if ( nil ) fmain + =
2020-01-15 17:39:35 +00:00
" mediump float rz = (abs(nposition.x) > abs(nposition.y) ? -nposition.x*nposition.y : 0.) + nposition.z; \n " ;
2019-11-08 14:01:03 +00:00
if ( asonov ) {
2019-11-14 20:21:17 +00:00
fsh + = " uniform mediump mat4 uStraighten; \n " ;
2020-01-15 17:39:35 +00:00
fmain + = " mediump vec4 sp = uStraighten * nposition; \n " ;
2019-11-08 14:01:03 +00:00
}
2020-05-08 19:18:47 +00:00
if ( hyperbolic ) {
fmain + =
" mediump float ch = cosh(dist); mediump float sh = sinh(dist); \n "
" mediump vec4 v = position * ch + tangent * sh; \n "
" mediump vec4 ntangent = tangent * ch + position * sh; \n "
" mediump vec4 nposition = v; \n " ;
}
if ( sphere & & ! use_christoffel ) {
fmain + =
" mediump float ch = cos(dist); mediump float sh = sin(dist); \n "
" mediump vec4 v = position * ch + tangent * sh; \n "
" mediump vec4 ntangent = tangent * ch - position * sh; \n "
" mediump vec4 nposition = v; \n " ;
}
2020-05-09 08:41:15 +00:00
bool reg = hyperbolic | | sphere | | euclid | | sl2 ;
2019-10-23 16:52:57 +00:00
2020-05-08 19:18:47 +00:00
if ( reg ) {
fsh + = " mediump float len_h(vec4 h) { return 1. - h[3]; } \n " ;
string s = rotspace ? " -2 " : " " ;
fmain + =
" mediump float best = len(nposition); \n "
" for(int i=0; i<sides " + s + " ; i++) { \n "
" mediump float cand = len(uM[walloffset+i] * nposition); \n "
" if(cand < best) { best = cand; which = i; } \n "
" } \n " ;
if ( rotspace ) fmain + =
" if(which == -1) { \n "
" best = len_h(nposition); \n "
" mediump float cand1 = len_h(uM[walloffset+sides-2]*nposition); \n "
" if(cand1 < best) { best = cand1; which = sides-2; } \n "
" mediump float cand2 = len_h(uM[walloffset+sides-1]*nposition); \n "
" if(cand2 < best) { best = cand2; which = sides-1; } \n "
" } \n " ;
}
2019-10-23 16:52:57 +00:00
fmain + =
" if(next >= minstep) { \n " ;
2020-05-08 19:18:47 +00:00
if ( reg ) fmain + = " if(which != -1) { \n " ;
else if ( asonov ) fmain + =
2019-11-08 14:01:03 +00:00
" if(abs(sp.x) > 1. || abs(sp.y) > 1. || abs(sp.z) > 1.) { \n " ;
else if ( nih ) fmain + =
2019-11-02 10:51:44 +00:00
" if(abs(nposition.x) > uBinaryWidth || abs(nposition.y) > uBinaryWidth || abs(nposition.z) > .5) { \n " ;
else if ( sol ) fmain + =
2019-10-23 16:52:57 +00:00
" if(abs(nposition.x) > uBinaryWidth || abs(nposition.y) > uBinaryWidth || abs(nposition.z) > log(2.)/2.) { \n " ;
else fmain + =
" if(abs(nposition.x) > .5 || abs(nposition.y) > .5 || abs(rz) > .5) { \n " ;
fmain + =
" next = dist / 2.; continue; \n "
" } \n "
" if(next < maxstep) next = next / 2.; \n "
" } \n "
" else { \n " ;
2019-12-14 11:28:45 +00:00
if ( sn : : in ( ) ) {
2019-11-08 14:01:03 +00:00
if ( asonov ) fmain + =
" if(sp.x > 1.) which = 4; \n "
" if(sp.y > 1.) which = 5; \n "
" if(sp.x <-1.) which = 10; \n "
" if(sp.y <-1.) which = 11; \n "
" if(sp.z > 1.) { \n "
2020-01-15 17:39:35 +00:00
" mediump float best = 999.; \n "
2019-11-08 14:01:03 +00:00
" for(int i=0; i<4; i++) { \n "
2020-01-15 17:39:35 +00:00
" mediump float cand = len(uStraighten * uM[i] * position); \n "
2019-11-08 14:01:03 +00:00
" if(cand < best) { best = cand; which = i;} \n "
" } \n "
" } \n "
" if(sp.z < -1.) { \n "
2020-01-15 17:39:35 +00:00
" mediump float best = 999.; \n "
2019-11-08 14:01:03 +00:00
" for(int i=6; i<10; i++) { \n "
2020-01-15 17:39:35 +00:00
" mediump float cand = len(uStraighten * uM[i] * position); \n "
2019-11-08 14:01:03 +00:00
" if(cand < best) { best = cand; which = i;} \n "
" } \n "
" } \n " ;
else if ( sol & & ! nih ) fmain + =
2019-10-23 16:52:57 +00:00
" if(nposition.x > uBinaryWidth) which = 0; \n "
" if(nposition.x <-uBinaryWidth) which = 4; \n "
" if(nposition.y > uBinaryWidth) which = 1; \n "
2019-11-02 10:51:44 +00:00
" if(nposition.y <-uBinaryWidth) which = 5; \n " ;
if ( nih ) fmain + =
" if(nposition.x > uBinaryWidth) which = 0; \n "
" if(nposition.x <-uBinaryWidth) which = 2; \n "
" if(nposition.y > uBinaryWidth) which = 1; \n "
" if(nposition.y <-uBinaryWidth) which = 3; \n " ;
if ( sol & & nih ) fmain + =
" if(nposition.z > .5) which = nposition.x > 0. ? 5 : 4; \n "
" if(nposition.z <-.5) which = nposition.y > uBinaryWidth/3. ? 8 : nposition.y < -uBinaryWidth/3. ? 6 : 7; \n " ;
if ( nih & & ! sol ) fmain + =
" if(nposition.z > .5) which = 4; \n "
" if(nposition.z < -.5) which = (nposition.y > uBinaryWidth/3. ? 9 : nposition.y < -uBinaryWidth/3. ? 5 : 7) + (nposition.x>0.?1:0); \n " ;
2019-11-08 14:01:03 +00:00
if ( sol & & ! nih & & ! asonov ) fmain + =
2019-10-23 16:52:57 +00:00
" if(nposition.z > log(2.)/2.) which = nposition.x > 0. ? 3 : 2; \n "
" if(nposition.z <-log(2.)/2.) which = nposition.y > 0. ? 7 : 6; \n " ;
2019-11-02 10:51:44 +00:00
}
2020-05-08 19:18:47 +00:00
else if ( nil ) fmain + =
2019-10-23 16:52:57 +00:00
" if(nposition.x > .5) which = 3; \n "
" if(nposition.x <-.5) which = 0; \n "
" if(nposition.y > .5) which = 4; \n "
" if(nposition.y <-.5) which = 1; \n "
" if(rz > .5) which = 5; \n "
" if(rz <-.5) which = 2; \n " ;
fmain + =
" next = maxstep; \n "
" } \n " ;
fmain + =
2019-10-23 21:09:49 +00:00
" position = nposition; \n " ;
2020-05-08 19:18:47 +00:00
if ( use_christoffel ) fmain + =
2020-04-11 22:40:15 +00:00
" tangent = tangent + (acc1+2.*acc2+2.*acc3+acc4)/(6.*dist); \n " ;
2020-05-08 19:18:47 +00:00
else if ( nil ) fmain + =
" tangent = translatev(position, xt); \n " ;
else fmain + =
" tangent = ntangent; \n " ;
2020-05-09 08:41:15 +00:00
if ( stretch : : in ( ) | | sl2 ) {
2020-05-08 19:18:47 +00:00
fmain + =
" tangent = s_itranslate(position) * tangent; \n "
" tangent[3] = 0.; \n "
2020-05-09 16:30:36 +00:00
" float nvelsquared = dot(tangent.xy, tangent.xy) + " + to_glsl ( stretch : : squared ( ) ) + " * tangent.z * tangent.z; \n "
2020-05-08 19:18:47 +00:00
" tangent /= sqrt(nvelsquared); \n "
" tangent = s_translate(position) * tangent; \n " ;
}
2019-10-22 20:42:48 +00:00
}
2019-10-22 08:52:17 +00:00
else fmain + =
" position = position + tangent * dist; \n " ;
2019-11-08 13:59:44 +00:00
# if CAP_FIX_RAYCAST
if ( hyperbolic ) fmain + =
" position /= sqrt(position.w*position.w - dot(position.xyz, position.xyz)); \n "
" tangent -= dot(vec4(-position.xyz, position.w), tangent) * position; \n "
" tangent /= sqrt(dot(tangent.xyz, tangent.xyz) - tangent.w*tangent.w); \n " ;
# endif
2019-10-22 20:42:48 +00:00
2019-12-14 11:05:01 +00:00
if ( hyperbolic & & bt : : in ( ) ) {
2019-11-02 09:40:22 +00:00
fmain + =
" if(which == 20) { \n "
2020-01-15 17:39:35 +00:00
" mediump float best = 999.; \n "
2019-11-02 09:40:22 +00:00
" for(int i= " + its ( flat2 ) + " ; i< " + its ( S7 ) + " ; i++) { \n "
2020-01-15 17:39:35 +00:00
" mediump float cand = len(uM[i] * position); \n "
2019-11-02 09:40:22 +00:00
" if(cand < best) { best = cand; which = i; } \n "
" } \n "
" } \n "
" if(which == 21) { \n "
2020-01-15 17:39:35 +00:00
" mediump float best = 999.; \n "
2019-11-02 09:40:22 +00:00
" for(int i=0; i< " + its ( flat1 ) + " ; i++) { \n "
2020-01-15 17:39:35 +00:00
" mediump float cand = len(uM[i] * position); \n "
2019-11-02 09:40:22 +00:00
" if(cand < best) { best = cand; which = i; } \n "
" } \n "
// "gl_FragColor = vec4(.5 + .5 * sin((go+dist)*100.), 1, float(which)/3., 1); return;\n"
" } \n " ;
}
2019-10-23 16:52:57 +00:00
2019-11-02 09:40:22 +00:00
fmain + = " go = go + dist; \n " ;
2019-10-22 20:42:48 +00:00
fmain + = " if(which == -1) continue; \n " ;
2019-11-02 09:40:22 +00:00
2019-10-28 16:33:17 +00:00
if ( prod ) fmain + = " position.w = -zpos; \n " ;
2019-10-22 08:52:17 +00:00
// apply wall color
fmain + =
2020-01-15 17:39:35 +00:00
" mediump vec2 u = cid + vec2(float(which) / float(uLength), 0); \n "
" mediump vec4 col = texture2D(tWallcolor, u); \n "
2019-11-03 12:36:06 +00:00
" if(col[3] > 0.0) { \n " ;
2019-11-08 13:59:19 +00:00
if ( hard_limit < NO_LIMIT )
2020-05-09 16:30:36 +00:00
fmain + = " if(go > " + to_glsl ( hard_limit ) + " ) { gl_FragDepth = 1.; return; } \n " ;
2019-11-03 12:36:06 +00:00
if ( ! ( levellines & & disable_texture ) ) fmain + =
2020-05-08 19:14:31 +00:00
" mediump vec2 inface = map_texture(position, which+walloffset); \n "
2020-01-15 17:39:35 +00:00
" mediump vec3 tmap = texture2D(tTextureMap, u).rgb; \n "
2019-10-26 08:54:26 +00:00
" if(tmap.z == 0.) col.xyz *= min(1., (1.-inface.x)/ tmap.x); \n "
2019-10-26 08:32:44 +00:00
" else { \n "
2020-01-15 17:39:35 +00:00
" mediump vec2 inface2 = tmap.xy + tmap.z * inface; \n "
2019-10-26 08:32:44 +00:00
" col.xyz *= texture2D(tTexture, inface2).rgb; \n "
2019-11-03 12:36:06 +00:00
" } \n " ;
fmain + =
2020-01-15 17:39:35 +00:00
" mediump float d = max(1. - go / uLinearSightRange, uExpStart * exp(-go / uExpDecay)); \n "
2019-10-26 13:33:57 +00:00
" col.xyz = col.xyz * d + uFogColor.xyz * (1.-d); \n " ;
2019-10-23 16:52:57 +00:00
if ( nil ) fmain + =
2019-10-26 08:32:44 +00:00
" if(abs(abs(position.x)-abs(position.y)) < .005) col.xyz /= 2.; \n " ;
2019-10-23 16:52:57 +00:00
2019-10-26 08:55:19 +00:00
if ( use_reflect ) fmain + =
" if(col.w == 1.) { \n "
2020-05-09 16:30:36 +00:00
" col.w = " + to_glsl ( 1 - reflect_val ) + " ; \n "
2019-10-26 08:55:19 +00:00
" reflect = true; \n "
" } \n " ;
2019-10-26 12:11:44 +00:00
ld vnear = glhr : : vnear_default ;
ld vfar = glhr : : vfar_default ;
2019-10-23 16:52:57 +00:00
fmain + =
2019-10-27 00:23:20 +00:00
" gl_FragColor.xyz += left * col.xyz * col.w; \n " ;
if ( use_reflect ) fmain + =
" if(reflect && depthtoset) { \n " ;
else fmain + =
2019-10-26 12:11:44 +00:00
" if(col.w == 1.) { \n " ;
if ( hyperbolic ) fmain + =
2020-01-15 17:39:35 +00:00
" mediump float z = at0.z * sinh(go); \n "
" mediump float w = 1.; \n " ;
2019-10-26 12:11:44 +00:00
else fmain + =
2020-01-15 17:39:35 +00:00
" mediump float z = at0.z * go; \n "
" mediump float w = 1.; \n " ;
2019-10-27 00:23:20 +00:00
2019-11-03 12:36:06 +00:00
if ( levellines ) {
if ( hyperbolic )
fmain + = " gl_FragColor.xyz *= 0.5 + 0.5 * cos(z/cosh(go) * uLevelLines * 2. * PI); \n " ;
else
fmain + = " gl_FragColor.xyz *= 0.5 + 0.5 * cos(z * uLevelLines * 2. * PI); \n " ;
2019-11-14 20:21:17 +00:00
fsh + = " uniform mediump float uLevelLines; \n " ;
2019-11-03 12:36:06 +00:00
}
2020-01-15 17:39:35 +00:00
# ifndef GLES_ONLY
2019-10-26 12:11:44 +00:00
fmain + =
2020-05-09 16:30:36 +00:00
" gl_FragDepth = ( " + to_glsl ( - vnear + vfar ) + " +w* " + to_glsl ( 2 * vnear * vfar ) + " /z)/ " + to_glsl ( vnear - vfar ) + " ; \n "
2019-10-27 00:23:20 +00:00
" gl_FragDepth = (gl_FragDepth + 1.) / 2.; \n " ;
2020-01-15 17:39:35 +00:00
# endif
2019-10-27 00:23:20 +00:00
if ( ! use_reflect ) fmain + =
" return; \n " ;
else fmain + =
" depthtoset = false; \n " ;
fmain + =
2019-10-26 12:11:44 +00:00
" } \n "
2019-10-26 08:54:26 +00:00
" left *= (1. - col.w); \n "
2019-10-22 08:52:17 +00:00
" } \n " ;
2019-10-27 00:23:20 +00:00
if ( use_reflect ) {
2020-05-08 19:14:31 +00:00
if ( prod ) fmain + = " if(reflect && which >= " + its ( deg - 2 ) + " ) { zspeed = -zspeed; continue; } \n " ;
2019-12-14 11:05:01 +00:00
if ( hyperbolic & & bt : : in ( ) ) fmain + =
2019-11-02 09:40:22 +00:00
" if(reflect && (which < " + its ( flat1 ) + " || which >= " + its ( flat2 ) + " )) { \n "
2020-01-15 17:39:35 +00:00
" mediump float x = -log(position.w - position.x); \n "
" mediump vec4 xtan = xpush(-x) * tangent; \n "
" mediump float diag = (position.y*position.y+position.z*position.z)/2.; \n "
" mediump vec4 normal = vec4(1.-diag, -position.y, -position.z, -diag); \n "
" mediump float mdot = dot(xtan.xyz, normal.xyz) - xtan.w * normal.w; \n "
2019-11-02 09:40:22 +00:00
" xtan = xtan - normal * mdot * 2.; \n "
" tangent = xpush(x) * xtan; \n "
" continue; \n "
" } \n " ;
2019-11-09 11:12:16 +00:00
if ( asonov ) {
fmain + =
" if(reflect) { \n "
" if(which == 4 || which == 10) tangent = refl(tangent, position.z, uReflectX); \n "
" else if(which == 5 || which == 11) tangent = refl(tangent, position.z, uReflectY); \n "
" else tangent.z = -tangent.z; \n "
" } \n " ;
fsh + =
2019-11-14 20:21:17 +00:00
" uniform mediump vec4 uReflectX, uReflectY; \n "
2020-01-15 17:39:35 +00:00
" mediump vec4 refl(mediump vec4 t, float z, mediump vec4 r) { \n "
2019-11-09 11:12:16 +00:00
" t.x *= exp(z); t.y /= exp(z); \n "
" t -= dot(t, r) * r; \n "
" t.x /= exp(z); t.y *= exp(z); \n "
" return t; \n "
" } \n " ;
}
else if ( sol & & ! nih & & ! asonov ) fmain + =
2019-10-27 00:23:20 +00:00
" if(reflect) { \n "
" if(which == 0 || which == 4) tangent.x = -tangent.x; \n "
" else if(which == 1 || which == 5) tangent.y = -tangent.y; \n "
" else tangent.z = -tangent.z; \n "
" continue; \n "
" } \n " ;
2019-11-02 10:51:44 +00:00
else if ( nih ) fmain + =
" if(reflect) { \n "
" if(which == 0 || which == 2) tangent.x = -tangent.x; \n "
" else if(which == 1 || which == 3) tangent.y = -tangent.y; \n "
" else tangent.z = -tangent.z; \n "
" continue; \n "
" } \n " ;
2019-10-27 00:23:20 +00:00
else fmain + =
" if(reflect) { \n "
2019-10-28 16:33:17 +00:00
" tangent = uM[ " + its ( deg ) + " +which] * tangent; \n "
2019-10-27 00:23:20 +00:00
" continue; \n "
" } \n " ;
}
2019-10-22 08:52:17 +00:00
// next cell
fmain + =
2020-01-15 17:39:35 +00:00
" mediump vec4 connection = texture2D(tConnections, u); \n "
2019-10-28 16:33:17 +00:00
" cid = connection.xy; \n " ;
if ( prod ) fmain + =
2020-05-08 19:14:31 +00:00
" if(which == sides-2) { zpos += uPLevel+uPLevel; } \n "
" if(which == sides-1) { zpos -= uPLevel+uPLevel; } \n " ;
2019-10-28 16:33:17 +00:00
fmain + =
2019-10-25 22:01:12 +00:00
" int mid = int(connection.z * 1024.); \n "
2020-05-08 19:14:31 +00:00
" mediump mat4 m = " GET ( " uM " , " mid " ) " * " GET ( " uM " , " walloffset+which " ) " ; \n "
2020-01-15 17:39:35 +00:00
" position = m * position; \n "
" tangent = m * tangent; \n " ;
2019-10-22 08:52:17 +00:00
2020-05-08 19:14:31 +00:00
if ( bi ) {
fmain + =
" walloffset = int(connection.w * 256.); \n "
" sides = int(connection.w * 4096.) - 16 * walloffset; \n " ;
// fmain += "if(sides != 8) { gl_FragColor = vec4(.5,float(sides)/8.,.5,1); return; }";
}
2019-10-22 08:52:17 +00:00
fmain + =
2019-10-26 12:11:44 +00:00
" } \n "
2019-10-27 00:23:20 +00:00
" gl_FragColor.xyz += left * uFogColor.xyz; \n " ;
2020-01-15 17:39:35 +00:00
# ifndef GLES_ONLY
2019-10-27 00:23:20 +00:00
if ( use_reflect ) fmain + =
" if(depthtoset) gl_FragDepth = 1.; \n " ;
else fmain + =
" gl_FragDepth = 1.; \n " ;
2020-01-15 17:39:35 +00:00
# endif
2019-10-27 00:23:20 +00:00
fmain + =
2019-10-21 22:37:57 +00:00
" } " ;
2019-10-22 08:52:17 +00:00
fsh + = fmain ;
2020-03-29 15:35:42 +00:00
callhooks ( hooks_rayshader , vsh , fsh ) ;
2019-10-21 22:37:57 +00:00
our_raycaster = make_shared < raycaster > ( vsh , fsh ) ;
}
full_enable ( our_raycaster ) ;
}
2019-10-25 22:01:12 +00:00
int length , per_row , rows ;
2019-10-21 22:37:57 +00:00
2019-10-22 08:52:17 +00:00
void bind_array ( vector < array < float , 4 > > & v , GLint t , GLuint & tx , int id ) {
if ( t = = - 1 ) println ( hlog , " bind to nothing " ) ;
2019-10-21 22:37:57 +00:00
glUniform1i ( t , id ) ;
if ( tx = = 0 ) glGenTextures ( 1 , & tx ) ;
glActiveTexture ( GL_TEXTURE0 + id ) ;
2019-10-25 22:01:12 +00:00
glBindTexture ( GL_TEXTURE_2D , tx ) ;
2019-10-21 22:37:57 +00:00
2019-10-25 22:01:12 +00:00
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_NEAREST ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_NEAREST ) ;
2019-10-21 22:37:57 +00:00
2019-10-26 15:03:29 +00:00
glTexImage2D ( GL_TEXTURE_2D , 0 , 0x8814 /* GL_RGBA32F */ , length , isize ( v ) / length , 0 , GL_RGBA , GL_FLOAT , & v [ 0 ] ) ;
2019-10-21 22:37:57 +00:00
GLERR ( " bind_array " ) ;
}
2019-10-25 22:01:12 +00:00
void uniform2 ( GLint id , array < float , 2 > fl ) {
glUniform2f ( id , fl [ 0 ] , fl [ 1 ] ) ;
2019-10-25 13:05:17 +00:00
}
2019-10-25 22:01:12 +00:00
array < float , 2 > enc ( int i , int a ) {
array < float , 2 > res ;
2019-10-28 16:33:17 +00:00
res [ 0 ] = ( ( i % per_row ) * deg + a + .5 ) / length ;
2019-10-25 22:01:12 +00:00
res [ 1 ] = ( ( i / per_row ) + .5 ) / rows ;
return res ;
2020-02-23 01:51:27 +00:00
}
2019-10-25 13:18:31 +00:00
2019-12-06 13:14:27 +00:00
color_t color_out_of_range = 0x0F0800FF ;
2019-10-25 22:17:58 +00:00
2019-10-25 12:50:48 +00:00
EX void cast ( ) {
2019-10-21 22:37:57 +00:00
enable_raycaster ( ) ;
2019-10-23 21:10:50 +00:00
2019-10-25 12:50:48 +00:00
if ( comparison_mode )
2019-10-23 21:10:50 +00:00
glColorMask ( GL_TRUE , GL_FALSE , GL_FALSE , GL_TRUE ) ;
2019-10-21 22:37:57 +00:00
auto & o = our_raycaster ;
vector < glvertex > screen = {
glhr : : makevertex ( - 1 , - 1 , 1 ) ,
glhr : : makevertex ( - 1 , + 1 , 1 ) ,
glhr : : makevertex ( + 1 , - 1 , 1 ) ,
glhr : : makevertex ( - 1 , + 1 , 1 ) ,
glhr : : makevertex ( + 1 , - 1 , 1 ) ,
glhr : : makevertex ( + 1 , + 1 , 1 )
} ;
2019-11-16 02:04:01 +00:00
ld d = current_display - > eyewidth ( ) ;
if ( vid . stereo_mode = = sLR ) d = 2 * d - 1 ;
else d = - d ;
glUniform1f ( o - > uShift , - global_projection * d ) ;
2019-10-21 22:37:57 +00:00
auto & cd = current_display ;
2019-11-16 02:04:01 +00:00
cd - > set_viewport ( global_projection ) ;
cd - > set_mask ( global_projection ) ;
glUniform1f ( o - > uFovX , cd - > tanfov / ( vid . stereo_mode = = sLR ? 2 : 1 ) ) ;
2019-10-21 22:37:57 +00:00
glUniform1f ( o - > uFovY , cd - > tanfov * cd - > ysize / cd - > xsize ) ;
2020-03-29 15:35:42 +00:00
glUniform1f ( o - > uPosX , - ( ( cd - > xcenter - cd - > xtop ) * 2. / cd - > xsize - 1 ) ) ;
glUniform1f ( o - > uPosY , - ( ( cd - > ycenter - cd - > ytop ) * 2. / cd - > ysize - 1 ) ) ;
2019-10-21 22:37:57 +00:00
2020-03-29 15:35:42 +00:00
if ( ! callhandlers ( false , hooks_rayset , o ) ) {
2019-10-28 16:33:17 +00:00
2019-10-25 22:01:12 +00:00
length = 4096 ;
2019-10-28 16:33:17 +00:00
per_row = length / deg ;
2019-10-25 22:01:12 +00:00
vector < cell * > lst ;
2019-11-13 23:26:50 +00:00
cell * cs = centerover ;
2019-10-28 16:33:17 +00:00
transmatrix T = cview ( ) ;
2019-11-16 02:04:01 +00:00
if ( global_projection )
T = xpush ( vid . ipd * global_projection / 2 ) * T ;
2019-11-14 16:20:55 +00:00
if ( nonisotropic ) T = NLP * T ;
2019-10-28 16:33:17 +00:00
T = inverse ( T ) ;
2019-11-14 18:33:55 +00:00
virtualRebase ( cs , T ) ;
2019-10-28 16:33:17 +00:00
2019-10-25 22:12:30 +00:00
if ( true ) {
manual_celllister cl ;
2019-10-28 16:33:17 +00:00
cl . add ( cs ) ;
2019-11-02 09:41:42 +00:00
bool optimize = ! isWall3 ( cs ) ;
2019-10-25 22:12:30 +00:00
for ( int i = 0 ; i < isize ( cl . lst ) ; i + + ) {
cell * c = cl . lst [ i ] ;
2019-10-25 22:27:31 +00:00
if ( racing : : on & & i > 0 & & c - > wall = = waBarrier ) continue ;
2019-11-02 09:41:42 +00:00
if ( optimize & & isWall3 ( c ) ) continue ;
2019-10-25 22:12:30 +00:00
forCellCM ( c2 , c ) {
if ( rays_generate ) setdist ( c2 , 7 , c ) ;
cl . add ( c2 ) ;
if ( isize ( cl . lst ) > = max_cells ) goto finish ;
}
}
finish :
lst = cl . lst ;
}
2019-10-21 22:37:57 +00:00
2019-10-25 22:01:12 +00:00
rows = next_p2 ( ( isize ( lst ) + per_row - 1 ) / per_row ) ;
2019-10-22 08:52:17 +00:00
2019-10-21 22:37:57 +00:00
map < cell * , int > ids ;
for ( int i = 0 ; i < isize ( lst ) ; i + + ) ids [ lst [ i ] ] = i ;
glUniform1i ( o - > uLength , length ) ;
2019-11-14 20:21:17 +00:00
GLERR ( " uniform mediump length " ) ;
2019-10-21 22:37:57 +00:00
2019-10-28 16:33:17 +00:00
glUniformMatrix4fv ( o - > uStart , 1 , 0 , glhr : : tmtogl_transpose3 ( T ) . as_array ( ) ) ;
2019-11-14 16:20:55 +00:00
if ( o - > uLP ! = - 1 ) glUniformMatrix4fv ( o - > uLP , 1 , 0 , glhr : : tmtogl_transpose3 ( inverse ( NLP ) ) . as_array ( ) ) ;
2019-11-14 20:21:17 +00:00
GLERR ( " uniform mediump start " ) ;
2019-10-26 12:17:50 +00:00
uniform2 ( o - > uStartid , enc ( ids [ cs ] , 0 ) ) ;
2019-11-14 20:21:17 +00:00
GLERR ( " uniform mediump startid " ) ;
2019-10-21 22:37:57 +00:00
glUniform1f ( o - > uIPD , vid . ipd ) ;
2019-11-14 20:21:17 +00:00
GLERR ( " uniform mediump IPD " ) ;
2020-05-08 19:14:31 +00:00
if ( o - > uWallOffset ! = - 1 ) {
glUniform1i ( o - > uWallOffset , wall_offset ( centerover ) ) ;
glUniform1i ( o - > uSides , centerover - > type ) ;
}
2020-02-07 18:13:18 +00:00
2020-05-09 16:32:16 +00:00
auto sa = hybrid : : gen_sample_list ( ) ;
2020-05-08 19:14:31 +00:00
2020-05-09 16:32:16 +00:00
vector < transmatrix > ms ( sa . back ( ) . first , Id ) ;
for ( auto & p : sa ) {
int id = p . first ;
cell * c = p . second ;
if ( ! c ) continue ;
for ( int j = 0 ; j < c - > type ; j + + )
ms [ id + j ] = hybrid : : ray_iadj ( c , j ) ;
2020-05-08 19:14:31 +00:00
}
2019-10-28 16:33:17 +00:00
2020-05-09 16:32:16 +00:00
// println(hlog, ms);
2019-10-27 00:23:20 +00:00
if ( ! sol & & ! nil & & reflect_val ) {
2020-05-08 19:14:31 +00:00
if ( BITRUNCATED ) exit ( 1 ) ;
for ( int j = 0 ; j < centerover - > type ; j + + ) {
2019-10-27 00:23:20 +00:00
transmatrix T = inverse ( ms [ j ] ) ;
hyperpoint h = tC0 ( T ) ;
ld d = hdist0 ( h ) ;
transmatrix U = rspintox ( h ) * xpush ( d / 2 ) * MirrorX * xpush ( - d / 2 ) * spintox ( h ) ;
ms . push_back ( U ) ;
}
}
2019-10-25 22:01:12 +00:00
vector < array < float , 4 > > connections ( length * rows ) ;
vector < array < float , 4 > > wallcolor ( length * rows ) ;
2019-10-26 08:32:44 +00:00
vector < array < float , 4 > > texturemap ( length * rows ) ;
2019-10-25 22:01:12 +00:00
2019-10-21 22:37:57 +00:00
if ( 1 ) for ( cell * c : lst ) {
int id = ids [ c ] ;
forCellIdEx ( c1 , i , c ) {
2019-10-28 16:33:17 +00:00
int u = ( id / per_row * length ) + ( id % per_row * deg ) + i ;
2019-10-21 22:37:57 +00:00
if ( ! ids . count ( c1 ) ) {
2019-10-26 07:14:38 +00:00
wallcolor [ u ] = glhr : : acolor ( color_out_of_range | 0xFF ) ;
2019-10-26 08:32:44 +00:00
texturemap [ u ] = glhr : : makevertex ( 0.1 , 0 , 0 ) ;
2019-10-21 22:37:57 +00:00
continue ;
}
2019-10-25 22:01:12 +00:00
auto code = enc ( ids [ c1 ] , 0 ) ;
connections [ u ] [ 0 ] = code [ 0 ] ;
connections [ u ] [ 1 ] = code [ 1 ] ;
2019-10-21 22:37:57 +00:00
if ( isWall3 ( c1 ) ) {
2019-10-25 10:44:41 +00:00
celldrawer dd ;
2019-11-25 19:05:52 +00:00
dd . c = c1 ;
2019-10-25 10:44:41 +00:00
dd . setcolors ( ) ;
2019-10-26 08:32:44 +00:00
transmatrix Vf ;
dd . set_land_floor ( Vf ) ;
2019-10-25 10:44:41 +00:00
color_t wcol = darkena ( dd . wcol , 0 , 0xFF ) ;
2019-10-26 07:14:38 +00:00
int dv = get_darkval ( c1 , c - > c . spin ( i ) ) ;
float p = 1 - dv / 16. ;
2019-10-21 22:37:57 +00:00
wallcolor [ u ] = glhr : : acolor ( wcol ) ;
2019-10-26 07:14:38 +00:00
for ( int a : { 0 , 1 , 2 } ) wallcolor [ u ] [ a ] * = p ;
2019-10-26 08:32:44 +00:00
if ( qfi . fshape ) {
texturemap [ u ] = floor_texture_map [ qfi . fshape - > id ] ;
}
else
texturemap [ u ] = glhr : : makevertex ( 0.1 , 0 , 0 ) ;
2019-10-21 22:37:57 +00:00
}
2019-10-26 08:54:26 +00:00
else {
color_t col = transcolor ( c , c1 , winf [ c - > wall ] . color ) | transcolor ( c1 , c , winf [ c1 - > wall ] . color ) ;
if ( col = = 0 )
wallcolor [ u ] = glhr : : acolor ( 0 ) ;
else {
int dv = get_darkval ( c1 , c - > c . spin ( i ) ) ;
float p = 1 - dv / 16. ;
wallcolor [ u ] = glhr : : acolor ( col ) ;
for ( int a : { 0 , 1 , 2 } ) wallcolor [ u ] [ a ] * = p ;
texturemap [ u ] = glhr : : makevertex ( 0.001 , 0 , 0 ) ;
}
}
2019-10-28 16:33:17 +00:00
2020-05-08 19:14:31 +00:00
transmatrix T = currentmap - > iadj ( c , i ) * inverse ( ms [ wall_offset ( c ) + i ] ) ;
2019-10-21 22:37:57 +00:00
for ( int k = 0 ; k < = isize ( ms ) ; k + + ) {
if ( k < isize ( ms ) & & ! eqmatrix ( ms [ k ] , T ) ) continue ;
if ( k = = isize ( ms ) ) ms . push_back ( T ) ;
2019-10-25 22:01:12 +00:00
connections [ u ] [ 2 ] = ( k + .5 ) / 1024. ;
2019-10-21 22:37:57 +00:00
break ;
}
2020-05-08 19:14:31 +00:00
connections [ u ] [ 3 ] = ( wall_offset ( c1 ) / 256. ) + ( c1 - > type + .5 ) / 4096. ;
2019-10-21 22:37:57 +00:00
}
}
2020-05-08 19:14:31 +00:00
if ( prod ) {
2020-05-09 16:32:16 +00:00
for ( auto p : sa ) {
int id = p . first ;
if ( id = = 0 ) continue ;
ms [ id - 2 ] = Id ;
ms [ id - 1 ] = Id ;
2020-05-08 19:14:31 +00:00
}
}
2019-10-22 10:07:38 +00:00
vector < GLint > wallstart ;
for ( auto i : cgi . wallstart ) wallstart . push_back ( i ) ;
glUniform1iv ( o - > uWallstart , isize ( wallstart ) , & wallstart [ 0 ] ) ;
vector < glvertex > wallx , wally ;
for ( auto & m : cgi . raywall ) {
wallx . push_back ( glhr : : pointtogl ( m [ 0 ] ) ) ;
wally . push_back ( glhr : : pointtogl ( m [ 1 ] ) ) ;
}
glUniform4fv ( o - > uWallX , isize ( wallx ) , & wallx [ 0 ] [ 0 ] ) ;
glUniform4fv ( o - > uWallY , isize ( wally ) , & wally [ 0 ] [ 0 ] ) ;
2019-11-03 12:36:06 +00:00
if ( o - > uLevelLines ! = - 1 )
glUniform1f ( o - > uLevelLines , levellines ) ;
2019-10-22 20:42:48 +00:00
if ( o - > uBinaryWidth ! = - 1 )
2019-11-02 10:51:44 +00:00
glUniform1f ( o - > uBinaryWidth , vid . binary_width / 2 * ( nih ? 1 : log ( 2 ) ) ) ;
2019-11-08 14:01:03 +00:00
if ( o - > uStraighten ! = - 1 ) {
2019-11-08 14:35:23 +00:00
glUniformMatrix4fv ( o - > uStraighten , 1 , 0 , glhr : : tmtogl_transpose ( asonov : : straighten ) . as_array ( ) ) ;
2019-11-08 14:01:03 +00:00
}
2019-11-09 11:12:16 +00:00
if ( o - > uReflectX ! = - 1 ) {
auto h = glhr : : pointtogl ( tangent_length ( spin ( 90 * degree ) * asonov : : ty , 2 ) ) ;
glUniform4fv ( o - > uReflectX , 1 , & h [ 0 ] ) ;
h = glhr : : pointtogl ( tangent_length ( spin ( 90 * degree ) * asonov : : tx , 2 ) ) ;
glUniform4fv ( o - > uReflectY , 1 , & h [ 0 ] ) ;
}
2019-10-28 16:33:17 +00:00
if ( o - > uPLevel ! = - 1 )
glUniform1f ( o - > uPLevel , cgi . plevel / 2 ) ;
2019-11-02 09:40:22 +00:00
if ( o - > uBLevel ! = - 1 )
2019-12-14 11:05:01 +00:00
glUniform1f ( o - > uBLevel , log ( bt : : expansion ( ) ) / 2 ) ;
2019-10-28 16:33:17 +00:00
2019-10-25 13:05:17 +00:00
glUniform1f ( o - > uLinearSightRange , sightranges [ geometry ] ) ;
glUniform1f ( o - > uExpDecay , exp_decay_current ( ) ) ;
glUniform1f ( o - > uExpStart , exp_start ) ;
2019-10-22 20:42:48 +00:00
2019-10-21 22:37:57 +00:00
vector < glhr : : glmatrix > gms ;
2019-10-28 16:33:17 +00:00
for ( auto & m : ms ) gms . push_back ( glhr : : tmtogl_transpose3 ( m ) ) ;
2019-10-21 22:37:57 +00:00
glUniformMatrix4fv ( o - > uM , isize ( gms ) , 0 , gms [ 0 ] . as_array ( ) ) ;
bind_array ( wallcolor , o - > tWallcolor , txWallcolor , 4 ) ;
bind_array ( connections , o - > tConnections , txConnections , 3 ) ;
2019-10-26 08:32:44 +00:00
bind_array ( texturemap , o - > tTextureMap , txTextureMap , 5 ) ;
2019-10-21 22:37:57 +00:00
2019-10-26 13:33:57 +00:00
auto cols = glhr : : acolor ( darkena ( backcolor , 0 , 0xFF ) ) ;
glUniform4f ( o - > uFogColor , cols [ 0 ] , cols [ 1 ] , cols [ 2 ] , cols [ 3 ] ) ;
2020-03-29 15:35:42 +00:00
}
2019-10-26 13:33:57 +00:00
2019-10-21 22:37:57 +00:00
glVertexAttribPointer ( hr : : aPosition , 4 , GL_FLOAT , GL_FALSE , sizeof ( glvertex ) , & screen [ 0 ] ) ;
2019-10-26 12:11:44 +00:00
if ( ray : : comparison_mode )
glhr : : set_depthtest ( false ) ;
else {
glhr : : set_depthtest ( true ) ;
glhr : : set_depthwrite ( true ) ;
}
2019-10-21 22:37:57 +00:00
glBlendFunc ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA ) ;
2019-10-26 08:32:44 +00:00
glActiveTexture ( GL_TEXTURE0 + 0 ) ;
glBindTexture ( GL_TEXTURE_2D , floor_textures - > renderedTexture ) ;
2019-10-21 22:37:57 +00:00
glDrawArrays ( GL_TRIANGLES , 0 , 6 ) ;
GLERR ( " finish " ) ;
}
2019-10-25 12:50:48 +00:00
EX void configure ( ) {
cmode = sm : : SIDE | sm : : MAYDARK ;
gamescreen ( 0 ) ;
dialog : : init ( XLAT ( " raycasting configuration " ) ) ;
dialog : : addBoolItem ( XLAT ( " available in current geometry " ) , available ( ) , 0 ) ;
dialog : : addBoolItem ( XLAT ( " use raycasting? " ) , want_use = = 2 ? true : in_use , ' u ' ) ;
if ( want_use = = 1 ) dialog : : lastItem ( ) . value = XLAT ( " SMART " ) ;
dialog : : add_action ( [ ] {
want_use + + ; want_use % = 3 ;
} ) ;
dialog : : addBoolItem_action ( XLAT ( " comparison mode " ) , comparison_mode , ' c ' ) ;
2019-10-25 13:05:17 +00:00
dialog : : addSelItem ( XLAT ( " exponential range " ) , fts ( exp_decay_current ( ) ) , ' r ' ) ;
dialog : : add_action ( [ & ] {
2019-11-08 14:00:09 +00:00
dialog : : editNumber ( exp_decay_current ( ) , 0 , 40 , 0.25 , 5 , XLAT ( " exponential range " ) ,
2019-10-25 13:05:17 +00:00
XLAT ( " brightness formula: max(1-d/sightrange, s*exp(-d/r)) " )
) ;
} ) ;
dialog : : addSelItem ( XLAT ( " exponential start " ) , fts ( exp_start ) , ' s ' ) ;
dialog : : add_action ( [ & ] {
dialog : : editNumber ( exp_start , 0 , 1 , 0.1 , 1 , XLAT ( " exponential start " ) ,
XLAT ( " brightness formula: max(1-d/sightrange, s*exp(-d/r)) \n " )
) ;
} ) ;
2019-11-08 13:59:19 +00:00
if ( hard_limit < NO_LIMIT )
dialog : : addSelItem ( XLAT ( " hard limit " ) , fts ( hard_limit ) , ' H ' ) ;
else
dialog : : addBoolItem ( XLAT ( " hard limit " ) , false , ' H ' ) ;
dialog : : add_action ( [ & ] {
if ( hard_limit > = NO_LIMIT ) hard_limit = 10 ;
dialog : : editNumber ( hard_limit , 0 , 100 , 1 , 10 , XLAT ( " hard limit " ) , " " ) ;
dialog : : reaction = reset_raycaster ;
dialog : : extra_options = [ ] {
dialog : : addItem ( " no limit " , ' N ' ) ;
dialog : : add_action ( [ ] { hard_limit = NO_LIMIT ; reset_raycaster ( ) ; } ) ;
} ;
} ) ;
2019-10-27 00:23:20 +00:00
if ( ! nil ) {
dialog : : addSelItem ( XLAT ( " reflective walls " ) , fts ( reflect_val ) , ' R ' ) ;
dialog : : add_action ( [ & ] {
dialog : : editNumber ( reflect_val , 0 , 1 , 0.1 , 0 , XLAT ( " reflective walls " ) , " " ) ;
dialog : : reaction = reset_raycaster ;
} ) ;
}
2019-10-25 13:18:31 +00:00
2020-05-09 08:41:15 +00:00
if ( nonisotropic | | stretch : : in ( ) ) {
2019-10-25 22:43:15 +00:00
dialog : : addSelItem ( XLAT ( " max step " ) , fts ( maxstep_current ( ) ) , ' x ' ) ;
dialog : : add_action ( [ ] {
2020-04-11 22:40:15 +00:00
dialog : : editNumber ( maxstep_current ( ) , 1e-6 , 1 , 0.1 , sol ? 0.05 : 0.1 , XLAT ( " max step " ) , " affects the precision of solving the geodesic equation in Solv " ) ;
2019-10-25 22:43:15 +00:00
dialog : : scaleLog ( ) ;
dialog : : bound_low ( 1e-9 ) ;
dialog : : reaction = reset_raycaster ;
} ) ;
dialog : : addSelItem ( XLAT ( " min step " ) , fts ( minstep ) , ' n ' ) ;
dialog : : add_action ( [ ] {
2019-10-26 13:42:38 +00:00
dialog : : editNumber ( minstep , 1e-6 , 1 , 0.1 , 0.001 , XLAT ( " min step " ) , " how precisely should we find out when do cross the cell boundary " ) ;
2019-10-25 22:43:15 +00:00
dialog : : scaleLog ( ) ;
dialog : : bound_low ( 1e-9 ) ;
dialog : : reaction = reset_raycaster ;
} ) ;
}
2019-10-25 13:18:31 +00:00
dialog : : addSelItem ( XLAT ( " iterations " ) , its ( max_iter_current ( ) ) , ' s ' ) ;
dialog : : add_action ( [ & ] {
2019-10-26 13:42:38 +00:00
dialog : : editNumber ( max_iter_current ( ) , 0 , 600 , 1 , 60 , XLAT ( " iterations " ) , " in H3/H2xE/E3 this is the number of cell boundaries; in nonisotropic, the number of simulation steps " ) ;
2019-10-25 22:43:15 +00:00
dialog : : reaction = reset_raycaster ;
2019-10-25 13:18:31 +00:00
} ) ;
2019-10-25 22:12:30 +00:00
dialog : : addSelItem ( XLAT ( " max cells " ) , its ( max_cells ) , ' s ' ) ;
dialog : : add_action ( [ & ] {
dialog : : editNumber ( max_cells , 16 , 131072 , 0.1 , 4096 , XLAT ( " max cells " ) , " " ) ;
dialog : : scaleLog ( ) ;
dialog : : extra_options = [ ] {
dialog : : addBoolItem_action ( " generate " , rays_generate , ' G ' ) ;
2019-10-25 22:17:58 +00:00
dialog : : addColorItem ( XLAT ( " out-of-range color " ) , color_out_of_range , ' X ' ) ;
dialog : : add_action ( [ ] {
dialog : : openColorDialog ( color_out_of_range ) ;
dialog : : dialogflags | = sm : : SIDE ;
} ) ;
2019-10-25 22:12:30 +00:00
} ;
} ) ;
2019-11-03 12:36:06 +00:00
edit_levellines ( ' L ' ) ;
2019-10-25 13:05:17 +00:00
2019-10-25 12:50:48 +00:00
dialog : : addBack ( ) ;
dialog : : display ( ) ;
}
2019-10-25 22:12:40 +00:00
# if CAP_COMMANDLINE
int readArgs ( ) {
using namespace arg ;
if ( 0 ) ;
else if ( argis ( " -ray-do " ) ) {
PHASEFROM ( 2 ) ;
want_use = 2 ;
}
else if ( argis ( " -ray-dont " ) ) {
PHASEFROM ( 2 ) ;
want_use = 0 ;
}
else if ( argis ( " -ray-smart " ) ) {
PHASEFROM ( 2 ) ;
want_use = 1 ;
}
2020-05-08 19:20:33 +00:00
else if ( argis ( " -ray-range " ) ) {
PHASEFROM ( 2 ) ;
shift_arg_formula ( exp_start ) ;
shift_arg_formula ( exp_decay_current ( ) ) ;
want_use = 1 ;
}
2019-11-02 21:31:50 +00:00
else if ( argis ( " -ray-out " ) ) {
PHASEFROM ( 2 ) ; shift ( ) ; color_out_of_range = arghex ( ) ;
}
2019-10-28 16:33:54 +00:00
else if ( argis ( " -ray-comp " ) ) {
PHASEFROM ( 2 ) ;
comparison_mode = true ;
}
2020-05-08 19:20:33 +00:00
else if ( argis ( " -ray-sol " ) ) {
PHASEFROM ( 2 ) ;
shift ( ) ; max_iter_sol = argi ( ) ;
shift_arg_formula ( maxstep_sol , reset_raycaster ) ;
reset_raycaster ( ) ;
}
2019-10-25 22:12:40 +00:00
else if ( argis ( " -ray-cells " ) ) {
PHASEFROM ( 2 ) ; shift ( ) ;
rays_generate = true ;
max_cells = argi ( ) ;
}
2019-10-27 00:23:20 +00:00
else if ( argis ( " -ray-reflect " ) ) {
PHASEFROM ( 2 ) ;
shift_arg_formula ( reflect_val ) ;
}
2019-10-25 22:12:40 +00:00
else if ( argis ( " -ray-cells-no " ) ) {
PHASEFROM ( 2 ) ; shift ( ) ;
rays_generate = false ;
max_cells = argi ( ) ;
}
else return 1 ;
return 0 ;
}
2019-11-23 22:51:52 +00:00
auto hook = addHook ( hooks_args , 100 , readArgs ) ;
# endif
# if CAP_CONFIG
2019-11-16 00:40:14 +00:00
void addconfig ( ) {
addparam ( exp_start , " ray_exp_start " ) ;
addparam ( exp_decay_exp , " ray_exp_decay_exp " ) ;
addparam ( maxstep_sol , " ray_maxstep_sol " ) ;
addparam ( maxstep_nil , " ray_maxstep_nil " ) ;
addparam ( minstep , " ray_minstep " ) ;
addparam ( reflect_val , " ray_reflect_val " ) ;
addparam ( hard_limit , " ray_hard_limit " ) ;
addsaver ( want_use , " ray_want_use " ) ;
addsaver ( exp_decay_poly , " ray_exp_decay_poly " ) ;
addsaver ( max_iter_iso , " ray_max_iter_iso " ) ;
addsaver ( max_iter_sol , " ray_max_iter_sol " ) ;
addsaver ( max_cells , " ray_max_cells " ) ;
addsaver ( rays_generate , " ray_generate " ) ;
}
2019-11-23 22:51:52 +00:00
auto hookc = addHook ( hooks_configfile , 100 , addconfig ) ;
2019-10-25 22:12:40 +00:00
# endif
2019-11-23 22:51:52 +00:00
2019-11-03 13:19:11 +00:00
# endif
2019-10-25 22:12:40 +00:00
2020-03-21 09:49:07 +00:00
# if !CAP_RAY
2019-11-03 13:19:11 +00:00
EX always_false in_use ;
EX always_false comparison_mode ;
EX void reset_raycaster ( ) { }
EX void cast ( ) { }
# endif
2019-10-25 12:50:48 +00:00
EX }
2019-10-21 22:37:57 +00:00
}