2019-08-10 11:43:24 +00:00
// Hyperbolic Rogue -- basic geometry
// Copyright (C) 2011-2019 Zeno Rogue, see 'hyper.cpp' for details
2016-08-26 09:58:03 +00:00
2019-08-10 11:43:24 +00:00
/** \file geometry.cpp
* \ brief Calculation of basic , and less basic , constants in each geometry
*/
2015-08-08 13:57:52 +00:00
2019-09-05 07:15:40 +00:00
# include "hyper.h"
2018-06-10 23:58:31 +00:00
namespace hr {
2019-08-09 23:56:00 +00:00
# if HDR
struct usershapelayer {
vector < hyperpoint > list ;
bool sym ;
int rots ;
color_t color ;
hyperpoint shift , spin ;
ld zlevel ;
int texture_offset ;
PPR prio ;
} ;
2019-08-10 08:57:14 +00:00
extern int usershape_changes ;
2019-08-09 23:56:00 +00:00
static const int USERLAYERS = 32 ;
struct usershape { usershapelayer d [ USERLAYERS ] ; } ;
struct hpcshape {
int s , e ;
PPR prio ;
int flags ;
hyperpoint intester ;
struct basic_textureinfo * tinf ;
int texture_offset ;
int shs , she ;
void clear ( ) { s = e = shs = she = texture_offset = 0 ; prio = PPR : : ZERO ; tinf = NULL ; flags = 0 ; }
} ;
2019-08-10 08:57:14 +00:00
# define SIDE_SLEV 0
# define SIDE_WTS3 3
# define SIDE_WALL 4
# define SIDE_LAKE 5
# define SIDE_LTOB 6
# define SIDE_BTOI 7
# define SIDE_SKY 8
# define SIDE_HIGH 9
# define SIDE_HIGH2 10
2020-02-26 00:15:30 +00:00
# define SIDE_ASHA 11
# define SIDE_BSHA 12
# define SIDEPARS 13
2019-08-10 08:57:14 +00:00
2022-02-01 16:08:54 +00:00
/** GOLDBERG_BITS controls the size of tables for Goldberg. see gp::check_limits */
2021-07-18 16:32:50 +00:00
# ifndef GOLDBERG_BITS
# define GOLDBERG_BITS 5
# endif
static const int GOLDBERG_LIMIT = ( 1 < < GOLDBERG_BITS ) ;
static const int GOLDBERG_MASK = ( GOLDBERG_LIMIT - 1 ) ;
2020-05-25 00:27:04 +00:00
# ifndef BADMODEL
2019-08-10 08:57:14 +00:00
# define BADMODEL 0
2020-05-25 00:27:04 +00:00
# endif
2019-08-10 08:57:14 +00:00
2020-05-25 00:27:04 +00:00
# ifndef WINGS
2019-08-09 23:56:00 +00:00
static const int WINGS = ( BADMODEL ? 1 : 4 ) ;
2020-05-25 00:27:04 +00:00
# endif
2019-08-09 23:56:00 +00:00
typedef array < hpcshape , WINGS + 1 > hpcshape_animated ;
extern vector < hpcshape > shPlainWall3D , shWireframe3D , shWall3D , shMiniWall3D ;
struct floorshape {
bool is_plain ;
int shapeid ;
int id ;
int pstrength ; // pattern strength in 3D
int fstrength ; // frame strength in 3D
PPR prio ;
2020-01-18 15:03:32 +00:00
vector < hpcshape > b , shadow , side [ SIDEPARS ] , levels [ SIDEPARS ] , cone [ 2 ] ;
vector < vector < hpcshape > > gpside [ SIDEPARS ] ;
2019-08-09 23:56:00 +00:00
floorshape ( ) { prio = PPR : : FLOOR ; pstrength = fstrength = 10 ; }
} ;
struct plain_floorshape : floorshape {
ld rad0 , rad1 ;
void configure ( ld r0 , ld r1 ) { rad0 = r0 ; rad1 = r1 ; }
} ;
2019-08-10 08:57:14 +00:00
extern vector < ld > equal_weights ;
2019-08-09 23:56:00 +00:00
// noftype: 0 (shapeid2 is heptagonal or just use shapeid1), 1 (shapeid2 is pure heptagonal), 2 (shapeid2 is Euclidean), 3 (shapeid2 is hexagonal)
struct escher_floorshape : floorshape {
int shapeid0 , shapeid1 , noftype , shapeid2 ;
ld scale ;
} ;
2019-08-10 11:43:24 +00:00
2019-08-20 10:57:05 +00:00
struct basic_textureinfo {
int texture_id ;
vector < glvertex > tvertices ;
2020-09-11 09:08:27 +00:00
vector < glvertex > colors ;
2019-08-20 10:57:05 +00:00
} ;
2021-03-31 08:30:03 +00:00
/** additional modules can add extra shapes etc. */
struct gi_extension {
2021-03-31 11:35:28 +00:00
virtual ~ gi_extension ( ) { }
2021-03-31 08:30:03 +00:00
} ;
2021-12-11 22:28:05 +00:00
struct expansion_analyzer ;
2021-07-12 09:07:22 +00:00
/** both for 'heptagon' 3D cells and subdivided 3D cells */
2021-07-06 23:48:20 +00:00
struct subcellshape {
2021-07-12 10:23:34 +00:00
/** \brief raw coordinates of vertices of all faces */
2021-07-06 23:48:20 +00:00
vector < vector < hyperpoint > > faces ;
2021-07-12 10:23:34 +00:00
/** \brief raw coordinates of all vertices in one vector */
2021-07-06 23:48:20 +00:00
vector < hyperpoint > vertices_only ;
2021-07-12 10:23:34 +00:00
/** \brief cooked coordinates of vertices of all faces, computed from faces as: from_cellcenter * final_coords(v) */
vector < vector < hyperpoint > > faces_local ;
/** \brief cooked coordinates of all vertices in one vector */
2021-07-06 23:48:20 +00:00
vector < hyperpoint > vertices_only_local ;
2021-07-12 10:23:34 +00:00
/** \brief weights -- used to generate wall shapes in some geometries, empty otherwise */
vector < vector < double > > weights ;
/** the center of every raw face */
2021-07-06 23:48:20 +00:00
vector < hyperpoint > face_centers ;
2021-07-11 13:07:40 +00:00
vector < vector < char > > dirdist ;
2021-07-06 23:48:20 +00:00
hyperpoint cellcenter ;
transmatrix to_cellcenter ;
transmatrix from_cellcenter ;
2021-07-12 09:07:22 +00:00
/** \brief for adjacent directions a,b, next_dir[a][b] is the next direction adjacent to a, in (counter?)clockwise order from b */
2021-07-12 18:54:16 +00:00
vector < vector < char > > next_dir ;
/** useful in product geometries */
vector < hyperpoint > walltester ;
2021-07-12 09:07:22 +00:00
/** compute all the properties based on `faces`, for the main heptagon cellshape */
void compute_hept ( ) ;
/** compute all the properties based on `faces`, for subcells */
void compute_sub ( ) ;
/** common part of compute_hept and compute_sub */
void compute_common ( ) ;
2021-07-06 23:48:20 +00:00
} ;
2022-07-14 09:28:24 +00:00
enum class ePipeEnd { sharp , ball } ;
2019-08-10 11:43:24 +00:00
/** basic geometry parameters */
2019-08-09 23:56:00 +00:00
struct geometry_information {
2019-08-10 11:43:24 +00:00
/** distance from heptagon center to another heptagon center */
ld tessf ;
/** distance from heptagon center to adjacent cell center (either hcrossf or tessf) */
ld crossf ;
/** distance from heptagon center to small heptagon vertex */
ld hexf ;
/** distance from heptagon center to big heptagon vertex */
ld hcrossf ;
/** distance between adjacent hexagon vertices */
ld hexhexdist ;
/** distance between hexagon vertex and hexagon center */
ld hexvdist ;
/** distance between heptagon vertex and hexagon center (either hcrossf or something else) */
ld hepvdist ;
2019-08-09 23:56:00 +00:00
2019-08-10 11:43:24 +00:00
/** distance from heptagon center to heptagon vertex (either hexf or hcrossf) */
ld rhexf ;
2019-08-09 23:56:00 +00:00
2021-09-17 11:50:24 +00:00
/** edge length */
ld edgelen ;
2020-04-05 08:53:34 +00:00
/** basic parameters for 3D geometries */
map < int , int > close_distances ;
2020-05-26 22:54:15 +00:00
int loop , face , schmid ;
2020-04-05 08:53:34 +00:00
2020-05-26 22:54:15 +00:00
transmatrix spins [ 32 ] , adjmoves [ 32 ] ;
2021-07-06 23:48:20 +00:00
2021-07-12 09:07:22 +00:00
unique_ptr < struct subcellshape > heptshape ;
2021-07-06 23:48:20 +00:00
vector < struct subcellshape > subshapes ;
2020-04-05 08:53:34 +00:00
ld adjcheck ;
ld strafedist ;
2020-05-27 23:50:00 +00:00
ld ultra_mirror_dist , ultra_material_part , ultra_mirror_part ;
vector < transmatrix > ultra_mirrors ;
2020-04-05 08:53:34 +00:00
int xp_order , r_order , rx_order ;
transmatrix full_X , full_R , full_P ;
/** for 2D geometries */
2020-01-18 15:03:32 +00:00
vector < transmatrix > heptmove , hexmove , invhexmove ;
2019-08-09 23:56:00 +00:00
int base_distlimit ;
2019-08-10 11:43:24 +00:00
/** size of the Sword (from Orb of the Sword), used in the shmup mode */
2019-08-09 23:56:00 +00:00
ld sword_size ;
2019-08-10 11:43:24 +00:00
/** scale factor for the graphics of most things*/
ld scalefactor ;
ld orbsize , floorrad0 , floorrad1 , zhexf ;
2019-08-09 23:56:00 +00:00
ld corner_bonus ;
ld hexshift ;
ld asteroid_size [ 8 ] ;
ld wormscale ;
ld tentacle_length ;
2019-08-18 19:16:27 +00:00
/** level in product geometries */
ld plevel ;
2019-08-26 12:16:55 +00:00
/** level for a z-step */
int single_step ;
2020-07-24 00:30:50 +00:00
/** the number of levels in PSL */
int psl_steps ;
2020-04-06 09:24:11 +00:00
/** for binary tilings */
transmatrix direct_tmatrix [ 14 ] ;
transmatrix inverse_tmatrix [ 14 ] ;
/** a bitmask for hr::bt::use_direct_for */
int use_direct ;
2019-08-09 23:56:00 +00:00
2019-08-10 11:43:24 +00:00
/** various parameters related to the 3D view */
2019-08-09 23:56:00 +00:00
ld INFDEEP , BOTTOM , HELLSPIKE , LAKE , WALL , FLOOR , STUFF ,
SLEV [ 4 ] , FLATEYE ,
LEG0 , LEG1 , LEG , LEG3 , GROIN , GROIN1 , GHOST ,
BODY , BODY1 , BODY2 , BODY3 ,
NECK1 , NECK , NECK3 , HEAD , HEAD1 , HEAD2 , HEAD3 ,
2020-02-26 00:15:30 +00:00
ALEG0 , ALEG , ABODY , AHEAD , BIRD , LOWSKY , SKY , HIGH , HIGH2 ,
SHALLOW ;
2019-08-09 23:56:00 +00:00
ld human_height , slev ;
ld eyelevel_familiar , eyelevel_human , eyelevel_dog ;
# if CAP_SHAPES
hpcshape
shSemiFloorSide [ SIDEPARS ] ,
shBFloor [ 2 ] ,
shWave [ 8 ] [ 2 ] ,
shCircleFloor ,
shBarrel ,
shWall [ 2 ] , shMineMark [ 2 ] , shBigMineMark [ 2 ] , shFan ,
shZebra [ 5 ] ,
shSwitchDisk ,
shTower [ 11 ] ,
shEmeraldFloor [ 6 ] ,
shSemiFeatherFloor [ 2 ] ,
shSemiFloor [ 2 ] , shSemiBFloor [ 2 ] , shSemiFloorShadow ,
shMercuryBridge [ 2 ] ,
shTriheptaSpecial [ 14 ] ,
shCross , shGiantStar [ 2 ] , shLake , shMirror ,
shHalfFloor [ 6 ] , shHalfMirror [ 3 ] ,
2022-09-15 01:11:52 +00:00
shGem [ 2 ] , shStar , shFlash , shDisk , shHalfDisk , shDiskT , shDiskS , shDiskM , shDiskSq , shEccentricDisk , shDiskSegment ,
2022-09-15 04:32:36 +00:00
shHeptagon , shHeptagram ,
2019-08-09 23:56:00 +00:00
shTinyBird , shTinyShark ,
2022-08-29 02:06:01 +00:00
shEgg , shSmallEgg ,
2022-08-27 19:43:22 +00:00
shRing , shSpikedRing , shTargetRing , shSawRing , shGearRing , shPeaceRing ,
2022-09-17 22:00:54 +00:00
shHeptaRing , shSpearRing , shLoveRing , shFrogRing ,
2022-08-27 19:43:22 +00:00
shPowerGearRing , shProtectiveRing , shTerraRing , shMoveRing ,
shReserved4 , shMoonDisk ,
2022-08-28 17:25:42 +00:00
shDaisy , shSnowflake , shTriangle , shNecro , shStatue , shKey , shWindArrow ,
2019-08-09 23:56:00 +00:00
shGun ,
2022-08-29 02:41:16 +00:00
shFigurine , shTreat , shSmallTreat ,
2019-08-09 23:56:00 +00:00
shElementalShard ,
// shBranch,
2019-08-19 08:33:07 +00:00
shIBranch , shTentacle , shTentacleX , shILeaf [ 3 ] ,
2019-08-09 23:56:00 +00:00
shMovestar ,
shWolf , shYeti , shDemon , shGDemon , shEagle , shGargoyleWings , shGargoyleBody ,
shFoxTail1 , shFoxTail2 ,
shDogBody , shDogHead , shDogFrontLeg , shDogRearLeg , shDogFrontPaw , shDogRearPaw ,
shDogTorso ,
shHawk ,
shCatBody , shCatLegs , shCatHead , shFamiliarHead , shFamiliarEye ,
shWolf1 , shWolf2 , shWolf3 ,
shRatEye1 , shRatEye2 , shRatEye3 ,
shDogStripes ,
2022-08-26 22:21:00 +00:00
shPBody , shSmallPBody , shPSword , shSmallPSword , shPKnife ,
2019-08-09 23:56:00 +00:00
shFerocityM , shFerocityF ,
shHumanFoot , shHumanLeg , shHumanGroin , shHumanNeck , shSkeletalFoot , shYetiFoot ,
2022-08-27 04:58:48 +00:00
shMagicSword , shSmallSword , shMagicShovel , shSeaTentacle , shKrakenHead , shKrakenEye , shKrakenEye2 ,
2019-08-09 23:56:00 +00:00
shArrow ,
shPHead , shPFace , shGolemhead , shHood , shArmor ,
shAztecHead , shAztecCap ,
shSabre , shTurban1 , shTurban2 , shVikingHelmet , shRaiderHelmet , shRaiderArmor , shRaiderBody , shRaiderShirt ,
shWestHat1 , shWestHat2 , shGunInHand ,
shKnightArmor , shKnightCloak , shWightCloak ,
2022-08-29 03:05:03 +00:00
shGhost , shEyes , shSlime , shJelly , shJoint , shWormHead , shSmallWormHead , shTentHead , shShark , shWormSegment , shSmallWormSegment , shWormTail , shSmallWormTail ,
shSlimeEyes , shDragonEyes , shSmallDragonEyes , shWormEyes , shSmallWormEyes , shGhostEyes ,
shMiniGhost , shSmallEyes , shMiniEyes ,
2022-08-27 12:43:24 +00:00
shHedgehogBlade , shSmallHedgehogBlade , shHedgehogBladePlayer ,
2019-08-09 23:56:00 +00:00
shWolfBody , shWolfHead , shWolfLegs , shWolfEyes ,
shWolfFrontLeg , shWolfRearLeg , shWolfFrontPaw , shWolfRearPaw ,
shFemaleBody , shFemaleHair , shFemaleDress , shWitchDress ,
shWitchHair , shBeautyHair , shFlowerHair , shFlowerHand , shSuspenders , shTrophy ,
shBugBody , shBugArmor , shBugLeg , shBugAntenna ,
2022-08-29 04:09:24 +00:00
shPickAxe , shSmallPickAxe , shPike , shFlailBall , shSmallFlailBall , shFlailTrunk , shSmallFlailTrunk , shFlailChain , shHammerHead , shSmallHammerHead ,
2019-08-09 23:56:00 +00:00
shBook , shBookCover , shGrail ,
shBoatOuter , shBoatInner , shCompass1 , shCompass2 , shCompass3 ,
shKnife , shTongue , shFlailMissile , shTrapArrow ,
2022-09-15 23:02:27 +00:00
shPirateHook , shSmallPirateHook , shPirateHood , shEyepatch , shPirateX ,
2019-08-09 23:56:00 +00:00
// shScratch,
2021-03-21 10:31:07 +00:00
shHeptaMarker , shSnowball , shHugeDisk , shSun , shNightStar , shEuclideanSky ,
2019-08-09 23:56:00 +00:00
shSkeletonBody , shSkull , shSkullEyes , shFatBody , shWaterElemental ,
shPalaceGate , shFishTail ,
shMouse , shMouseLegs , shMouseEyes ,
shPrincessDress , shPrinceDress ,
shWizardCape1 , shWizardCape2 ,
shBigCarpet1 , shBigCarpet2 , shBigCarpet3 ,
2022-08-26 19:34:04 +00:00
shGoatHead , shRose , shRoseItem , shSmallRose , shThorns ,
2019-08-09 23:56:00 +00:00
shRatHead , shRatTail , shRatEyes , shRatCape1 , shRatCape2 ,
shWizardHat1 , shWizardHat2 ,
shTortoise [ 13 ] [ 6 ] ,
2022-08-29 03:05:03 +00:00
shDragonLegs , shDragonTail , shDragonHead , shSmallDragonHead , shDragonSegment , shDragonNostril , shSmallDragonNostril ,
2019-08-09 23:56:00 +00:00
shDragonWings ,
shSolidBranch , shWeakBranch , shBead0 , shBead1 ,
shBatWings , shBatBody , shBatMouth , shBatFang , shBatEye ,
shParticle [ 16 ] , shAsteroid [ 8 ] ,
shReptile [ 5 ] [ 4 ] ,
shReptileBody , shReptileHead , shReptileFrontFoot , shReptileRearFoot ,
shReptileFrontLeg , shReptileRearLeg , shReptileTail , shReptileEye ,
shTrylobite , shTrylobiteHead , shTrylobiteBody ,
shTrylobiteFrontLeg , shTrylobiteRearLeg , shTrylobiteFrontClaw , shTrylobiteRearClaw ,
shBullBody , shBullHead , shBullHorn , shBullRearHoof , shBullFrontHoof ,
2022-08-28 01:21:53 +00:00
shSmallBullHead , shSmallBullHorn ,
shTinyBullHead , shTinyBullHorn , shTinyBullBody ,
2019-08-09 23:56:00 +00:00
shButterflyBody , shButterflyWing , shGadflyBody , shGadflyWing , shGadflyEye ,
shTerraArmor1 , shTerraArmor2 , shTerraArmor3 , shTerraHead , shTerraFace ,
shJiangShi , shJiangShiDress , shJiangShiCap1 , shJiangShiCap2 ,
2020-02-26 00:19:49 +00:00
shPikeBody , shPikeEye ,
2019-08-09 23:56:00 +00:00
shAsymmetric ,
shPBodyOnly , shPBodyArm , shPBodyHand , shPHeadOnly ,
2022-08-29 23:14:59 +00:00
shDodeca , shSmallerDodeca ,
2022-09-16 19:13:20 +00:00
shLightningBolt , shHumanoid , shHalfHumanoid , shHourglass ,
2022-09-17 20:39:11 +00:00
shShield , shSmallFan , shTreeIcon , shLeafIcon ;
2019-08-09 23:56:00 +00:00
2022-08-26 22:21:00 +00:00
hpcshape shFrogRearFoot , shFrogFrontFoot , shFrogRearLeg , shFrogFrontLeg , shFrogRearLeg2 , shFrogBody , shFrogEye , shFrogStripe , shFrogJumpFoot , shFrogJumpLeg , shSmallFrogRearFoot , shSmallFrogFrontFoot , shSmallFrogRearLeg , shSmallFrogFrontLeg , shSmallFrogRearLeg2 , shSmallFrogBody ;
2020-02-26 00:19:49 +00:00
2019-08-09 23:56:00 +00:00
hpcshape_animated
shAnimatedEagle , shAnimatedTinyEagle , shAnimatedGadfly , shAnimatedHawk , shAnimatedButterfly ,
2021-05-09 00:25:05 +00:00
shAnimatedGargoyle , shAnimatedGargoyle2 , shAnimatedBat , shAnimatedBat2 ;
2021-05-09 00:25:17 +00:00
hpcshape shTinyArrow ;
2021-05-09 00:25:05 +00:00
hpcshape shReserved [ 16 ] ;
int orb_inner_ring ; //< for shDisk* shapes, the number of vertices in the inner ring
int res1 , res2 ;
2019-08-09 23:56:00 +00:00
2020-01-25 23:48:56 +00:00
map < int , hpcshape > shPipe ;
2019-08-09 23:56:00 +00:00
vector < hpcshape > shPlainWall3D , shWireframe3D , shWall3D , shMiniWall3D ;
2019-08-21 05:33:24 +00:00
vector < hyperpoint > walltester ;
2019-10-22 10:07:38 +00:00
vector < int > wallstart ;
vector < transmatrix > raywall ;
2019-08-09 23:56:00 +00:00
vector < struct plain_floorshape * > all_plain_floorshapes ;
vector < struct escher_floorshape * > all_escher_floorshapes ;
plain_floorshape
shFloor ,
shMFloor , shMFloor2 , shMFloor3 , shMFloor4 , shFullFloor ,
shBigTriangle , shTriheptaFloor , shBigHepta ;
escher_floorshape
shStarFloor , shCloudFloor , shCrossFloor , shChargedFloor ,
shSStarFloor , shOverFloor , shTriFloor , shFeatherFloor ,
shBarrowFloor , shNewFloor , shTrollFloor , shButterflyFloor ,
shLavaFloor , shLavaSeabed , shSeabed , shCloudSeabed ,
shCaveSeabed , shPalaceFloor , shDemonFloor , shCaveFloor ,
shDesertFloor , shPowerFloor , shRoseFloor , shSwitchFloor ,
shTurtleFloor , shRedRockFloor [ 3 ] , shDragonFloor ;
ld dlow_table [ SIDEPARS ] , dhi_table [ SIDEPARS ] , dfloor_table [ SIDEPARS ] ;
int prehpc ;
2022-04-25 17:53:36 +00:00
/** list of points in all shapes */
2019-08-09 23:56:00 +00:00
vector < hyperpoint > hpc ;
2022-04-25 17:53:36 +00:00
/** what shape are we currently creating */
hpcshape * last ;
/** is the current shape already started? first = not yet */
2019-08-09 23:56:00 +00:00
bool first ;
2022-04-25 17:53:36 +00:00
/** starting point of the current shape, can be ultraideal */
hyperpoint starting_point ;
/** first ideal point of the current shape */
hyperpoint starting_ideal ;
/** last added point of the current shape, can be ultraideal */
hyperpoint last_point ;
/** last ideal point of the current shape */
hyperpoint last_ideal ;
2019-08-09 23:56:00 +00:00
bool validsidepar [ SIDEPARS ] ;
vector < glvertex > ourshape ;
# endif
hpcshape shFullCross [ 2 ] ;
int SD3 , SD6 , SD7 , S12 , S14 , S21 , S28 , S42 , S36 , S84 ;
2022-11-12 21:38:45 +00:00
ld S_step ;
2019-08-09 23:56:00 +00:00
2020-05-09 16:32:16 +00:00
vector < pair < int , cell * > > walloffsets ;
2019-08-18 18:13:46 +00:00
2019-08-09 23:56:00 +00:00
vector < array < int , 3 > > symmetriesAt ;
2020-01-28 14:15:35 +00:00
struct cellrotation_t {
transmatrix M ;
vector < int > mapping ;
int inverse_id ;
} ;
vector < cellrotation_t > cellrotations ;
2019-10-12 09:22:13 +00:00
2019-08-09 23:56:00 +00:00
# ifndef SCALETUNER
static constexpr
# endif
double bscale7 = 1 , brot7 = 0 , bscale6 = 1 , brot6 = 0 ;
vector < hpcshape * > allshapes ;
transmatrix shadowmulmatrix ;
map < usershapelayer * , hpcshape > ushr ;
void prepare_basics ( ) ;
void prepare_compute3 ( ) ;
void prepare_shapes ( ) ;
void prepare_usershapes ( ) ;
void hpcpush ( hyperpoint h ) ;
2022-04-25 17:53:36 +00:00
void hpc_connect_ideal ( hyperpoint a , hyperpoint b ) ;
2019-08-09 23:56:00 +00:00
void hpcsquare ( hyperpoint h1 , hyperpoint h2 , hyperpoint h3 , hyperpoint h4 ) ;
void chasmifyPoly ( double fac , double fac2 , int k ) ;
void shift ( hpcshape & sh , double dx , double dy , double dz ) ;
void initPolyForGL ( ) ;
void extra_vertices ( ) ;
transmatrix ddi ( int a , ld x ) ;
void drawTentacle ( hpcshape & h , ld rad , ld var , ld divby ) ;
hyperpoint hpxyzsc ( double x , double y , double z ) ;
hyperpoint turtlevertex ( int u , double x , double y , double z ) ;
void bshape ( hpcshape & sh , PPR prio ) ;
void finishshape ( ) ;
void bshape ( hpcshape & sh , PPR prio , double shzoom , int shapeid , double bonus = 0 , flagtype flags = 0 ) ;
void copyshape ( hpcshape & sh , hpcshape & orig , PPR prio ) ;
void zoomShape ( hpcshape & old , hpcshape & newsh , double factor , PPR prio ) ;
void pushShape ( usershapelayer & ds ) ;
void make_sidewalls ( ) ;
void procedural_shapes ( ) ;
void make_wall ( int id , const vector < hyperpoint > vertices , vector < ld > weights = equal_weights ) ;
2019-08-18 18:13:46 +00:00
void reserve_wall3d ( int i ) ;
void compute_cornerbonus ( ) ;
2019-08-09 23:56:00 +00:00
void create_wall3d ( ) ;
void configure_floorshapes ( ) ;
void init_floorshapes ( ) ;
void bshape2 ( hpcshape & sh , PPR prio , int shapeid , struct matrixlist & m ) ;
2019-12-27 22:01:55 +00:00
void bshape_regular ( floorshape & fsh , int id , int sides , ld shift , ld size , cell * model ) ;
2019-08-09 23:56:00 +00:00
void generate_floorshapes_for ( int id , cell * c , int siid , int sidir ) ;
void generate_floorshapes ( ) ;
void make_floor_textures_here ( ) ;
2022-04-22 22:57:04 +00:00
void finish_apeirogon ( hyperpoint center ) ;
2019-08-09 23:56:00 +00:00
vector < hyperpoint > get_shape ( hpcshape sh ) ;
void add_cone ( ld z0 , const vector < hyperpoint > & vh , ld z1 ) ;
void add_prism_sync ( ld z0 , vector < hyperpoint > vh0 , ld z1 , vector < hyperpoint > vh1 ) ;
void add_prism ( ld z0 , vector < hyperpoint > vh0 , ld z1 , vector < hyperpoint > vh1 ) ;
void shift_last ( ld z ) ;
void shift_shape ( hpcshape & sh , ld z ) ;
void shift_shape_orthogonally ( hpcshape & sh , ld z ) ;
void add_texture ( hpcshape & sh ) ;
void make_ha_3d ( hpcshape & sh , bool isarmor , ld scale ) ;
void make_humanoid_3d ( hpcshape & sh ) ;
void addtri ( array < hyperpoint , 3 > hs , int kind ) ;
void make_armor_3d ( hpcshape & sh , int kind = 1 ) ;
void make_foot_3d ( hpcshape & sh ) ;
void make_head_only ( ) ;
void make_head_3d ( hpcshape & sh ) ;
void make_paw_3d ( hpcshape & sh , hpcshape & legsh ) ;
void make_abody_3d ( hpcshape & sh , ld tail ) ;
void make_ahead_3d ( hpcshape & sh ) ;
void make_skeletal ( hpcshape & sh , ld push = 0 ) ;
void make_revolution ( hpcshape & sh , int mx = 180 , ld push = 0 ) ;
void make_revolution_cut ( hpcshape & sh , int each = 180 , ld push = 0 , ld width = 99 ) ;
void clone_shape ( hpcshape & sh , hpcshape & target ) ;
void animate_bird ( hpcshape & orig , hpcshape_animated & animated , ld body ) ;
void slimetriangle ( hyperpoint a , hyperpoint b , hyperpoint c , ld rad , int lev ) ;
void balltriangle ( hyperpoint a , hyperpoint b , hyperpoint c , ld rad , int lev ) ;
void make_ball ( hpcshape & sh , ld rad , int lev ) ;
void make_star ( hpcshape & sh , ld rad ) ;
void make_euclidean_sky ( ) ;
void adjust_eye ( hpcshape & eye , hpcshape head , ld shift_eye , ld shift_head , int q , ld zoom = 1 ) ;
void shift_last_straight ( ld z ) ;
void queueball ( const transmatrix & V , ld rad , color_t col , eItem what ) ;
void make_shadow ( hpcshape & sh ) ;
void make_3d_models ( ) ;
/* Goldberg parameters */
# if CAP_GP
struct gpdata_t {
2021-07-18 16:32:50 +00:00
vector < array < array < array < transmatrix , 6 > , GOLDBERG_LIMIT > , GOLDBERG_LIMIT > > Tf ;
2019-08-09 23:56:00 +00:00
transmatrix corners ;
ld alpha ;
int area ;
2021-07-18 16:32:50 +00:00
int pshid [ 3 ] [ 8 ] [ GOLDBERG_LIMIT ] [ GOLDBERG_LIMIT ] [ 8 ] ;
2020-07-12 18:43:58 +00:00
int nextid ;
2019-08-09 23:56:00 +00:00
} ;
2020-05-04 01:21:14 +00:00
shared_ptr < gpdata_t > gpdata = nullptr ;
2019-08-09 23:56:00 +00:00
# endif
2021-12-11 22:28:05 +00:00
shared_ptr < expansion_analyzer > expansion = nullptr ;
2019-08-09 23:56:00 +00:00
2020-05-04 01:21:14 +00:00
int state = 0 ;
int usershape_state = 0 ;
2019-08-20 10:57:05 +00:00
/** contains the texture point coordinates for 3D models */
basic_textureinfo models_texture ;
2022-08-05 18:06:05 +00:00
geometry_information ( ) { last = NULL ; use_count = 0 ; }
2019-08-09 23:56:00 +00:00
void require_basics ( ) { if ( state & 1 ) return ; state | = 1 ; prepare_basics ( ) ; }
void require_shapes ( ) { if ( state & 2 ) return ; state | = 2 ; prepare_shapes ( ) ; }
void require_usershapes ( ) { if ( usershape_state = = usershape_changes ) return ; usershape_state = usershape_changes ; prepare_usershapes ( ) ; }
int timestamp ;
2020-01-25 23:48:56 +00:00
2022-07-14 09:28:24 +00:00
hpcshape & generate_pipe ( ld length , ld width , ePipeEnd endtype = ePipeEnd : : sharp ) ;
2021-03-31 08:30:03 +00:00
map < string , unique_ptr < gi_extension > > ext ;
2022-08-05 18:06:05 +00:00
/** prevent from being destroyed */
int use_count ;
2019-08-09 23:56:00 +00:00
} ;
# endif
2021-07-12 10:23:34 +00:00
EX subcellshape & get_hsh ( ) {
if ( ! cgi . heptshape ) cgi . heptshape = ( unique_ptr < subcellshape > ) ( new subcellshape ) ;
return * cgi . heptshape ;
}
EX void add_wall ( int i , const vector < hyperpoint > & h ) {
auto & f = get_hsh ( ) . faces ;
if ( isize ( f ) < = i ) f . resize ( i + 1 ) ;
f [ i ] = h ;
}
2019-08-10 11:43:24 +00:00
/** values of hcrossf and hexf for the standard geometry. Since polygons are
* usually drawn in this geometry , the scale in other geometries is usually
* based on comparing these values to the values in the other geometry .
*/
2017-10-27 18:07:58 +00:00
2019-08-24 09:55:45 +00:00
# if HDR
static const ld hcrossf7 = 0.620672 , hexf7 = 0.378077 , tessf7 = 1.090550 , hexhexdist7 = 0.566256 ;
# endif
2015-08-08 13:57:52 +00:00
2019-09-05 10:00:55 +00:00
EX bool scale_used ( ) { return ( shmup : : on & & geometry = = gNormal & & BITRUNCATED ) ? ( cheater | | autocheat ) : true ; }
2019-07-21 21:12:16 +00:00
2021-07-07 16:26:03 +00:00
EX bool is_subcube_based ( eVariation var ) {
2021-07-13 13:12:03 +00:00
return among ( var , eVariation : : subcubes , eVariation : : dual_subcubes , eVariation : : bch , eVariation : : bch_oct ) ;
2021-07-07 16:26:03 +00:00
}
2021-07-08 22:07:35 +00:00
EX bool is_reg3_variation ( eVariation var ) {
return var = = eVariation : : coxeter ;
}
2019-05-26 16:04:02 +00:00
void geometry_information : : prepare_basics ( ) {
2015-08-08 13:57:52 +00:00
2019-05-26 16:04:02 +00:00
DEBBI ( DF_INIT | DF_POLY | DF_GEOM , ( " prepare_basics " ) ) ;
2017-10-27 18:07:58 +00:00
hexshift = 0 ;
2016-08-26 09:58:03 +00:00
2022-11-12 21:38:45 +00:00
ld ALPHA = TAU / S7 ;
2019-12-14 11:18:24 +00:00
2017-10-28 08:04:28 +00:00
ld fmin , fmax ;
2020-05-31 01:30:14 +00:00
ld s3 , beta ;
2021-07-12 10:23:34 +00:00
heptshape = nullptr ;
2017-10-28 08:04:28 +00:00
2022-08-24 23:06:49 +00:00
xp_order = 0 ;
2022-12-08 18:38:06 +00:00
if ( arcm : : in ( ) & & ! mproduct )
2018-08-19 21:06:32 +00:00
ginf [ gArchimedean ] . cclass = gcHyperbolic ;
2020-07-12 18:52:32 +00:00
dynamicval < eVariation > gv ( variation , variation ) ;
bool inv = INVERSE ;
if ( INVERSE ) {
variation = gp : : variation_for ( gp : : param ) ;
println ( hlog , " bitruncated = " , BITRUNCATED ) ;
}
2018-08-17 11:29:00 +00:00
2022-12-08 18:38:06 +00:00
if ( mhybrid ) {
2019-08-18 11:05:47 +00:00
auto t = this ;
2022-12-08 18:38:06 +00:00
ld d = mproduct ? 1 : 2 ;
2019-08-24 12:07:46 +00:00
hybrid : : in_underlying_geometry ( [ & ] {
t - > rhexf = cgi . rhexf / d ;
t - > hexf = cgi . hexf / d ;
t - > crossf = cgi . crossf / d ;
t - > hcrossf = cgi . crossf / d ;
t - > tessf = cgi . tessf / d ;
t - > hexvdist = cgi . hexvdist / d ;
2022-11-12 21:38:45 +00:00
t - > hexhexdist = hdist ( xpush0 ( cgi . hcrossf ) , xspinpush0 ( TAU / S7 , cgi . hcrossf ) ) / d ;
2019-08-18 11:05:47 +00:00
t - > base_distlimit = cgi . base_distlimit - 1 ;
} ) ;
2019-08-24 12:07:46 +00:00
goto hybrid_finish ;
2019-08-18 11:05:47 +00:00
}
2019-08-24 09:55:45 +00:00
2022-12-08 18:38:06 +00:00
if ( embedded_plane ) geom3 : : light_flip ( true ) ;
2019-12-14 11:05:01 +00:00
if ( ( sphere | | hyperbolic ) & & WDIM = = 3 & & ! bt : : in ( ) ) {
2019-02-25 12:17:53 +00:00
rhexf = hexf = 0.378077 ;
crossf = hcrossf = 0.620672 ;
tessf = 1.090550 ;
hexhexdist = 0.566256 ;
goto finish ;
}
2020-05-31 01:30:14 +00:00
s3 = S3 ;
2020-05-31 14:18:44 +00:00
if ( fake : : in ( ) & & ! arcm : : in ( ) ) s3 = fake : : around ;
2020-05-31 01:30:14 +00:00
2022-11-12 21:38:45 +00:00
beta = ( S3 > = OINF & & ! fake : : in ( ) ) ? 0 : TAU / s3 ;
2016-08-26 09:58:03 +00:00
2020-05-31 01:30:14 +00:00
tessf = euclid ? 1 : edge_of_triangle_with_angles ( beta , M_PI / S7 , M_PI / S7 ) ;
2015-08-08 13:57:52 +00:00
2022-11-12 21:38:45 +00:00
if ( elliptic & & S7 = = 4 & & ! fake : : in ( ) ) tessf = 90. _deg ;
2015-08-08 13:57:52 +00:00
2022-11-12 21:38:45 +00:00
hcrossf = euclid ? tessf / 2 / sin ( M_PI / s3 ) : edge_of_triangle_with_angles ( 90. _deg , M_PI / S7 , beta / 2 ) ;
2020-09-11 09:22:26 +00:00
if ( S3 > = OINF ) hcrossf = 10 ;
2019-04-28 10:12:02 +00:00
2018-08-28 15:17:34 +00:00
crossf = BITRUNCATED ? hcrossf : tessf ;
2015-08-08 13:57:52 +00:00
fmin = 0 , fmax = tessf ;
for ( int p = 0 ; p < 100 ; p + + ) {
ld f = ( fmin + fmax ) / 2 ;
2018-08-19 14:28:36 +00:00
hyperpoint H = xpush0 ( f ) ;
2022-11-12 21:38:45 +00:00
hyperpoint H1 = spin ( TAU / S7 ) * H ;
2018-08-19 14:28:36 +00:00
hyperpoint H2 = xpush0 ( tessf - f ) ;
2015-08-08 13:57:52 +00:00
ld v1 = intval ( H , H1 ) , v2 = intval ( H , H2 ) ;
2020-05-31 01:30:14 +00:00
if ( fake : : in ( ) & & WDIM = = 2 ) {
hexvdist = hdist ( xpush0 ( f ) , xspinpush0 ( ALPHA / 2 , hcrossf ) ) ;
v2 = hdist (
2022-11-12 21:38:45 +00:00
spin ( 90. _deg / S3 ) * xpush0 ( hexvdist ) ,
spin ( - 90. _deg / S3 ) * xpush0 ( hexvdist )
2020-05-31 01:30:14 +00:00
) ;
v1 = hdist (
spin ( M_PI / S7 ) * xpush0 ( f ) ,
spin ( - M_PI / S7 ) * xpush0 ( f )
) ;
}
2015-08-08 13:57:52 +00:00
if ( v1 < v2 ) fmin = f ; else fmax = f ;
}
hexf = fmin ;
2018-08-28 15:17:34 +00:00
rhexf = BITRUNCATED ? hexf : hcrossf ;
2022-11-12 21:38:45 +00:00
edgelen = hdist ( xpush0 ( rhexf ) , xspinpush0 ( TAU / S7 , rhexf ) ) ;
2017-10-29 16:12:40 +00:00
2019-11-27 00:01:20 +00:00
if ( BITRUNCATED & & ! ( S7 & 1 ) )
2017-10-28 08:04:28 +00:00
hexshift = ALPHA / 2 + ALPHA * ( ( S7 - 1 ) / 2 ) + M_PI ;
2019-11-27 00:01:20 +00:00
2017-10-28 08:04:28 +00:00
finish :
2017-10-28 23:57:34 +00:00
2018-08-19 14:28:36 +00:00
hexvdist = hdist ( xpush0 ( hexf ) , xspinpush0 ( ALPHA / 2 , hcrossf ) ) ;
2017-10-29 16:12:40 +00:00
2020-05-31 01:30:14 +00:00
hexhexdist = fake : : in ( ) ?
2 * hdist0 ( mid ( xspinpush0 ( M_PI / S6 , hexvdist ) , xspinpush0 ( - M_PI / S6 , hexvdist ) ) )
2022-11-12 21:38:45 +00:00
: hdist ( xpush0 ( crossf ) , xspinpush0 ( TAU / S7 , crossf ) ) ;
2020-05-31 01:30:14 +00:00
2019-05-12 23:57:40 +00:00
DEBB ( DF_GEOM | DF_POLY ,
( format ( " S7=%d S6=%d hexf = " LDF " hcross = " LDF " tessf = " LDF " hexshift = " LDF " hexhex = " LDF " hexv = " LDF " \n " , S7 , S6 , hexf , hcrossf , tessf , hexshift ,
hexhexdist , hexvdist ) ) ) ;
2017-10-29 16:12:40 +00:00
2018-08-28 15:17:34 +00:00
base_distlimit = ginf [ geometry ] . distlimit [ ! BITRUNCATED ] ;
2018-08-28 17:05:57 +00:00
2019-02-17 17:28:20 +00:00
# if CAP_GP
2020-07-12 18:52:32 +00:00
gp : : compute_geometry ( inv ) ;
2019-02-17 17:28:20 +00:00
# endif
# if CAP_IRR
2018-07-16 18:05:23 +00:00
irr : : compute_geometry ( ) ;
2019-02-17 17:28:20 +00:00
# endif
# if CAP_ARCM
2019-12-14 10:42:16 +00:00
if ( arcm : : in ( ) ) {
2020-05-31 14:18:44 +00:00
auto & ac = arcm : : current_or_fake ( ) ;
if ( fake : : in ( ) ) ac = arcm : : current ;
ac . compute_geometry ( ) ;
crossf = hcrossf7 * ac . scale ( ) ;
hexvdist = ac . scale ( ) * .5 ;
rhexf = ac . scale ( ) * .5 ;
2021-09-17 11:50:24 +00:00
edgelen = ac . edgelength ;
2018-08-28 17:05:57 +00:00
}
2019-02-17 17:28:20 +00:00
# endif
2019-02-28 14:03:17 +00:00
# if CAP_BT
2019-12-14 11:05:01 +00:00
if ( bt : : in ( ) ) hexvdist = rhexf = 1 , tessf = 1 , scalefactor = 1 , crossf = hcrossf7 ;
2019-12-14 11:12:24 +00:00
if ( geometry = = gHoroRec | | kite : : in ( ) | | sol | | nil | | nih ) hexvdist = rhexf = .5 , tessf = .5 , scalefactor = .5 , crossf = hcrossf7 / 2 ;
2019-12-14 11:05:01 +00:00
if ( bt : : in ( ) ) scalefactor * = min < ld > ( vid . binary_width , 1 ) , crossf * = min < ld > ( vid . binary_width , 1 ) ;
2019-02-28 14:03:17 +00:00
# endif
# if CAP_BT && MAXMDIM >= 4
2019-12-14 11:05:01 +00:00
if ( bt : : in ( ) ) bt : : build_tmatrix ( ) ;
2019-02-28 14:03:17 +00:00
# endif
2020-04-10 08:52:24 +00:00
# if MAXMDIM >= 4
2020-04-05 08:53:34 +00:00
if ( reg3 : : in ( ) ) reg3 : : generate ( ) ;
2020-05-15 09:40:57 +00:00
if ( euc : : in ( 3 ) ) euc : : generate ( ) ;
2021-07-12 10:23:34 +00:00
# if CAP_SOLV
else if ( sn : : in ( ) ) sn : : create_faces ( ) ;
# endif
# if CAP_BT
else if ( bt : : in ( ) ) bt : : create_faces ( ) ;
# endif
else if ( nil ) nilv : : create_faces ( ) ;
2020-04-10 08:52:24 +00:00
# endif
2019-02-28 02:41:59 +00:00
2019-08-24 12:07:46 +00:00
hybrid_finish :
2019-08-18 11:05:47 +00:00
2018-08-28 17:05:57 +00:00
scalefactor = crossf / hcrossf7 ;
orbsize = crossf ;
2020-05-31 01:30:14 +00:00
if ( fake : : in ( ) & & WDIM = = 2 ) {
auto & u = * fake : : underlying_cgip ;
geometry = fake : : underlying ;
2020-06-03 13:11:20 +00:00
ld orig = xpush0 ( u . hcrossf ) [ 0 ] / xpush0 ( u . hcrossf ) [ GDIM ] ;
2020-05-31 01:30:14 +00:00
geometry = gFake ;
2020-06-03 13:11:20 +00:00
ld our = xpush0 ( hcrossf ) [ 0 ] / xpush0 ( hcrossf ) [ GDIM ] ;
2020-05-31 01:30:14 +00:00
fake : : scale = our / orig ;
// if(debugflags & DF_GEOM)
}
if ( fake : : in ( ) & & WDIM = = 3 ) {
2020-05-16 09:22:09 +00:00
auto & u = fake : : underlying_cgip ;
crossf = u - > crossf * fake : : scale ;
scalefactor = u - > scalefactor * fake : : scale ;
orbsize = u - > orbsize * fake : : scale ;
hexf = u - > hexf * fake : : scale ;
rhexf = u - > rhexf * fake : : scale ;
hexvdist = u - > hexvdist * fake : : scale ;
2020-05-31 01:30:14 +00:00
hcrossf = u - > hcrossf * fake : : scale ;
2020-05-16 09:22:09 +00:00
}
2020-05-30 18:00:09 +00:00
if ( arb : : in ( ) ) {
2020-06-02 00:29:31 +00:00
auto csc = arb : : current_or_slided ( ) . cscale ;
2020-05-30 18:00:09 +00:00
scalefactor = csc ;
hcrossf = crossf = orbsize = hcrossf7 * csc ;
2021-07-30 10:12:25 +00:00
hexf = rhexf = hexvdist = csc * arb : : current_or_slided ( ) . floor_scale ;
2021-07-30 09:49:13 +00:00
base_distlimit = arb : : current . range ;
2020-05-30 18:00:09 +00:00
}
2021-07-06 23:48:20 +00:00
2022-02-17 20:00:10 +00:00
# if MAXMDIM >= 4
2021-07-07 16:26:03 +00:00
if ( is_subcube_based ( variation ) ) {
2021-07-06 23:48:20 +00:00
scalefactor / = reg3 : : subcube_count ;
orbsize / = reg3 : : subcube_count ;
}
2022-02-17 20:00:10 +00:00
# endif
2020-05-16 09:22:09 +00:00
2022-12-08 18:38:06 +00:00
if ( geom3 : : euc_in_hyp ( ) ) {
scalefactor * = exp ( - vid . depth ) ;
}
2022-12-13 22:26:44 +00:00
if ( geom3 : : euc_in_noniso ( ) ) scalefactor * = geom3 : : euclid_embed_scale ;
2022-12-08 18:38:06 +00:00
if ( geom3 : : sph_in_euc ( ) ) scalefactor * = ( 1 + vid . depth ) ;
if ( geom3 : : sph_in_hyp ( ) ) scalefactor * = sinh ( 1 + vid . depth ) ;
2021-03-21 10:31:29 +00:00
if ( scale_used ( ) ) {
scalefactor * = vid . creature_scale ;
orbsize * = vid . creature_scale ;
}
2019-02-28 02:41:59 +00:00
2018-08-28 17:05:57 +00:00
zhexf = BITRUNCATED ? hexf : crossf * .55 ;
2019-07-21 21:12:16 +00:00
if ( scale_used ( ) ) zhexf * = vid . creature_scale ;
2019-05-15 16:43:40 +00:00
if ( WDIM = = 2 & & GDIM = = 3 ) zhexf * = 1.5 , orbsize * = 1.2 ;
2018-08-28 17:05:57 +00:00
2022-10-06 10:26:17 +00:00
floorrad0 = hexvdist * ( GDIM = = 3 ? 1 : 1 - 0.08 * global_boundary_ratio ) ;
floorrad1 = rhexf * ( GDIM = = 3 ? 1 : 1 - 0.06 * global_boundary_ratio ) ;
2018-08-28 17:05:57 +00:00
2019-12-14 10:26:03 +00:00
if ( euc : : in ( 2 , 4 ) ) {
2018-08-28 17:05:57 +00:00
if ( ! BITRUNCATED )
2019-05-08 23:40:29 +00:00
floorrad0 = floorrad1 = rhexf * ( GDIM = = 3 ? 1 : .94 ) ;
2018-08-28 17:05:57 +00:00
else
2019-05-08 23:40:29 +00:00
floorrad0 = hexvdist * ( GDIM = = 3 ? 1 : .9 ) ,
floorrad1 = rhexf * ( GDIM = = 3 ? 1 : .8 ) ;
2018-08-28 17:05:57 +00:00
}
2018-09-23 11:56:00 +00:00
2019-08-18 19:16:27 +00:00
plevel = vid . plevel_factor * scalefactor ;
2019-08-26 12:16:55 +00:00
single_step = 1 ;
2022-12-08 18:38:06 +00:00
if ( mhybrid & & ! mproduct ) {
2020-10-15 14:33:52 +00:00
# if CAP_ARCM
2019-08-27 16:59:26 +00:00
if ( hybrid : : underlying = = gArchimedean )
2020-07-24 00:30:50 +00:00
arcm : : current . get_step_values ( psl_steps , single_step ) ;
2020-10-15 14:33:52 +00:00
# else
if ( 0 ) ;
# endif
2019-08-26 13:39:37 +00:00
else {
single_step = S3 * S7 - 2 * S7 - 2 * S3 ;
2020-07-24 00:30:50 +00:00
psl_steps = 2 * S7 ;
if ( BITRUNCATED ) psl_steps * = S3 ;
2020-10-06 19:11:27 +00:00
if ( inv ) psl_steps = 2 * S3 ;
2019-08-27 07:15:35 +00:00
if ( single_step < 0 ) single_step = - single_step ;
2019-08-26 13:39:37 +00:00
}
2020-07-24 00:30:50 +00:00
DEBB ( DF_GEOM | DF_POLY , ( " steps = " , psl_steps , " / " , single_step ) ) ;
plevel = M_PI * single_step / psl_steps ;
2019-08-26 12:16:55 +00:00
}
2019-08-18 19:16:27 +00:00
2018-09-23 11:56:00 +00:00
set_sibling_limit ( ) ;
2019-05-26 16:04:02 +00:00
2022-12-08 18:38:06 +00:00
geom3 : : light_flip ( false ) ;
2019-05-26 16:04:02 +00:00
prepare_compute3 ( ) ;
if ( hyperbolic & & & currfp ! = & fieldpattern : : fp_invalid )
currfp . analyze ( ) ;
2022-12-08 18:38:06 +00:00
heptmove . resize ( S7 ) ;
hexmove . resize ( S7 ) ;
invhexmove . resize ( S7 ) ;
for ( int d = 0 ; d < S7 ; d + + )
heptmove [ d ] = spin ( - d * ALPHA ) * lxpush ( tessf ) * spin ( M_PI ) ;
for ( int d = 0 ; d < S7 ; d + + )
hexmove [ d ] = spin ( hexshift - d * ALPHA ) * lxpush ( - crossf ) * spin ( M_PI ) ;
for ( int d = 0 ; d < S7 ; d + + ) invhexmove [ d ] = iso_inverse ( hexmove [ d ] ) ;
gp : : prepare_matrices ( inv ) ;
2021-03-30 09:27:48 +00:00
# if CAP_SOLV
2021-03-25 10:13:57 +00:00
if ( asonov : : in ( ) ) {
asonov : : prepare ( ) ;
asonov : : prepare_walls ( ) ;
}
2021-03-30 09:27:48 +00:00
# endif
2015-08-08 13:57:52 +00:00
}
2019-09-05 10:00:55 +00:00
EX transmatrix xspinpush ( ld dir , ld dist ) {
2022-12-08 18:38:06 +00:00
if ( WDIM = = 2 & & GDIM = = 3 ) {
geom3 : : light_flip ( true ) ;
transmatrix T = spin ( dir ) * xpush ( dist ) * spin ( - dir ) ;
geom3 : : light_flip ( false ) ;
swapmatrix ( T ) ;
return T ;
}
else if ( euclid )
2019-02-26 13:34:37 +00:00
return eupush ( cos ( dir ) * dist , - sin ( dir ) * dist ) ;
2017-03-23 10:53:57 +00:00
else
2018-08-19 13:52:39 +00:00
return spin ( dir ) * xpush ( dist ) * spin ( - dir ) ;
2015-08-08 13:57:52 +00:00
}
2019-08-09 20:07:03 +00:00
EX purehookset hooks_swapdim ;
2019-05-08 19:09:22 +00:00
2019-09-05 10:00:55 +00:00
EX namespace geom3 {
2017-03-23 10:53:57 +00:00
// Here we convert between the following parameters:
// abslev: level below the plane
// lev: level above the world (abslev = depth-lev)
// projection: projection parameter
// factor: zoom factor
2015-08-08 13:57:52 +00:00
2021-05-23 13:57:39 +00:00
EX ld abslev_to_projection ( ld abslev ) {
2019-05-29 14:27:24 +00:00
if ( sphere | | euclid ) return vid . camera + abslev ;
return tanh ( abslev ) / tanh ( vid . camera ) ;
2015-08-08 13:57:52 +00:00
}
2017-03-23 10:53:57 +00:00
ld projection_to_abslev ( ld proj ) {
2019-05-29 14:27:24 +00:00
if ( sphere | | euclid ) return proj - vid . camera ;
2017-03-23 10:53:57 +00:00
// tanh(abslev) / tanh(camera) = proj
2019-05-29 14:27:24 +00:00
return atanh ( proj * tanh ( vid . camera ) ) ;
2015-08-08 13:57:52 +00:00
}
2017-03-23 10:53:57 +00:00
ld lev_to_projection ( ld lev ) {
2019-05-29 14:27:24 +00:00
return abslev_to_projection ( vid . depth - lev ) ;
2015-08-08 13:57:52 +00:00
}
2017-03-23 10:53:57 +00:00
ld projection_to_factor ( ld proj ) {
return lev_to_projection ( 0 ) / proj ;
}
2019-09-05 10:00:55 +00:00
EX ld factor_to_projection ( ld fac ) {
2017-03-23 10:53:57 +00:00
return lev_to_projection ( 0 ) / fac ;
}
2019-09-05 10:00:55 +00:00
EX ld lev_to_factor ( ld lev ) {
2022-12-08 18:38:06 +00:00
if ( mproduct ) return - lev ;
2019-05-08 16:33:08 +00:00
if ( WDIM = = 3 ) return lev ;
2019-05-29 14:27:24 +00:00
if ( GDIM = = 3 ) return vid . depth - lev ;
2017-03-23 10:53:57 +00:00
return projection_to_factor ( lev_to_projection ( lev ) ) ;
}
2019-09-06 06:17:02 +00:00
EX ld factor_to_lev ( ld fac ) {
2022-12-08 18:38:06 +00:00
if ( mproduct ) return - fac ;
2019-08-15 13:05:43 +00:00
if ( GDIM = = 3 ) return fac ;
2019-05-29 14:27:24 +00:00
return vid . depth - projection_to_abslev ( factor_to_projection ( fac ) ) ;
2017-03-23 10:53:57 +00:00
}
2019-09-05 10:00:55 +00:00
EX void do_auto_eye ( ) {
2019-06-01 17:58:07 +00:00
if ( ! vid . auto_eye ) return ;
auto & cs = getcs ( ) ;
if ( cs . charid < 4 )
vid . eye = cgi . eyelevel_human ;
else if ( cs . charid < 8 )
vid . eye = cgi . eyelevel_dog ;
else if ( cs . charid = = 8 )
vid . eye = cgi . eyelevel_familiar ;
}
2017-03-23 10:53:57 +00:00
// how should we scale at level lev
2019-09-06 06:17:02 +00:00
EX ld scale_at_lev ( ld lev ) {
2017-03-23 10:53:57 +00:00
if ( sphere | | euclid ) return 1 ;
2019-05-29 14:27:24 +00:00
return cosh ( vid . depth - lev ) ;
2017-03-23 10:53:57 +00:00
}
2019-09-05 10:00:55 +00:00
EX string invalid ;
2017-03-23 10:53:57 +00:00
2019-09-05 10:00:55 +00:00
EX ld actual_wall_height ( ) {
2022-12-08 18:38:06 +00:00
if ( mhybrid ) return cgi . plevel ;
2019-02-17 17:28:20 +00:00
# if CAP_GP
2019-05-29 14:27:24 +00:00
if ( GOLDBERG & & vid . gp_autoscale_heights )
return vid . wall_height * min < ld > ( 4 / hypot_d ( 2 , gp : : next ) , 1 ) ;
2019-02-17 17:28:20 +00:00
# endif
2019-05-29 14:27:24 +00:00
return vid . wall_height ;
2018-04-23 10:34:14 +00:00
}
2019-09-05 10:00:55 +00:00
EX }
2018-04-23 10:34:14 +00:00
2019-05-26 16:04:02 +00:00
void geometry_information : : prepare_compute3 ( ) {
using namespace geom3 ;
2019-05-12 23:57:40 +00:00
DEBBI ( DF_INIT | DF_POLY | DF_GEOM , ( " geom3::compute " ) ) ;
2020-04-16 22:53:58 +00:00
// tanh(depth) / tanh(camera) == pconf.alpha
2017-03-23 10:53:57 +00:00
invalid = " " ;
2022-12-08 18:38:06 +00:00
if ( GDIM = = 3 | | flipped ) ;
2019-05-29 14:27:24 +00:00
else if ( vid . tc_alpha < vid . tc_depth & & vid . tc_alpha < vid . tc_camera )
2020-04-16 22:53:58 +00:00
pconf . alpha = tan_auto ( vid . depth ) / tan_auto ( vid . camera ) ;
2019-05-29 14:27:24 +00:00
else if ( vid . tc_depth < vid . tc_alpha & & vid . tc_depth < vid . tc_camera ) {
2020-04-16 22:53:58 +00:00
ld v = pconf . alpha * tan_auto ( vid . camera ) ;
2021-05-23 13:47:45 +00:00
if ( hyperbolic & & ( v < 1e-6 - 12 | | v > 1 - 1e-12 ) ) invalid = XLAT ( " cannot adjust depth " ) , vid . depth = vid . camera ;
2019-05-29 14:27:24 +00:00
else vid . depth = atan_auto ( v ) ;
2017-03-23 10:53:57 +00:00
}
else {
2020-04-16 22:53:58 +00:00
ld v = tan_auto ( vid . depth ) / pconf . alpha ;
2021-05-23 13:47:45 +00:00
if ( hyperbolic & & ( v < 1e-12 - 1 | | v > 1 - 1e-12 ) ) invalid = XLAT ( " cannot adjust camera " ) , vid . camera = vid . depth ;
2019-05-29 14:27:24 +00:00
else vid . camera = atan_auto ( v ) ;
2017-03-23 10:53:57 +00:00
}
2021-05-23 13:47:45 +00:00
if ( fabs ( pconf . alpha ) < 1e-6 ) invalid = XLAT ( " does not work with perfect Klein " ) ;
2017-03-23 10:53:57 +00:00
if ( invalid ! = " " ) {
INFDEEP = .7 ;
BOTTOM = .8 ;
HELLSPIKE = .85 ;
LAKE = .9 ;
2019-05-08 16:33:08 +00:00
FLOOR = 1 ;
2017-03-23 10:53:57 +00:00
WALL = 1.25 ;
SLEV [ 0 ] = 1 ;
SLEV [ 1 ] = 1.08 ;
SLEV [ 2 ] = 1.16 ;
SLEV [ 3 ] = 1.24 ;
FLATEYE = 1.03 ;
LEG1 = 1.025 ;
LEG = 1.05 ;
LEG3 = 1.075 ;
GROIN = 1.09 ;
GROIN1 = 1.105 ;
GHOST = 1.1 ;
BODY = 1.15 ;
2019-02-27 18:15:58 +00:00
BODY1 = 1.151 ;
BODY2 = 1.152 ;
BODY3 = 1.153 ;
2017-03-23 10:53:57 +00:00
NECK1 = 1.16 ;
NECK = 1.17 ;
NECK3 = 1.18 ;
2019-02-27 00:15:40 +00:00
HEAD = 1.188 ;
HEAD1 = 1.189 ;
HEAD2 = 1.190 ;
2019-04-20 23:00:15 +00:00
HEAD3 = 1.191 ;
2017-03-23 10:53:57 +00:00
ABODY = 1.08 ;
AHEAD = 1.12 ;
BIRD = 1.20 ;
}
else {
2022-11-12 21:38:45 +00:00
INFDEEP = GDIM = = 3 ? ( sphere ? 90. _deg : + 5 ) : ( euclid | | sphere ) ? 0.01 : lev_to_projection ( 0 ) * tanh ( vid . camera ) ;
2018-04-23 10:34:14 +00:00
ld wh = actual_wall_height ( ) ;
WALL = lev_to_factor ( wh ) ;
2019-05-08 16:33:08 +00:00
FLOOR = lev_to_factor ( 0 ) ;
2017-03-23 10:53:57 +00:00
2019-05-29 14:27:24 +00:00
human_height = vid . human_wall_ratio * wh ;
if ( WDIM = = 3 ) human_height = scalefactor * vid . height_width / 2 ;
2022-12-08 18:38:06 +00:00
if ( mhybrid ) human_height = min ( human_height , cgi . plevel * .9 ) ;
2019-05-08 16:33:08 +00:00
ld reduce = ( WDIM = = 3 ? human_height / 2 : 0 ) ;
2019-02-27 17:59:21 +00:00
LEG0 = lev_to_factor ( human_height * .0 - reduce ) ;
LEG1 = lev_to_factor ( human_height * .1 - reduce ) ;
LEG = lev_to_factor ( human_height * .2 - reduce ) ;
LEG3 = lev_to_factor ( human_height * .3 - reduce ) ;
GROIN = lev_to_factor ( human_height * .4 - reduce ) ;
GROIN1 = lev_to_factor ( human_height * .5 - reduce ) ;
BODY = lev_to_factor ( human_height * .6 - reduce ) ;
2019-02-27 18:15:58 +00:00
BODY1 = lev_to_factor ( human_height * .61 - reduce ) ;
BODY2 = lev_to_factor ( human_height * .62 - reduce ) ;
BODY3 = lev_to_factor ( human_height * .63 - reduce ) ;
2019-02-27 17:59:21 +00:00
NECK1 = lev_to_factor ( human_height * .7 - reduce ) ;
NECK = lev_to_factor ( human_height * .8 - reduce ) ;
NECK3 = lev_to_factor ( human_height * .9 - reduce ) ;
2019-04-20 23:00:15 +00:00
HEAD = lev_to_factor ( human_height * .97 - reduce ) ;
HEAD1 = lev_to_factor ( human_height * .98 - reduce ) ;
HEAD2 = lev_to_factor ( human_height * .99 - reduce ) ;
HEAD3 = lev_to_factor ( human_height - reduce ) ;
2017-03-23 10:53:57 +00:00
2019-08-15 13:05:43 +00:00
reduce = ( GDIM = = 3 ? human_height * .3 : 0 ) ;
2019-02-27 17:59:21 +00:00
2022-12-08 20:20:17 +00:00
int sgn = vid . wall_height > 0 ? 1 : - 1 ;
2022-12-13 22:26:44 +00:00
ld ees = geom3 : : euc_in_noniso ( ) ? geom3 : : euclid_embed_scale : 1 ;
2022-12-08 20:20:17 +00:00
2022-12-13 18:04:43 +00:00
STUFF = lev_to_factor ( 0 ) - sgn * max ( orbsize * ees * 0.3 , zhexf * ees * .6 ) ;
2019-05-08 16:33:08 +00:00
2019-02-27 17:59:21 +00:00
ABODY = lev_to_factor ( human_height * .4 - reduce ) ;
ALEG0 = lev_to_factor ( human_height * .0 - reduce ) ;
ALEG = lev_to_factor ( human_height * .2 - reduce ) ;
AHEAD = lev_to_factor ( human_height * .6 - reduce ) ;
2019-05-29 14:27:24 +00:00
BIRD = lev_to_factor ( WDIM = = 3 ? 0 : ( vid . human_wall_ratio + 1 ) / 2 * wh * .8 ) ;
2019-05-12 18:06:24 +00:00
GHOST = lev_to_factor ( WDIM = = 3 ? 0 : human_height * .5 ) ;
2017-03-23 10:53:57 +00:00
FLATEYE = lev_to_factor ( human_height * .15 ) ;
2019-05-29 14:27:24 +00:00
slev = vid . rock_wall_ratio * wh / 3 ;
2017-03-23 10:53:57 +00:00
for ( int s = 0 ; s < = 3 ; s + + )
2019-05-29 14:27:24 +00:00
SLEV [ s ] = lev_to_factor ( vid . rock_wall_ratio * wh * s / 3 ) ;
2022-12-08 21:15:57 +00:00
LAKE = lev_to_factor ( sgn * - vid . lake_top ) ;
SHALLOW = lev_to_factor ( sgn * - .4 ) ;
HELLSPIKE = lev_to_factor ( sgn * - ( vid . lake_top + vid . lake_bottom ) / 2 ) ;
BOTTOM = lev_to_factor ( sgn * - vid . lake_bottom ) ;
2019-06-07 15:51:50 +00:00
LOWSKY = lev_to_factor ( 2 * wh ) ;
2019-05-24 23:36:49 +00:00
HIGH = LOWSKY ;
2019-06-07 15:51:50 +00:00
HIGH2 = lev_to_factor ( 3 * wh ) ;
2022-12-08 20:20:17 +00:00
SKY = LOWSKY - sgn * 5 ;
2022-12-08 18:38:06 +00:00
if ( geom3 : : mgclass ( ) = = gcSphere & & geom3 : : ggclass ( ) ! = gcSphere ) {
ld max_high = lerp ( - FLOOR , - 1 , 0.8 ) ;
ld max_high2 = lerp ( - FLOOR , - 1 , 0.9 ) ;
if ( HIGH < max_high ) HIGH = max_high ;
if ( HIGH2 < max_high2 ) HIGH2 = max_high2 ;
if ( LOWSKY < max_high ) LOWSKY = max_high ;
if ( SKY < max_high ) SKY = max_high ;
if ( vid . wall_height < 0 ) {
SKY = - 3 * vid . wall_height ;
LOWSKY = 1.75 * SKY ;
}
2022-12-08 21:15:57 +00:00
if ( SHALLOW < max_high ) SHALLOW = max_high ;
if ( LAKE < max_high ) LAKE = max_high ;
if ( BOTTOM < max_high2 ) BOTTOM = max_high2 ;
if ( HELLSPIKE < max_high ) HELLSPIKE = max_high ;
if ( sgn < 0 ) INFDEEP = - 1 ;
2022-12-08 18:38:06 +00:00
}
2022-12-13 18:04:43 +00:00
if ( geom3 : : euc_in_hyp ( ) & & sgn < 0 ) INFDEEP = FLOOR - 5 ;
2017-03-23 10:53:57 +00:00
}
}
2019-05-09 15:01:08 +00:00
2019-08-09 19:00:52 +00:00
EX namespace geom3 {
2022-12-08 18:38:06 +00:00
# if HDR
enum eSpatialEmbedding {
seDefault ,
seFlat ,
seInverted ,
seLowerCurvature ,
seLowerCurvatureInverted ,
seMuchLowerCurvature ,
seMuchLowerCurvatureInverted ,
2022-12-13 18:04:43 +00:00
seProduct ,
2022-12-13 22:26:44 +00:00
seNil ,
seSol , seNIH , seSolN ,
seNIH_inv
2022-12-08 18:38:06 +00:00
} ;
# endif
EX vector < pair < string , string > > spatial_embedding_options = {
{ " default " , " Embed as a equidistant surface in the 3D version of the same geometry. This is the model used by HyperRogue in its 2D graphics. " } ,
{ " flat " , " Embed as a flat surface in the 3D version of the same geometry. " } ,
{ " inverted " , " Embed as a equidistant surface, but this time it is inverted. " } ,
{ " lower curvature " , " Embed as a convex surface in a space of lower curvature. " } ,
{ " lower curvature inverted " , " Embed as a concave surface in a space of lower curvature. " } ,
{ " much lower curvature " , " Embed sphere as a convex sphere in hyperbolic space. " } ,
{ " much lower curvature inverted " , " Embed sphere as a concave sphere in hyperbolic space. " } ,
2022-12-13 18:04:43 +00:00
{ " product " , " Add one extra dimension in the Euclidean way. " } ,
2022-12-13 22:26:44 +00:00
{ " Nil " , " Embed into Nil. Works only with Euclidean. You need to set the variation to Pure. " } ,
{ " Sol " , " Embed into Sol. Works only with Euclidean. You need to set the variation to Pure. " } ,
{ " stretched hyperbolic " , " Embed into stretched hyperbolic geometry. Works only with Euclidean. You need to set the variation to Pure. " } ,
{ " stretched Sol " , " Embed into stretched Sol geometry. Works only with Euclidean. You need to set the variation to Pure. " } ,
{ " stretched hyperbolic inverted " , " Embed into stretched hyperbolic geometry as a concave horosphere. Works only with Euclidean. You need to set the variation to Pure. " } ,
2022-12-08 18:38:06 +00:00
} ;
EX eSpatialEmbedding spatial_embedding ;
2022-12-13 18:04:43 +00:00
EX ld euclid_embed_scale = 1 ;
2022-12-08 18:38:06 +00:00
EX vector < geometryinfo > ginf_backup ;
EX eGeometryClass mgclass ( ) {
return ( embedded_plane ? ginf_backup : ginf ) [ geometry ] . g . kind ;
}
EX eGeometryClass ggclass ( ) {
return ( flipped ? ginf_backup : ginf ) [ geometry ] . g . kind ;
}
EX bool euc_in_hyp ( ) {
return ggclass ( ) = = gcHyperbolic & & mgclass ( ) = = gcEuclid ;
}
2022-12-13 18:04:43 +00:00
EX bool euc_in_nil ( ) {
return ggclass ( ) = = gcNil & & mgclass ( ) = = gcEuclid ;
}
2022-12-13 22:26:44 +00:00
EX bool euc_in_solnih ( ) {
return among ( ggclass ( ) , gcSol , gcNIH , gcSolN ) & & mgclass ( ) = = gcEuclid ;
}
EX bool euc_in_noniso ( ) {
return among ( ggclass ( ) , gcNil , gcSol , gcNIH , gcSolN ) & & nonisotropic ;
}
2022-12-08 18:38:06 +00:00
EX bool sph_in_euc ( ) {
return ggclass ( ) = = gcEuclid & & mgclass ( ) = = gcSphere ;
}
EX bool sph_in_hyp ( ) {
return ggclass ( ) = = gcHyperbolic & & mgclass ( ) = = gcSphere ;
}
EX bool in_product ( ) {
return ggclass ( ) = = gcProduct ;
}
EX bool same_in_same ( ) {
return mgclass ( ) = = ggclass ( ) ;
}
EX bool flipped ;
EX void light_flip ( bool f ) {
if ( f ! = flipped ) {
swap ( ginf [ geometry ] . g , geom3 : : ginf_backup [ geometry ] . g ) ;
swap ( ginf [ geometry ] . flags , geom3 : : ginf_backup [ geometry ] . flags ) ;
flipped = f ;
}
}
2019-08-22 09:24:25 +00:00
2022-12-08 18:38:06 +00:00
# if HDR
template < class T > auto in_flipped ( const T & f ) - > decltype ( f ( ) ) {
light_flip ( true ) ;
finalizer ff ( [ ] { light_flip ( false ) ; } ) ;
return f ( ) ;
}
# define IPF(x) geom3::in_flipped([&] { return (x); })
# endif
EX void apply_always3 ( ) {
if ( ! vid . always3 & & ! ginf_backup . empty ( ) ) {
ginf = ginf_backup ;
ginf_backup . clear ( ) ;
}
if ( vid . always3 & & ginf_backup . empty ( ) ) {
ginf_backup = ginf ;
for ( geometryinfo & gi : ginf ) {
auto & g = gi . g ;
if ( vid . always3 & & g . gameplay_dimension = = 2 & & g . graphical_dimension = = 2 ) {
g . graphical_dimension + + ;
g . homogeneous_dimension + + ;
g . sig [ 3 ] = g . sig [ 2 ] ;
g . sig [ 2 ] = g . sig [ 1 ] ;
if ( spatial_embedding = = seProduct & & g . kind ! = gcEuclid ) {
g . kind = gcProduct ;
g . homogeneous_dimension - - ;
g . sig [ 2 ] = g . sig [ 3 ] ;
}
if ( among ( spatial_embedding , seLowerCurvature , seLowerCurvatureInverted ) ) {
if ( g . kind = = gcEuclid ) g = ginf [ gSpace534 ] . g ;
if ( g . kind = = gcSphere ) g = ginf [ gCubeTiling ] . g ;
g . gameplay_dimension = 2 ;
}
if ( among ( spatial_embedding , seMuchLowerCurvature , seMuchLowerCurvatureInverted ) ) {
g = ginf [ gSpace534 ] . g ;
g . gameplay_dimension = 2 ;
}
2022-12-13 18:04:43 +00:00
if ( spatial_embedding = = seNil & & euclid ) {
g = ginf [ gNil ] . g ;
g . gameplay_dimension = 2 ;
}
2022-12-13 22:26:44 +00:00
if ( spatial_embedding = = seSol & & euclid ) {
g = ginf [ gSol ] . g ;
g . gameplay_dimension = 2 ;
}
if ( spatial_embedding = = seNIH & & euclid ) {
g = ginf [ gNIH ] . g ;
g . gameplay_dimension = 2 ;
}
if ( spatial_embedding = = seNIH_inv & & euclid ) {
g = ginf [ gNIH ] . g ;
g . gameplay_dimension = 2 ;
}
if ( spatial_embedding = = seSolN & & euclid ) {
g = ginf [ gSolN ] . g ;
g . gameplay_dimension = 2 ;
}
2022-12-08 18:38:06 +00:00
}
2019-08-22 09:24:25 +00:00
}
}
}
2019-05-11 06:19:38 +00:00
# if MAXMDIM >= 4
2019-08-09 19:00:52 +00:00
EX void switch_always3 ( ) {
2019-05-28 23:09:38 +00:00
if ( dual : : split ( switch_always3 ) ) return ;
2020-10-15 14:33:52 +00:00
# if CAP_GL && CAP_RUG
2019-05-13 10:59:49 +00:00
if ( rug : : rugged ) rug : : close ( ) ;
2020-07-03 12:42:33 +00:00
# endif
2019-05-29 14:27:24 +00:00
vid . always3 = ! vid . always3 ;
2019-08-22 09:24:25 +00:00
apply_always3 ( ) ;
2019-05-10 02:03:07 +00:00
swapmatrix ( View ) ;
2019-05-09 15:01:08 +00:00
callhooks ( hooks_swapdim ) ;
}
2019-05-11 06:19:38 +00:00
# endif
2019-05-09 15:01:08 +00:00
2019-08-09 19:00:52 +00:00
EX void switch_tpp ( ) {
2019-05-28 23:09:38 +00:00
if ( dual : : split ( switch_fpp ) ) return ;
2020-04-16 22:53:58 +00:00
if ( pmodel = = mdDisk & & pconf . camera_angle ) {
2019-05-09 15:01:08 +00:00
vid . yshift = 0 ;
2020-04-16 22:53:58 +00:00
pconf . camera_angle = 0 ;
pconf . xposition = 0 ;
pconf . yposition = 0 ;
pconf . scale = 1 ;
2019-05-09 15:01:08 +00:00
vid . fixed_facing = false ;
}
else {
vid . yshift = - 0.3 ;
2020-04-16 22:53:58 +00:00
pconf . camera_angle = - 45 ;
pconf . scale = 18 / 16. * vid . xres / vid . yres / multi : : players ;
pconf . xposition = 0 ;
pconf . yposition = - 0.9 ;
2019-05-09 15:01:08 +00:00
vid . fixed_facing = true ;
vid . fixed_facing_dir = 90 ;
}
}
2019-08-09 19:00:52 +00:00
EX void switch_fpp ( ) {
2019-05-11 06:19:38 +00:00
# if MAXMDIM >= 4
2020-10-15 14:33:52 +00:00
# if CAP_GL && CAP_RUG
2019-05-13 10:59:49 +00:00
if ( rug : : rugged ) rug : : close ( ) ;
2020-07-03 12:42:33 +00:00
# endif
2019-05-28 23:09:38 +00:00
if ( dual : : split ( switch_fpp ) ) return ;
2019-05-28 23:20:25 +00:00
check_cgi ( ) ; cgi . require_basics ( ) ;
2020-09-16 03:57:05 +00:00
View = iso_inverse ( models : : rotmatrix ( ) ) * View ;
2019-05-29 14:27:24 +00:00
if ( ! vid . always3 ) {
vid . always3 = true ;
2019-08-22 09:24:25 +00:00
apply_always3 ( ) ;
2019-05-28 23:20:25 +00:00
ld ms = min < ld > ( cgi . scalefactor , 1 ) ;
2022-12-08 18:38:06 +00:00
vid . depth = ms ;
2019-05-29 14:27:24 +00:00
vid . wall_height = 1.5 * ms ;
2022-12-08 18:38:06 +00:00
if ( sphere & & same_in_same ( ) ) {
2022-11-12 21:38:45 +00:00
vid . depth = 30 * degree ;
vid . wall_height = 60 * degree ;
2019-05-09 17:15:00 +00:00
}
2019-05-29 14:27:24 +00:00
vid . human_wall_ratio = 0.8 ;
2022-12-08 18:38:06 +00:00
if ( mgclass ( ) = = gcEuclid & & allowIncreasedSight ( ) & & vid . use_smart_range = = 0 ) {
2019-05-28 23:20:25 +00:00
genrange_bonus = gamerange_bonus = sightrange_bonus = cgi . base_distlimit * 3 / 2 ;
}
2019-05-29 14:27:24 +00:00
vid . camera = 0 ;
2022-12-08 18:38:06 +00:00
vid . eye = 0 ;
if ( sph_in_euc ( ) | | sph_in_hyp ( ) ) {
vid . depth = 0 ;
vid . wall_height = - 1 ;
vid . eye = 0.5 ;
if ( among ( spatial_embedding , seLowerCurvatureInverted , seMuchLowerCurvatureInverted ) ) {
vid . wall_height = 1.4 ;
vid . eye = - 0.2 ;
vid . depth = 0.5 ;
}
}
if ( spatial_embedding = = seFlat ) {
vid . eye - = vid . depth / 2 ;
vid . depth = 0 ;
}
if ( spatial_embedding = = seInverted ) {
vid . eye - = vid . depth * 1.5 ;
vid . depth * = - 1 ;
}
if ( euc_in_hyp ( ) & & spatial_embedding = = seLowerCurvatureInverted ) {
vid . wall_height * = - 1 ;
vid . eye = 2 * vid . depth ;
}
if ( euc_in_hyp ( ) & & spatial_embedding = = seMuchLowerCurvatureInverted ) {
vid . wall_height * = - 1 ;
vid . eye = 2 * vid . depth ;
}
2022-12-13 22:26:44 +00:00
if ( euc_in_noniso ( ) & & spatial_embedding = = seNIH_inv ) {
vid . wall_height * = - 1 ;
vid . eye = 2 * vid . depth ;
}
2022-12-08 20:36:22 +00:00
if ( msphere & & spatial_embedding = = seProduct ) {
vid . depth = 0 ;
vid . wall_height = 2 ;
vid . eye = - 2 ;
}
2022-12-13 18:04:43 +00:00
if ( pmodel = = mdDisk ) pmodel = nonisotropic ? mdGeodesic : mdPerspective ;
2019-05-10 02:03:07 +00:00
swapmatrix ( View ) ;
2021-04-15 15:54:49 +00:00
swapmatrix ( current_display - > which_copy ) ;
2019-05-09 15:01:08 +00:00
callhooks ( hooks_swapdim ) ;
2021-02-06 11:25:30 +00:00
for ( auto m : allmaps ) m - > on_dim_change ( ) ;
2020-05-29 08:47:18 +00:00
if ( cgflags & qIDEAL & & vid . texture_step < 32 )
vid . texture_step = 32 ;
2019-05-13 14:01:52 +00:00
# if CAP_RACING
racing : : player_relative = true ;
# endif
2022-12-08 18:38:06 +00:00
check_cgi ( ) ;
cgi . prepare_basics ( ) ;
2019-05-09 15:01:08 +00:00
}
else {
2019-05-29 14:27:24 +00:00
vid . always3 = false ;
2019-08-22 09:24:25 +00:00
apply_always3 ( ) ;
2019-05-29 14:27:24 +00:00
vid . wall_height = .3 ;
vid . human_wall_ratio = .7 ;
vid . camera = 1 ;
vid . depth = 1 ;
2019-05-09 15:01:08 +00:00
if ( pmodel = = mdPerspective ) pmodel = mdDisk ;
2019-05-10 02:03:07 +00:00
swapmatrix ( View ) ;
2021-04-15 15:54:49 +00:00
swapmatrix ( current_display - > which_copy ) ;
2019-05-09 15:01:08 +00:00
callhooks ( hooks_swapdim ) ;
2021-02-06 11:25:30 +00:00
for ( auto m : allmaps ) m - > on_dim_change ( ) ;
2019-05-09 15:01:08 +00:00
}
2019-08-09 22:58:50 +00:00
View = models : : rotmatrix ( ) * View ;
2019-05-11 06:19:38 +00:00
# endif
2019-06-13 15:03:32 +00:00
}
2019-05-09 15:01:08 +00:00
2019-08-09 19:00:52 +00:00
EX }
2015-08-08 13:57:52 +00:00
2019-08-09 20:37:11 +00:00
EX geometry_information * cgip ;
EX map < string , geometry_information > cgis ;
# if HDR
# define cgi (*cgip)
# endif
2019-05-26 16:04:02 +00:00
2019-09-05 10:00:55 +00:00
EX int last_texture_step ;
2019-06-18 14:01:28 +00:00
2019-06-18 14:16:09 +00:00
int ntimestamp ;
2021-03-21 10:33:25 +00:00
EX hookset < void ( string & ) > hooks_cgi_string ;
2020-05-15 09:41:30 +00:00
EX string cgi_string ( ) {
2019-05-26 16:04:02 +00:00
string s ;
auto V = [ & ] ( string a , string b ) { s + = a ; s + = " : " ; s + = b ; s + = " ; " ; } ;
V ( " GEO " , its ( int ( geometry ) ) ) ;
V ( " VAR " , its ( int ( variation ) ) ) ;
2022-04-24 20:09:54 +00:00
if ( arb : : in ( ) ) {
2020-06-02 00:29:31 +00:00
for ( auto & sl : arb : : current . sliders )
V ( " AS " , fts ( sl . current ) ) ;
2022-04-24 20:09:54 +00:00
for ( auto & sl : arb : : current . intsliders )
V ( " AS " , its ( sl . current ) ) ;
2020-06-02 00:29:31 +00:00
}
2020-05-15 09:46:26 +00:00
if ( fake : : in ( ) ) {
2020-05-31 01:30:14 +00:00
if ( hyperbolic ) V ( " H " , fts ( fake : : around ) ) ;
if ( euclid ) V ( " E " , fts ( fake : : around ) ) ;
if ( sphere ) V ( " S " , fts ( fake : : around ) ) ;
2020-05-15 09:46:26 +00:00
V ( " G " , FPIU ( cgi_string ( ) ) ) ;
2020-05-28 11:44:02 +00:00
return s ;
2020-05-15 09:46:26 +00:00
}
2020-07-12 18:52:32 +00:00
if ( GOLDBERG_INV ) V ( " GP " , its ( gp : : param . first ) + " , " + its ( gp : : param . second ) ) ;
2019-05-26 16:04:02 +00:00
if ( IRREGULAR ) V ( " IRR " , its ( irr : : irrid ) ) ;
2022-02-17 20:00:10 +00:00
# if MAXMDIM >= 4
2021-07-07 16:26:03 +00:00
if ( is_subcube_based ( variation ) ) V ( " SC " , its ( reg3 : : subcube_count ) ) ;
2021-07-09 12:00:54 +00:00
if ( variation = = eVariation : : coxeter ) V ( " COX " , its ( reg3 : : coxeter_param ) ) ;
2022-02-17 20:00:10 +00:00
# endif
2019-05-26 16:04:02 +00:00
2020-10-15 14:33:52 +00:00
# if CAP_ARCM
2019-12-14 10:42:16 +00:00
if ( arcm : : in ( ) ) V ( " ARCM " , arcm : : current . symbol ) ;
2020-10-15 14:33:52 +00:00
# endif
2019-12-27 11:05:28 +00:00
2019-12-27 21:59:02 +00:00
if ( arb : : in ( ) ) V ( " ARB " , its ( arb : : current . order ) ) ;
2022-05-01 09:18:39 +00:00
if ( arb : : in ( ) ) V ( " AP " , its ( arb : : apeirogon_simplified_display ) ) ;
2022-09-14 20:53:39 +00:00
if ( arb : : in ( ) ) V ( " F " , its ( arb : : extended_football ) ) ;
2022-10-06 10:26:17 +00:00
V ( " BR " , fts ( global_boundary_ratio ) ) ;
2019-08-22 10:14:39 +00:00
if ( cryst ) V ( " CRYSTAL " , its ( ginf [ gCrystal ] . sides ) + its ( ginf [ gCrystal ] . vertex ) ) ;
2019-05-26 16:04:02 +00:00
2019-12-14 11:05:01 +00:00
if ( bt : : in ( ) | | GDIM = = 3 ) V ( " WQ " , its ( vid . texture_step ) ) ;
2019-05-26 16:04:02 +00:00
2022-12-08 18:38:06 +00:00
if ( mhybrid ) {
2020-10-18 12:37:55 +00:00
V ( " U " , PIU ( cgi_string ( ) ) ) ;
}
2019-08-27 07:18:47 +00:00
2022-12-08 18:38:06 +00:00
if ( mproduct ) V ( " PL " , fts ( vid . plevel_factor ) ) ;
2019-11-13 19:48:38 +00:00
2019-11-17 12:35:18 +00:00
if ( geometry = = gFieldQuotient ) { V ( " S3= " , its ( S3 ) ) ; V ( " S7= " , its ( S7 ) ) ; }
2019-11-23 19:39:38 +00:00
if ( nil ) V ( " NIL " , its ( S7 ) ) ;
2019-11-17 12:35:18 +00:00
2019-12-14 11:05:01 +00:00
if ( bt : : in ( ) ) V ( " BT " , fts ( vid . binary_width ) ) ;
2021-03-21 11:50:51 +00:00
if ( nil ) V ( " NILW " , fts ( nilv : : nilwidth ) ) ;
2019-05-26 16:04:02 +00:00
if ( GDIM = = 2 ) {
2019-05-29 14:27:24 +00:00
V ( " CAMERA " , fts ( vid . camera ) ) ;
2019-05-26 16:04:02 +00:00
}
if ( WDIM = = 2 ) {
2019-05-29 14:27:24 +00:00
V ( " WH " , fts ( vid . wall_height ) ) ;
V ( " HW " , fts ( vid . human_wall_ratio ) ) ;
V ( " RW " , fts ( vid . rock_wall_ratio ) ) ;
V ( " DEPTH " , fts ( vid . depth ) ) ;
V ( " ASH " , ONOFF ( vid . gp_autoscale_heights ) ) ;
V ( " LT " , fts ( vid . lake_top ) ) ;
V ( " LB " , fts ( vid . lake_bottom ) ) ;
2021-10-15 20:38:24 +00:00
if ( GDIM = = 3 & & vid . pseudohedral )
2021-10-15 20:36:43 +00:00
V ( " PS " , fts ( vid . depth_bonus ) ) ;
2019-05-26 16:04:02 +00:00
}
2019-05-29 14:27:24 +00:00
V ( " 3D " , ONOFF ( vid . always3 ) ) ;
2019-05-26 16:04:02 +00:00
2022-12-09 00:58:01 +00:00
if ( embedded_plane ) V ( " X: " , its ( geom3 : : ggclass ( ) ) ) ;
2019-07-21 21:12:16 +00:00
if ( scale_used ( ) ) V ( " CS " , fts ( vid . creature_scale ) ) ;
2019-05-26 16:04:02 +00:00
2019-07-21 21:12:16 +00:00
if ( WDIM = = 3 ) V ( " HTW " , fts ( vid . height_width ) ) ;
2019-05-26 16:04:02 +00:00
V ( " LQ " , its ( vid . linequality ) ) ;
2021-03-21 10:33:25 +00:00
callhooks ( hooks_cgi_string , s ) ;
2019-05-26 16:04:02 +00:00
2020-05-15 09:41:30 +00:00
return s ;
}
2022-05-09 12:53:41 +00:00
# if MAXMDIM >= 4 && CAP_RAY
2022-02-17 20:00:10 +00:00
# define IFINTRA(x,y) x
# else
# define IFINTRA(x,y) y
# endif
2020-05-15 09:41:30 +00:00
EX void check_cgi ( ) {
string s = cgi_string ( ) ;
2019-05-26 16:04:02 +00:00
cgip = & cgis [ s ] ;
2019-06-18 14:16:09 +00:00
cgi . timestamp = + + ntimestamp ;
2022-12-08 18:38:06 +00:00
if ( mhybrid ) hybrid : : underlying_cgip - > timestamp = ntimestamp ;
2020-05-15 09:46:26 +00:00
if ( fake : : in ( ) ) fake : : underlying_cgip - > timestamp = ntimestamp ;
2022-05-06 10:40:48 +00:00
# if CAP_ARCM
2021-08-05 10:48:14 +00:00
if ( arcm : : alt_cgip ) arcm : : alt_cgip - > timestamp = ntimestamp ;
2022-05-06 10:40:48 +00:00
# endif
2019-06-18 14:01:28 +00:00
2022-08-05 18:06:05 +00:00
int limit = 4 ;
for ( auto & t : cgis ) if ( t . second . use_count ) limit + + ;
if ( isize ( cgis ) > limit ) {
2019-06-18 14:01:28 +00:00
vector < pair < int , string > > timestamps ;
2022-08-05 18:06:05 +00:00
for ( auto & t : cgis ) if ( ! t . second . use_count ) timestamps . emplace_back ( - t . second . timestamp , t . first ) ;
2019-06-18 14:01:28 +00:00
sort ( timestamps . begin ( ) , timestamps . end ( ) ) ;
2019-06-18 14:16:09 +00:00
while ( isize ( timestamps ) > 4 ) {
2020-03-31 17:02:25 +00:00
DEBB ( DF_GEOM , ( " erasing geometry " , timestamps . back ( ) . second ) ) ;
2019-06-18 14:01:28 +00:00
cgis . erase ( timestamps . back ( ) . second ) ;
timestamps . pop_back ( ) ;
}
}
if ( floor_textures & & last_texture_step ! = vid . texture_step ) {
println ( hlog , " changed " , last_texture_step , " to " , vid . texture_step ) ;
delete floor_textures ;
floor_textures = NULL ;
}
2020-07-03 12:48:36 +00:00
# if MAXMDIM >= 4 && CAP_GL
2019-08-15 13:05:43 +00:00
if ( ! floor_textures & & GDIM = = 3 & & ( cgi . state & 2 ) )
2019-06-18 14:01:28 +00:00
make_floor_textures ( ) ;
2019-07-12 21:17:00 +00:00
# endif
2019-06-18 14:01:28 +00:00
2015-08-08 13:57:52 +00:00
}
2019-05-26 16:04:02 +00:00
2019-06-18 14:01:28 +00:00
void clear_cgis ( ) {
printf ( " clear_cgis \n " ) ;
for ( auto & p : cgis ) if ( & p . second ! = & cgi ) { cgis . erase ( p . first ) ; return ; }
}
auto ah_clear_geo = addHook ( hooks_clear_cache , 0 , clear_cgis ) ;
2018-06-10 23:58:31 +00:00
}