import { vec2 , vec3 } from 'gl-matrix' ; import { v3 } from '../gl-matrix-extensions' ; type ivec3 = [ number , number , number ] ; /**
 * Helper class to generate a sphere geometry based on a refinable icosahedron
 */ export class Icosahedron { see faces protected _faces : Array < ivec3 > ; see vertices protected _vertices : Array < vec3 > ; see texcoords protected _texcoords : Array < vec2 > ; /**
     * Object constructor.
     */ constructor ( ) { } /**
     * Returns the base vertices for the icosahedron.
     */ protected baseVertices ( ) { const t = ( 1.0 + Math . sqrt ( 5.0 ) ) * 0.5 ; const i = 1.0 / Math . sqrt ( t * t + 1.0 ) ; const a = t * i ; const vertices = [ vec3 . fromValues ( - i , + a , 0 ) , vec3 . fromValues ( + i , + a , 0 ) , vec3 . fromValues ( - i , - a , 0 ) , vec3 . fromValues ( + i , - a , 0 ) , vec3 . fromValues ( 0 , - i , + a ) , vec3 . fromValues ( 0 , + i , + a ) , vec3 . fromValues ( 0 , - i , - a ) , vec3 . fromValues ( 0 , + i , - a ) , vec3 . fromValues ( + a , 0 , - i ) , vec3 . fromValues ( + a , 0 , + i ) , vec3 . fromValues ( - a , 0 , - i ) , vec3 . fromValues ( - a , 0 , + i ) , ] ; return vertices ; } /**
     * Returns the base faces for the icosahedron.
     */ protected baseFaces ( ) { const faces = [ [ 0 , 11 , 5 ] , [ 0 , 5 , 1 ] , [ 0 , 1 , 7 ] , [ 0 , 7 , 10 ] , [ 0 , 10 , 11 ] , [ 1 , 5 , 9 ] , [ 5 , 11 , 4 ] , [ 11 , 10 , 2 ] , [ 10 , 7 , 6 ] , [ 7 , 1 , 8 ] , [ 3 , 9 , 4 ] , [ 3 , 4 , 2 ] , [ 3 , 2 , 6 ] , [ 3 , 6 , 8 ] , [ 3 , 8 , 9 ] , [ 4 , 9 , 5 ] , [ 2 , 4 , 11 ] , [ 6 , 2 , 10 ] , [ 8 , 6 , 7 ] , [ 9 , 8 , 1 ] , ] ; return faces ; } param vertices param faces param levels protected refine ( vertices , faces , levels ) { const cache = new Map < number , number > ( ) ; for ( let i = 0 ; i < levels ; i ++ ) { const size = faces . length ; for ( let f = 0 ; f < size ; f ++ ) { const face = faces [ f ] ; const a = face [ 0 ] ; const b = face [ 1 ] ; const c = face [ 2 ] ; const ab = this . split ( a , b , vertices , cache ) ; const bc = this . split ( b , c , vertices , cache ) ; const ca = this . split ( c , a , vertices , cache ) ; faces [ f ] = [ ab , bc , ca ] ; faces . push ( [ a , ab , ca ] ) ; faces . push ( [ b , bc , ab ] ) ; faces . push ( [ c , ca , bc ] ) ; } } } param a param b param vertices param cache protected split ( a , b , vertices , cache ) { const aSmaller = ( a < b ) ; const smaller = aSmaller ? a : b ; const greater = aSmaller ? b : a ; const hash = ( smaller << 16 ) + greater ; if ( cache . has ( hash ) ) { return cache . get ( hash ) ! ; } const pos = vec3 . add ( v3 ( ) , vertices [ a ] , vertices [ b ] ) ; vec3 . normalize ( pos , pos ) ; vertices . push ( pos ) ; const index = vertices . length - 1 ; cache . set ( hash , index ) ; return index ; } param levels generateGeometry ( levels ) { this . _vertices = this . baseVertices ( ) ; this . _faces = this . baseFaces ( ) ; if ( levels > 0 ) { this . refine ( this . _vertices , this . _faces , Math . min ( Math . max ( levels , 0 ) , 8 ) ) ; } } /**
     * Generates texture coordinates for the icosahedron.
     */ generateTextureCoordinates ( ) { this . _texcoords = new Array < vec2 > ( ) ; const ofs = 0.5 ; for ( const pos of this . _vertices ) { const normal = vec3 . normalize ( v3 ( ) , pos ) ; const uv = vec2 . fromValues ( ofs - ( Math . atan2 ( normal [ 2 ] , normal [ 0 ] ) / ( 2.0 * Math . PI ) ) , Math . asin ( normal [ 1 ] ) / Math . PI + ofs ) ; this . _texcoords . push ( uv ) ; } } /**
     * Read-only access to the faces of the icosahedron.
     */ get faces ( ) : Array < ivec3 > { return this . _faces ; } /**
     * Read-only access to the vertices of the icosahedron.
     */ get vertices ( ) : Array < vec3 > { return this . _vertices ; } /**
     * Read-only access to the texture coordinates of the icosahedron.
     */ get texcoords ( ) : Array < vec2 > { return this . _texcoords ; } }