Skip to content

Instantly share code, notes, and snippets.

@ingenieroariel
Created January 27, 2024 22:03
Show Gist options
  • Save ingenieroariel/d8a85739ea01735cc71670f5e1832122 to your computer and use it in GitHub Desktop.
Save ingenieroariel/d8a85739ea01735cc71670f5e1832122 to your computer and use it in GitHub Desktop.
local mouseSpeed = 0.5
local touchSpeed = 0.1
local maxFov = 90
local minFov = 0.01
local maxPitch = 85
local minPitch = -85
local camera = {
vid = nil,
yaw = 0,
pitch = 0,
fov = maxFov,
fovDirty = false,
}
function camera:rebuild()
camtag_model(self.vid, 0.01, 100.0, self.fov, VRESW/VRESH, true, false)
self.fovDirty = false
end
local mouse = {
devid = nil,
buttons = {},
lastSample = {},
}
local touchscreen = {
devid = nil,
touches = {},
nTouches = 0,
}
local sphere
local shader = {}
local v = [[
#version 140
uniform mat4 modelview;
uniform mat4 projection;
attribute vec4 vertex;
attribute vec2 texcoord;
varying vec2 texco;
void main() {
texco = texcoord;
gl_Position = (projection * modelview) * vertex;
}
]]
local fragment_shader = [[
#version 140
#extension GL_EXT_gpu_shader4 : require
#define EPSILON 0.0000000000000001
#define PI2 6.28318530717958647693
#define PI 3.1415926535897932384626433832795
#define NUM_BASE_CELLS 122
#define NUM_ICOSA_FACES 20
#define NUM_DIGITS 15
#define M_AP7_ROT_RADS 0.333473172251832115336090755351601070065900389
#define M_SQRT7 2.6457513110645905905016157536392604257102
#define RES0_U_GNOMONIC 0.38196601125010500003
#define M_SQRT3_2 0.8660254037844386467637231707529361834714
#define M_SIN60 M_SQRT3_2
#define CENTER_DIGIT 0
#define K_AXES_DIGIT 1
#define J_AXES_DIGIT 2
#define JK_AXES_DIGIT 3
#define I_AXES_DIGIT 4
#define IK_AXES_DIGIT 5
#define IJ_AXES_DIGIT 6
#define INVALID_DIGIT 7
struct CellIndex {
int resolution;
int baseCell;
int digits[NUM_DIGITS];
};
struct FIJK {
int face;
ivec3 coord;
};
struct D {
FIJK homeFijk;
bool isPentagon;
ivec2 cwOffsetPent;
};
struct R {
int baseCell;
int ccwRot60;
};
/** @brief CoordIJK unit vectors corresponding to the 7 H3 digits.
*/
const ivec3 UV[7] = ivec3[7](
ivec3(0, 0, 0),
ivec3(0, 0, 1),
ivec3(0, 1, 0),
ivec3(0, 1, 1),
ivec3(1, 0, 0),
ivec3(1, 0, 1),
ivec3(1, 1, 0)
);
const int R60CCW[7] = int[7](
CENTER_DIGIT,
IK_AXES_DIGIT,
JK_AXES_DIGIT,
K_AXES_DIGIT,
IJ_AXES_DIGIT,
I_AXES_DIGIT,
J_AXES_DIGIT
);
const int R60CW[7] = int[7](
CENTER_DIGIT,
JK_AXES_DIGIT,
IJ_AXES_DIGIT,
J_AXES_DIGIT,
IK_AXES_DIGIT,
K_AXES_DIGIT,
I_AXES_DIGIT
);
/** @brief icosahedron face centers in lat/lng radians */
const vec2 FCG[NUM_ICOSA_FACES] = vec2[NUM_ICOSA_FACES](
vec2(0.803582649718989942, 1.248397419617396099),
vec2(1.307747883455638156, 2.536945009877921159),
vec2(1.054751253523952054, -1.347517358900396623),
vec2(0.600191595538186799, -0.450603909469755746),
vec2(0.491715428198773866, 0.401988202911306943),
vec2(0.172745327415618701, 1.678146885280433686),
vec2(0.605929321571350690, 2.953923329812411617),
vec2(0.427370518328979641, -1.888876200336285401),
vec2(-0.079066118549212831, -0.733429513380867741),
vec2(-0.230961644455383637, 0.506495587332349035),
vec2(0.079066118549212831, 2.408163140208925497),
vec2(0.230961644455383637, -2.635097066257444203),
vec2(-0.172745327415618701, -1.463445768309359553),
vec2(-0.605929321571350690, -0.187669323777381622),
vec2(-0.427370518328979641, 1.252716453253507838),
vec2(-0.600191595538186799, 2.690988744120037492),
vec2(-0.491715428198773866, -2.739604450678486295),
vec2(-0.803582649718989942, -1.893195233972397139),
vec2(-1.307747883455638156, -0.604647643711872080),
vec2(-1.054751253523952054, 1.794075294689396615)
);
/** @brief icosahedron face centers in x/y/z on the unit sphere */
const vec3 FCP[NUM_ICOSA_FACES] = vec3[NUM_ICOSA_FACES](
vec3(0.2199307791404606, 0.6583691780274996, 0.7198475378926182),
vec3(-0.2139234834501421, 0.1478171829550703, 0.9656017935214205),
vec3(0.1092625278784797, -0.4811951572873210, 0.8697775121287253),
vec3(0.7428567301586791, -0.3593941678278028, 0.5648005936517033),
vec3(0.8112534709140969, 0.3448953237639384, 0.4721387736413930),
vec3(-0.1055498149613921, 0.9794457296411413, 0.1718874610009365),
vec3(-0.8075407579970092, 0.1533552485898818, 0.5695261994882688),
vec3(-0.2846148069787907, -0.8644080972654206, 0.4144792552473539),
vec3(0.7405621473854482, -0.6673299564565524, -0.0789837646326737),
vec3(0.8512303986474293, 0.4722343788582681, -0.2289137388687808),
vec3(-0.7405621473854481, 0.6673299564565524, 0.0789837646326737),
vec3(-0.8512303986474292, -0.4722343788582682, 0.2289137388687808),
vec3(0.1055498149613919, -0.9794457296411413, -0.1718874610009365),
vec3(0.8075407579970092, -0.1533552485898819, -0.5695261994882688),
vec3(0.2846148069787908, 0.8644080972654204, -0.4144792552473539),
vec3(-0.7428567301586791, 0.3593941678278027, -0.5648005936517033),
vec3(-0.8112534709140971, -0.3448953237639382, -0.4721387736413930),
vec3(-0.2199307791404607, -0.6583691780274996, -0.7198475378926182),
vec3(0.2139234834501420, -0.1478171829550704, -0.9656017935214205),
vec3(-0.1092625278784796, 0.4811951572873210, -0.8697775121287253)
);
/** @brief icosahedron face ijk axes as azimuth in radians from face center to
* vertex 0/1/2 respectively
*/
const vec3 FARC[NUM_ICOSA_FACES] = vec3[NUM_ICOSA_FACES](
vec3(5.619958268523939882, 3.525563166130744542,
1.431168063737548730),
vec3(5.760339081714187279, 3.665943979320991689,
1.571548876927796127),
vec3(0.780213654393430055, 4.969003859179821079,
2.874608756786625655),
vec3(0.430469363979999913, 4.619259568766391033,
2.524864466373195467),
vec3(6.130269123335111400, 4.035874020941915804,
1.941478918548720291),
vec3(2.692877706530642877, 0.598482604137447119,
4.787272808923838195),
vec3(2.982963003477243874, 0.888567901084048369,
5.077358105870439581),
vec3(3.532912002790141181, 1.438516900396945656,
5.627307105183336758),
vec3(3.494305004259568154, 1.399909901866372864,
5.588700106652763840),
vec3(3.003214169499538391, 0.908819067106342928,
5.097609271892733906),
vec3(5.930472956509811562, 3.836077854116615875,
1.741682751723420374),
vec3(0.138378484090254847, 4.327168688876645809,
2.232773586483450311),
vec3(0.448714947059150361, 4.637505151845541521,
2.543110049452346120),
vec3(0.158629650112549365, 4.347419854898940135,
2.253024752505744869),
vec3(5.891865957979238535, 3.797470855586042958,
1.703075753192847583),
vec3(2.711123289609793325, 0.616728187216597771,
4.805518392002988683),
vec3(3.294508837434268316, 1.200113735041072948,
5.388903939827463911),
vec3(3.804819692245439833, 1.710424589852244509,
5.899214794638635174),
vec3(3.664438879055192436, 1.570043776661997111,
5.758833981448388027),
vec3(2.361378999196363184, 0.266983896803167583,
4.455774101589558636)
);
const R FIBC[NUM_ICOSA_FACES * 3 * 3 * 3] = R[NUM_ICOSA_FACES * 3 * 3 * 3](
R(16, 0), R(18, 0), R(24, 0),
R(33, 0), R(30, 0), R(32, 3),
R(49, 1), R(48, 3), R(50, 3),
R(8, 0), R(5, 5), R(10, 5),
R(22, 0), R(16, 0), R(18, 0),
R(41, 1), R(33, 0), R(30, 0),
R(4, 0), R(0, 5), R(2, 5),
R(15, 1), R(8, 0), R(5, 5),
R(31, 1), R(22, 0), R(16, 0),
R(2, 0), R(6, 0), R(14, 0),
R(10, 0), R(11, 0), R(17, 3),
R(24, 1), R(23, 3), R(25, 3),
R(0, 0), R(1, 5), R(9, 5),
R(5, 0), R(2, 0), R(6, 0),
R(18, 1), R(10, 0), R(11, 0),
R(4, 1), R(3, 5), R(7, 5),
R(8, 1), R(0, 0), R(1, 5),
R(16, 1), R(5, 0), R(2, 0),
R(7, 0), R(21, 0), R(38, 0),
R(9, 0), R(19, 0), R(34, 3),
R(14, 1), R(20, 3), R(36, 3),
R(3, 0), R(13, 5), R(29, 5),
R(1, 0), R(7, 0), R(21, 0),
R(6, 1), R(9, 0), R(19, 0),
R(4, 2), R(12, 5), R(26, 5),
R(0, 1), R(3, 0), R(13, 5),
R(2, 1), R(1, 0), R(7, 0),
R(26, 0), R(42, 0), R(58, 0),
R(29, 0), R(43, 0), R(62, 3),
R(38, 1), R(47, 3), R(64, 3),
R(12, 0), R(28, 5), R(44, 5),
R(13, 0), R(26, 0), R(42, 0),
R(21, 1), R(29, 0), R(43, 0),
R(4, 3), R(15, 5), R(31, 5),
R(3, 1), R(12, 0), R(28, 5),
R(7, 1), R(13, 0), R(26, 0),
R(31, 0), R(41, 0), R(49, 0),
R(44, 0), R(53, 0), R(61, 3),
R(58, 1), R(65, 3), R(75, 3),
R(15, 0), R(22, 5), R(33, 5),
R(28, 0), R(31, 0), R(41, 0),
R(42, 1), R(44, 0), R(53, 0),
R(4, 4), R(8, 5), R(16, 5),
R(12, 1), R(15, 0), R(22, 5),
R(26, 1), R(28, 0), R(31, 0),
R(50, 0), R(48, 0), R(49, 3),
R(32, 0), R(30, 3), R(33, 3),
R(24, 3), R(18, 3), R(16, 3),
R(70, 0), R(67, 0), R(66, 3),
R(52, 3), R(50, 0), R(48, 0),
R(37, 3), R(32, 0), R(30, 3),
R(83, 0), R(87, 3), R(85, 3),
R(74, 3), R(70, 0), R(67, 0),
R(57, 1), R(52, 3), R(50, 0),
R(25, 0), R(23, 0), R(24, 3),
R(17, 0), R(11, 3), R(10, 3),
R(14, 3), R(6, 3), R(2, 3),
R(45, 0), R(39, 0), R(37, 3),
R(35, 3), R(25, 0), R(23, 0),
R(27, 3), R(17, 0), R(11, 3),
R(63, 0), R(59, 3), R(57, 3),
R(56, 3), R(45, 0), R(39, 0),
R(46, 3), R(35, 3), R(25, 0),
R(36, 0), R(20, 0), R(14, 3),
R(34, 0), R(19, 3), R(9, 3),
R(38, 3), R(21, 3), R(7, 3),
R(55, 0), R(40, 0), R(27, 3),
R(54, 3), R(36, 0), R(20, 0),
R(51, 3), R(34, 0), R(19, 3),
R(72, 0), R(60, 3), R(46, 3),
R(73, 3), R(55, 0), R(40, 0),
R(71, 3), R(54, 3), R(36, 0),
R(64, 0), R(47, 0), R(38, 3),
R(62, 0), R(43, 3), R(29, 3),
R(58, 3), R(42, 3), R(26, 3),
R(84, 0), R(69, 0), R(51, 3),
R(82, 3), R(64, 0), R(47, 0),
R(76, 3), R(62, 0), R(43, 3),
R(97, 0), R(89, 3), R(71, 3),
R(98, 3), R(84, 0), R(69, 0),
R(96, 3), R(82, 3), R(64, 0),
R(75, 0), R(65, 0), R(58, 3),
R(61, 0), R(53, 3), R(44, 3),
R(49, 3), R(41, 3), R(31, 3),
R(94, 0), R(86, 0), R(76, 3),
R(81, 3), R(75, 0), R(65, 0),
R(66, 3), R(61, 0), R(53, 3),
R(107, 0), R(104, 3), R(96, 3),
R(101, 3), R(94, 0), R(86, 0),
R(85, 3), R(81, 3), R(75, 0),
R(57, 0), R(59, 0), R(63, 3),
R(74, 0), R(78, 3), R(79, 3),
R(83, 3), R(92, 3), R(95, 3),
R(37, 0), R(39, 3), R(45, 3),
R(52, 0), R(57, 0), R(59, 0),
R(70, 3), R(74, 0), R(78, 3),
R(24, 0), R(23, 3), R(25, 3),
R(32, 3), R(37, 0), R(39, 3),
R(50, 3), R(52, 0), R(57, 0),
R(46, 0), R(60, 0), R(72, 3),
R(56, 0), R(68, 3), R(80, 3),
R(63, 3), R(77, 3), R(90, 3),
R(27, 0), R(40, 3), R(55, 3),
R(35, 0), R(46, 0), R(60, 0),
R(45, 3), R(56, 0), R(68, 3),
R(14, 0), R(20, 3), R(36, 3),
R(17, 3), R(27, 0), R(40, 3),
R(25, 3), R(35, 0), R(46, 0),
R(71, 0), R(89, 0), R(97, 3),
R(73, 0), R(91, 3), R(103, 3),
R(72, 3), R(88, 3), R(105, 3),
R(51, 0), R(69, 3), R(84, 3),
R(54, 0), R(71, 0), R(89, 0),
R(55, 3), R(73, 0), R(91, 3),
R(38, 0), R(47, 3), R(64, 3),
R(34, 3), R(51, 0), R(69, 3),
R(36, 3), R(54, 0), R(71, 0),
R(96, 0), R(104, 0), R(107, 3),
R(98, 0), R(110, 3), R(115, 3),
R(97, 3), R(111, 3), R(119, 3),
R(76, 0), R(86, 3), R(94, 3),
R(82, 0), R(96, 0), R(104, 0),
R(84, 3), R(98, 0), R(110, 3),
R(58, 0), R(65, 3), R(75, 3),
R(62, 3), R(76, 0), R(86, 3),
R(64, 3), R(82, 0), R(96, 0),
R(85, 0), R(87, 0), R(83, 3),
R(101, 0), R(102, 3), R(100, 3),
R(107, 3), R(112, 3), R(114, 3),
R(66, 0), R(67, 3), R(70, 3),
R(81, 0), R(85, 0), R(87, 0),
R(94, 3), R(101, 0), R(102, 3),
R(49, 0), R(48, 3), R(50, 3),
R(61, 3), R(66, 0), R(67, 3),
R(75, 3), R(81, 0), R(85, 0),
R(95, 0), R(92, 0), R(83, 0),
R(79, 0), R(78, 0), R(74, 3),
R(63, 1), R(59, 3), R(57, 3),
R(109, 0), R(108, 0), R(100, 5),
R(93, 1), R(95, 0), R(92, 0),
R(77, 1), R(79, 0), R(78, 0),
R(117, 4), R(118, 5), R(114, 5),
R(106, 1), R(109, 0), R(108, 0),
R(90, 1), R(93, 1), R(95, 0),
R(90, 0), R(77, 0), R(63, 0),
R(80, 0), R(68, 0), R(56, 3),
R(72, 1), R(60, 3), R(46, 3),
R(106, 0), R(93, 0), R(79, 5),
R(99, 1), R(90, 0), R(77, 0),
R(88, 1), R(80, 0), R(68, 0),
R(117, 3), R(109, 5), R(95, 5),
R(113, 1), R(106, 0), R(93, 0),
R(105, 1), R(99, 1), R(90, 0),
R(105, 0), R(88, 0), R(72, 0),
R(103, 0), R(91, 0), R(73, 3),
R(97, 1), R(89, 3), R(71, 3),
R(113, 0), R(99, 0), R(80, 5),
R(116, 1), R(105, 0), R(88, 0),
R(111, 1), R(103, 0), R(91, 0),
R(117, 2), R(106, 5), R(90, 5),
R(121, 1), R(113, 0), R(99, 0),
R(119, 1), R(116, 1), R(105, 0),
R(119, 0), R(111, 0), R(97, 0),
R(115, 0), R(110, 0), R(98, 3),
R(107, 1), R(104, 3), R(96, 3),
R(121, 0), R(116, 0), R(103, 5),
R(120, 1), R(119, 0), R(111, 0),
R(112, 1), R(115, 0), R(110, 0),
R(117, 1), R(113, 5), R(105, 5),
R(118, 1), R(121, 0), R(116, 0),
R(114, 1), R(120, 1), R(119, 0),
R(114, 0), R(112, 0), R(107, 0),
R(100, 0), R(102, 0), R(101, 3),
R(83, 1), R(87, 3), R(85, 3),
R(118, 0), R(120, 0), R(115, 5),
R(108, 1), R(114, 0), R(112, 0),
R(92, 1), R(100, 0), R(102, 0),
R(117, 0), R(121, 5), R(119, 5),
R(109, 1), R(118, 0), R(120, 0),
R(95, 1), R(108, 1), R(114, 0)
);
const D baseCellData[NUM_BASE_CELLS] = D[NUM_BASE_CELLS](
D(FIJK(1, ivec3(1, 0, 0)), false, ivec2(0, 0)),
D(FIJK(2, ivec3(1, 1, 0)), false, ivec2(0, 0)),
D(FIJK(1, ivec3(0, 0, 0)), false, ivec2(0, 0)),
D(FIJK(2, ivec3(1, 0, 0)), false, ivec2(0, 0)),
D(FIJK(0, ivec3(2, 0, 0)), true, ivec2(-1, -1)),
D(FIJK(1, ivec3(1, 1, 0)), false, ivec2(0, 0)),
D(FIJK(1, ivec3(0, 0, 1)), false, ivec2(0, 0)),
D(FIJK(2, ivec3(0, 0, 0)), false, ivec2(0, 0)),
D(FIJK(0, ivec3(1, 0, 0)), false, ivec2(0, 0)),
D(FIJK(2, ivec3(0, 1, 0)), false, ivec2(0, 0)),
D(FIJK(1, ivec3(0, 1, 0)), false, ivec2(0, 0)),
D(FIJK(1, ivec3(0, 1, 1)), false, ivec2(0, 0)),
D(FIJK(3, ivec3(1, 0, 0)), false, ivec2(0, 0)),
D(FIJK(3, ivec3(1, 1, 0)), false, ivec2(0, 0)),
D(FIJK(11, ivec3(2, 0, 0)), true, ivec2(2, 6)),
D(FIJK(4, ivec3(1, 0, 0)), false, ivec2(0, 0)),
D(FIJK(0, ivec3(0, 0, 0)), false, ivec2(0, 0)),
D(FIJK(6, ivec3(0, 1, 0)), false, ivec2(0, 0)),
D(FIJK(0, ivec3(0, 0, 1)), false, ivec2(0, 0)),
D(FIJK(2, ivec3(0, 1, 1)), false, ivec2(0, 0)),
D(FIJK(7, ivec3(0, 0, 1)), false, ivec2(0, 0)),
D(FIJK(2, ivec3(0, 0, 1)), false, ivec2(0, 0)),
D(FIJK(0, ivec3(1, 1, 0)), false, ivec2(0, 0)),
D(FIJK(6, ivec3(0, 0, 1)), false, ivec2(0, 0)),
D(FIJK(10, ivec3(2, 0, 0)), true, ivec2(1, 5)),
D(FIJK(6, ivec3(0, 0, 0)), false, ivec2(0, 0)),
D(FIJK(3, ivec3(0, 0, 0)), false, ivec2(0, 0)),
D(FIJK(11, ivec3(1, 0, 0)), false, ivec2(0, 0)),
D(FIJK(4, ivec3(1, 1, 0)), false, ivec2(0, 0)),
D(FIJK(3, ivec3(0, 1, 0)), false, ivec2(0, 0)),
D(FIJK(0, ivec3(0, 1, 1)), false, ivec2(0, 0)),
D(FIJK(4, ivec3(0, 0, 0)), false, ivec2(0, 0)),
D(FIJK(5, ivec3(0, 1, 0)), false, ivec2(0, 0)),
D(FIJK(0, ivec3(0, 1, 0)), false, ivec2(0, 0)),
D(FIJK(7, ivec3(0, 1, 0)), false, ivec2(0, 0)),
D(FIJK(11, ivec3(1, 1, 0)), false, ivec2(0, 0)),
D(FIJK(7, ivec3(0, 0, 0)), false, ivec2(0, 0)),
D(FIJK(10, ivec3(1, 0, 0)), false, ivec2(0, 0)),
D(FIJK(12, ivec3(2, 0, 0)), true, ivec2(3, 7)),
D(FIJK(6, ivec3(1, 0, 1)), false, ivec2(0, 0)),
D(FIJK(7, ivec3(1, 0, 1)), false, ivec2(0, 0)),
D(FIJK(4, ivec3(0, 0, 1)), false, ivec2(0, 0)),
D(FIJK(3, ivec3(0, 0, 1)), false, ivec2(0, 0)),
D(FIJK(3, ivec3(0, 1, 1)), false, ivec2(0, 0)),
D(FIJK(4, ivec3(0, 1, 0)), false, ivec2(0, 0)),
D(FIJK(6, ivec3(1, 0, 0)), false, ivec2(0, 0)),
D(FIJK(11, ivec3(0, 0, 0)), false, ivec2(0, 0)),
D(FIJK(8, ivec3(0, 0, 1)), false, ivec2(0, 0)),
D(FIJK(5, ivec3(0, 0, 1)), false, ivec2(0, 0)),
D(FIJK(14, ivec3(2, 0, 0)), true, ivec2(0, 9)),
D(FIJK(5, ivec3(0, 0, 0)), false, ivec2(0, 0)),
D(FIJK(12, ivec3(1, 0, 0)), false, ivec2(0, 0)),
D(FIJK(10, ivec3(1, 1, 0)), false, ivec2(0, 0)),
D(FIJK(4, ivec3(0, 1, 1)), false, ivec2(0, 0)),
D(FIJK(12, ivec3(1, 1, 0)), false, ivec2(0, 0)),
D(FIJK(7, ivec3(1, 0, 0)), false, ivec2(0, 0)),
D(FIJK(11, ivec3(0, 1, 0)), false, ivec2(0, 0)),
D(FIJK(10, ivec3(0, 0, 0)), false, ivec2(0, 0)),
D(FIJK(13, ivec3(2, 0, 0)), true, ivec2(4, 8)),
D(FIJK(10, ivec3(0, 0, 1)), false, ivec2(0, 0)),
D(FIJK(11, ivec3(0, 0, 1)), false, ivec2(0, 0)),
D(FIJK(9, ivec3(0, 1, 0)), false, ivec2(0, 0)),
D(FIJK(8, ivec3(0, 1, 0)), false, ivec2(0, 0)),
D(FIJK(6, ivec3(2, 0, 0)), true, ivec2(11, 15)),
D(FIJK(8, ivec3(0, 0, 0)), false, ivec2(0, 0)),
D(FIJK(9, ivec3(0, 0, 1)), false, ivec2(0, 0)),
D(FIJK(14, ivec3(1, 0, 0)), false, ivec2(0, 0)),
D(FIJK(5, ivec3(1, 0, 1)), false, ivec2(0, 0)),
D(FIJK(16, ivec3(0, 1, 1)), false, ivec2(0, 0)),
D(FIJK(8, ivec3(1, 0, 1)), false, ivec2(0, 0)),
D(FIJK(5, ivec3(1, 0, 0)), false, ivec2(0, 0)),
D(FIJK(12, ivec3(0, 0, 0)), false, ivec2(0, 0)),
D(FIJK(7, ivec3(2, 0, 0)), true, ivec2(12, 16)),
D(FIJK(12, ivec3(0, 1, 0)), false, ivec2(0, 0)),
D(FIJK(10, ivec3(0, 1, 0)), false, ivec2(0, 0)),
D(FIJK(9, ivec3(0, 0, 0)), false, ivec2(0, 0)),
D(FIJK(13, ivec3(1, 0, 0)), false, ivec2(0, 0)),
D(FIJK(16, ivec3(0, 0, 1)), false, ivec2(0, 0)),
D(FIJK(15, ivec3(0, 1, 1)), false, ivec2(0, 0)),
D(FIJK(15, ivec3(0, 1, 0)), false, ivec2(0, 0)),
D(FIJK(16, ivec3(0, 1, 0)), false, ivec2(0, 0)),
D(FIJK(14, ivec3(1, 1, 0)), false, ivec2(0, 0)),
D(FIJK(13, ivec3(1, 1, 0)), false, ivec2(0, 0)),
D(FIJK(5, ivec3(2, 0, 0)), true, ivec2(10, 19)),
D(FIJK(8, ivec3(1, 0, 0)), false, ivec2(0, 0)),
D(FIJK(14, ivec3(0, 0, 0)), false, ivec2(0, 0)),
D(FIJK(9, ivec3(1, 0, 1)), false, ivec2(0, 0)),
D(FIJK(14, ivec3(0, 0, 1)), false, ivec2(0, 0)),
D(FIJK(17, ivec3(0, 0, 1)), false, ivec2(0, 0)),
D(FIJK(12, ivec3(0, 0, 1)), false, ivec2(0, 0)),
D(FIJK(16, ivec3(0, 0, 0)), false, ivec2(0, 0)),
D(FIJK(17, ivec3(0, 1, 1)), false, ivec2(0, 0)),
D(FIJK(15, ivec3(0, 0, 1)), false, ivec2(0, 0)),
D(FIJK(16, ivec3(1, 0, 1)), false, ivec2(0, 0)),
D(FIJK(9, ivec3(1, 0, 0)), false, ivec2(0, 0)),
D(FIJK(15, ivec3(0, 0, 0)), false, ivec2(0, 0)),
D(FIJK(13, ivec3(0, 0, 0)), false, ivec2(0, 0)),
D(FIJK(8, ivec3(2, 0, 0)), true, ivec2(13, 17)),
D(FIJK(13, ivec3(0, 1, 0)), false, ivec2(0, 0)),
D(FIJK(17, ivec3(1, 0, 1)), false, ivec2(0, 0)),
D(FIJK(19, ivec3(0, 1, 0)), false, ivec2(0, 0)),
D(FIJK(14, ivec3(0, 1, 0)), false, ivec2(0, 0)),
D(FIJK(19, ivec3(0, 1, 1)), false, ivec2(0, 0)),
D(FIJK(17, ivec3(0, 1, 0)), false, ivec2(0, 0)),
D(FIJK(13, ivec3(0, 0, 1)), false, ivec2(0, 0)),
D(FIJK(17, ivec3(0, 0, 0)), false, ivec2(0, 0)),
D(FIJK(16, ivec3(1, 0, 0)), false, ivec2(0, 0)),
D(FIJK(9, ivec3(2, 0, 0)), true, ivec2(14, 18)),
D(FIJK(15, ivec3(1, 0, 1)), false, ivec2(0, 0)),
D(FIJK(15, ivec3(1, 0, 0)), false, ivec2(0, 0)),
D(FIJK(18, ivec3(0, 1, 1)), false, ivec2(0, 0)),
D(FIJK(18, ivec3(0, 0, 1)), false, ivec2(0, 0)),
D(FIJK(19, ivec3(0, 0, 1)), false, ivec2(0, 0)),
D(FIJK(17, ivec3(1, 0, 0)), false, ivec2(0, 0)),
D(FIJK(19, ivec3(0, 0, 0)), false, ivec2(0, 0)),
D(FIJK(18, ivec3(0, 1, 0)), false, ivec2(0, 0)),
D(FIJK(18, ivec3(1, 0, 1)), false, ivec2(0, 0)),
D(FIJK(19, ivec3(2, 0, 0)), true, ivec2(-1, -1)),
D(FIJK(19, ivec3(1, 0, 0)), false, ivec2(0, 0)),
D(FIJK(18, ivec3(0, 0, 0)), false, ivec2(0, 0)),
D(FIJK(19, ivec3(1, 0, 1)), false, ivec2(0, 0)),
D(FIJK(18, ivec3(1, 0, 0)), false, ivec2(0, 0))
);
highp float pointSquareDist(in vec3 v1, in vec3 v2) {
vec3 delta = v1 - v2;
return dot(delta, delta);
}
void geoToVec3d(in vec2 g, out vec3 v) {
highp float r = cos(g.x);
v = vec3(
cos(g.y) * r,
sin(g.y) * r,
sin(g.x)
);
}
void geoToClosestFace(in vec2 g, out int face, out highp float sqd) {
vec3 v3d;
geoToVec3d(g, v3d);
face = 0;
sqd = 5.;
for (int f=0; f<NUM_ICOSA_FACES; ++f) {
highp float sqdT = pointSquareDist(FCP[f], v3d);
if (sqdT < sqd) {
face = f;
sqd = sqdT;
}
}
}
highp float posAngleRads(in float rads) {
float tmp = (rads < 0.) ? rads + 2. * PI : rads;
if (rads >= 2. * PI) tmp -= 2. * PI;
return tmp;
}
highp float geoAzimuthRads(in vec2 p1, in vec2 p2) {
return atan(
cos(p2.x) * sin(p2.y - p1.y),
cos(p1.x) * sin(p2.x) -
sin(p1.x) * cos(p2.x) * cos(p2.y - p1.y)
);
}
void geoToHex2d(in vec2 g, in int res, out int face, out vec2 v) {
highp float sqd;
geoToClosestFace(g, face, sqd);
highp float r = acos(1. - sqd / 2.);
if (r < EPSILON) {
v = vec2(0.);
return;
}
highp float theta = posAngleRads(
FARC[face][0] -
posAngleRads(
geoAzimuthRads(FCG[face], g)
)
);
if (mod(res, 2) == 1)
theta = posAngleRads(theta - M_AP7_ROT_RADS);
r = tan(r);
r /= RES0_U_GNOMONIC;
for (int i=0; i<res; ++i) r *= M_SQRT7;
v = vec2(
r * cos(theta),
r * sin(theta)
);
}
void ijkNormalize(inout ivec3 c) {
if (c.x < 0) {
c.y -= c.x;
c.z -= c.x;
c.x = 0;
}
if (c.y < 0) {
c.x -= c.y;
c.z -= c.y;
c.y = 0;
}
if (c.z < 0) {
c.x -= c.z;
c.y -= c.z;
c.z = 0;
}
int m = int(min(c.x, int(min(c.y, c.z))));
if (m > 0) {
c -= ivec3(m);
}
}
void hex2dToCoordIJK(in vec2 v, out ivec3 h) {
highp float a1, a2;
highp float x1, x2;
int m1, m2;
highp float r1, r2;
h.z = 0;
a1 = abs(v.x);
a2 = abs(v.y);
x2 = a2 / M_SIN60;
x1 = a1 + x2 / 2.;
m1 = int(x1);
m2 = int(x2);
r1 = x1 - float(m1);
r2 = x2 - float(m2);
if (r1 < 0.5) {
if (r1 < 1. / 3.) {
if (r2 < (1. + r1) / 2.) {
h.x = m1;
h.y = m2;
} else {
h.x = m1;
h.y = m2 + 1;
}
} else {
if (r2 < (1. - r1)) {
h.y = m2;
} else {
h.y = m2 + 1;
}
if ((1. - r1) <= r2 && r2 < (2. * r1)) {
h.x = m1 + 1;
} else {
h.x = m1;
}
}
} else {
if (r1 < 2. / 3.) {
if (r2 < (1. - r1)) {
h.y = m2;
} else {
h.y = m2 + 1;
}
if ((2. * r1 - 1.) < r2 && r2 < (1. - r1)) {
h.x = m1;
} else {
h.x = m1 + 1;
}
} else {
if (r2 < (r1 / 2.)) {
h.x = m1 + 1;
h.y = m2;
} else {
h.x = m1 + 1;
h.y = m2 + 1;
}
}
}
if (v.x < 0.) {
if (mod(h.y, 2) == 0) {
int axisi = h.y / 2;
int diff = h.x - axisi;
h.x = h.x - 2 * diff;
} else {
int axisi = (h.y + 1) / 2;
int diff = h.x - axisi;
h.x = h.x - (2 * diff + 1);
}
}
if (v.y < 0.) {
h.x = h.x - (2 * h.y + 1) / 2;
h.y = -1 * h.y;
}
ijkNormalize(h);
}
void upAp7(inout ivec3 ijk) {
int i = ijk.x - ijk.z;
int j = ijk.y - ijk.z;
ijk = ivec3(
int(floor(float(3 * i - j) / 7. + 0.5)),
int(floor(float(i + 2 * j) / 7. + 0.5)),
0
);
ijkNormalize(ijk);
}
void upAp7r(inout ivec3 ijk) {
int i = ijk.x - ijk.z;
int j = ijk.y - ijk.z;
ijk = ivec3(
int(floor(float(2 * i + j) / 7. + 0.5)),
int(floor(float(3 * j - i) / 7. + 0.5)),
0
);
ijkNormalize(ijk);
}
void downAp7(inout ivec3 ijk) {
ivec3 iVec = ivec3(3, 0, 1);
ivec3 jVec = ivec3(1, 3, 0);
ivec3 kVec = ivec3(0, 1, 3);
iVec *= ijk.x;
jVec *= ijk.y;
kVec *= ijk.z;
ijk = iVec + jVec + kVec;
ijkNormalize(ijk);
}
void downAp7r(inout ivec3 ijk) {
ivec3 iVec = ivec3(3, 1, 0);
ivec3 jVec = ivec3(0, 3, 1);
ivec3 kVec = ivec3(1, 0, 3);
iVec *= ijk.x;
jVec *= ijk.y;
kVec *= ijk.z;
ijk = iVec + jVec + kVec;
ijkNormalize(ijk);
}
int unitIjkToDigit(in ivec3 ijk) {
ivec3 c = ijk;
ijkNormalize(c);
int digit = -1;
for (int i=0; i<7; ++i) {
if (c == UV[i]) {
digit = i;
break;
}
}
return digit;
}
int h3LeadingNonZeroDigit(in CellIndex h) {
for (int r=0; r<h.resolution; ++r) {
if (h.digits[r] > 0) return h.digits[r];
}
return 0;
}
void h3Rotate60ccw(inout CellIndex h) {
for (int r=0; r<h.resolution; ++r) {
h.digits[r] = R60CCW[ h.digits[r] ];
}
}
void h3Rotate60cw(inout CellIndex h) {
for (int r=0; r<h.resolution; ++r) {
h.digits[r] = R60CW[ h.digits[r] ];
}
}
bool baseCellIsCwOffset(in int baseCell, in int testFace) {
return baseCellData[baseCell].cwOffsetPent.x == testFace ||
baseCellData[baseCell].cwOffsetPent.y == testFace;
}
void geoToFaceIjk(in vec2 g, in int res, out FIJK h) {
vec2 v;
geoToHex2d(g, res, h.face, v);
hex2dToCoordIJK(v, h.coord);
}
CellIndex faceIjkToCellIndex(in FIJK fijk, in int res) {
CellIndex result = CellIndex(
res,
0,
int[NUM_DIGITS](0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
);
if (res == 0) {
result.baseCell = FIBC[
fijk.face * 27 +
fijk.coord.x * 9 +
fijk.coord.y * 3 +
fijk.coord.z
].baseCell;
return result;
}
FIJK fijkBC = fijk;
ivec3 ijk = fijkBC.coord;
for (int r=res-1; r >= 0; --r) {
ivec3 lastIJK = ijk;
ivec3 lastCenter;
if (mod(r + 1, 2) == 1) {
upAp7(ijk);
lastCenter = ijk;
downAp7(lastCenter);
} else {
upAp7r(ijk);
lastCenter = ijk;
downAp7r(lastCenter);
}
ivec3 diff = lastIJK - lastCenter;
ijkNormalize(diff);
result.digits[r] = unitIjkToDigit(diff);
}
fijkBC.coord = ijk;
R baseCellRotation = FIBC[
fijkBC.face * 27 +
fijkBC.coord.x * 9 +
fijkBC.coord.y * 3 +
fijkBC.coord.z
];
int baseCell = baseCellRotation.baseCell;
int numRots = baseCellRotation.ccwRot60;
result.baseCell = baseCell;
if (baseCellData[baseCell].isPentagon) {
if (h3LeadingNonZeroDigit(result) == K_AXES_DIGIT) {
if(baseCellIsCwOffset(baseCell, fijkBC.face)) {
h3Rotate60cw(result);
} else {
h3Rotate60ccw(result);
}
}
} else {
for (int i=0; i<numRots; ++i) {
h3Rotate60ccw(result);
}
}
return result;
}
CellIndex latLngToCellIndex(in vec2 g, in int res) {
FIJK fijk;
geoToFaceIjk(g, res, fijk);
return faceIjkToCellIndex(fijk, res);
}
const int LUT_WIDTH = 2048;
const int LUT_HEIGHTS[6] = int[6](1, 1, 3, 21, 141, 985);
vec4 sampleCellValue(in sampler2D s2D, in CellIndex c) {
ivec2 dims = textureSize2D(s2D, 0);
if (c.resolution > 5) return vec4(0);
int idx = 0;
int mult = 1;
for (int i=c.resolution-1; i>=0; --i) {
idx += c.digits[i] * mult;
mult *= 7;
}
idx += c.baseCell * mult;
int xCoord = idx % dims.x;
int yCoord = idx / dims.x;
return texelFetch2D(s2D, ivec2(xCoord, yCoord), 0);
}
int texelToIdx(in vec4 t) {
return
((int(t.b * 255) << 8) | int(t.a * 255)) * 2048 +
((int(t.r * 255) << 8) | int(t.g * 255));
}
vec4 sampleCellValueDense(in sampler2D s2D, in CellIndex c) {
int idx = texelToIdx(texelFetch2D(s2D, ivec2(
c.baseCell,
0.
), 0));
if (idx == 0) return vec4(0);
for (int r=0; r<c.resolution-1; ++r) {
idx += c.digits[r];
int x = idx % 2048;
int y = idx / 2048;
idx = texelToIdx(texelFetch2D(s2D, ivec2(x, y), 0));
if (idx == 0) return vec4(0);
}
idx += c.digits[c.resolution-1];
return texelFetch2D(s2D, ivec2(idx % 2048, idx / 2048), 0);
}
uniform sampler2D map_tu0;
uniform sampler2D map_tu1;
uniform highp float zoom;
varying vec2 texco;
void main() {
vec2 g = vec2(
(1 - texco.y) * PI - 0.5 * PI,
(1 - texco.x) * PI2 - PI
);
vec4 tex = texture2D(map_tu0, vec2(1 - texco.x, texco.y));
int resolution = 8;
CellIndex cell = latLngToCellIndex(g, resolution);
vec4 hCol = sampleCellValueDense(map_tu1, cell);
gl_FragColor = vec4(tex.rgb * (1 - hCol.a) + hCol.rgb * hCol.a, 1.);
}
]]
function shader.get()
local s = build_shader(v, fragment_shader, "geopoints")
return s
end
function geopointvis()
shader = shader.get()
shader_uniform(shader, "zoom", "f", 0)
sphere = build_sphere(5, 40, 40, 2)
image_framesetsize(sphere, 2, FRAMESET_MULTITEXTURE)
show_image(sphere)
image_shader(sphere, shader)
local img = load_image("./earthmap10k.jpg")
set_image_as_frame(sphere, img, 0)
delete_image(img)
local data_tex = load_image("./h3_res8_dense.png")
image_texfilter(data_tex, FILTER_NONE)
set_image_as_frame(sphere, data_tex, 1)
delete_image(data_tex)
image_color(WORLDID, 50, 50, 50, 0)
camera.vid = null_surface(1, 1)
move3d_model(camera.vid, 0, 0, -10.0)
camera:rebuild()
end
function geopointvis_clock_pulse(tick)
local t = tick/CLOCKRATE
if camera.fovDirty then
camera:rebuild()
end
rotate3d_model(sphere, 0, camera.pitch, camera.yaw, 1/CLOCKRATE)
end
function geopointvis_input(input)
if input.kind == "analog" then
if mouse.devid and mouse.devid ~= input.devid then
return
end
local sample = input.samples[1]
if not mouse.buttons[1] and not mouse.buttons[2] then
mouse.lastSample[input.subid] = sample
return
end
local delta
if input.relative then
delta = sample
else
delta = sample - mouse.lastSample[input.subid]
end
mouse.lastSample[input.subid] = sample
if mouse.buttons[1] then
local panSpeed = mouseSpeed * (
0.001 + 0.999*(camera.fov - minFov)/(maxFov - minFov)
)
if input.subid == 0 then
camera.yaw = (
camera.yaw + delta * panSpeed
) % 360
elseif input.subid == 1 then
camera.pitch = math.max(
minPitch,
math.min(
maxPitch,
camera.pitch + delta * panSpeed
)
)
end
elseif mouse.buttons[2] then
if input.subid == 1 then
local zoomSpeed = mouseSpeed * (0.1 + 0.9*(camera.fov - minFov)/(maxFov - minFov))
camera.fov = math.max(
minFov,
math.min(
maxFov,
camera.fov + delta * zoomSpeed
)
)
camera.fovDirty = true
shader_uniform(shader, "zoom", "f", 1 - (camera.fov - minFov)/(maxFov - minFov))
end
end
elseif input.kind == "touch" then
if touchscreen.devid == nil then
touchscreen.devid = input.devid
elseif touchscreen.devid ~= input.devid then
return
end
-- Recount on finger addition or removal
local alreadyDetected = touchscreen.touches[input.subid] ~= nil
if alreadyDetected ~= input.active then
touchscreen.nTouches = input.active and 1 or 0
for _,_ in pairs(touchscreen.touches) do
touchscreen.nTouches = touchscreen.nTouches + 1
end
end
if not input.active then
touchscreen.touches[input.subid] = nil
touchscreen.nTouches = touchscreen.nTouches - 1
if touchscreen.nTouches < 2 then
touchscreen.lastDist = nil
end
return
end
local touch = touchscreen.touches[input.subid]
if touchscreen.nTouches == 1 and touch then
local deltaX = input.x - touch[1]
local deltaY = input.y - touch[2]
local panSpeed = touchSpeed * (
0.001 + 0.999*(camera.fov - minFov)/(maxFov - minFov)
)
camera.yaw = (
camera.yaw + deltaX * panSpeed
) % 360
camera.pitch = math.max(
minPitch,
math.min(
maxPitch,
camera.pitch + deltaY * panSpeed
)
)
elseif touchscreen.nTouches == 2 and touch then
local delta = input.y - touch[2]
local zoomSpeed = touchSpeed * (0.1 + 0.9*(camera.fov - minFov)/(maxFov - minFov))
camera.fov = math.max(
minFov,
math.min(
maxFov,
camera.fov - delta * zoomSpeed
)
)
camera.fovDirty = true
shader_uniform(shader, "zoom", "f", 1 - (camera.fov - minFov)/(maxFov - minFov))
end
touchscreen.touches[input.subid] = {input.x, input.y}
elseif input.kind == "digital" then
if input.mouse then
if input.active then
mouse.devid = input.devid
elseif mouse.devid == input.devid then
mouse.devid = nil
else
return
end
mouse.buttons[input.subid] = input.active
elseif input.keyboard then
if input.keysym == 27 then
shutdown()
end
end
end
end
function geopointvis_display_state(disp)
if disp == "reset" then
resize_video_canvas(VRESW, VRESH)
camera:rebuild()
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment