{"id":19742868,"url":"https://github.com/raub/geogen-raub","last_synced_at":"2026-05-16T07:35:54.232Z","repository":{"id":57249814,"uuid":"186802532","full_name":"raub/geogen-raub","owner":"raub","description":"Planetary geometry generator","archived":false,"fork":false,"pushed_at":"2019-06-27T08:24:30.000Z","size":136,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-12T10:06:36.415Z","etag":null,"topics":["3d","generator","geometry","gl","graphics","heightmap","javascript","js","node-3d","planet","webgl"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/raub.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-05-15T10:18:22.000Z","updated_at":"2022-06-07T15:06:23.000Z","dependencies_parsed_at":"2022-08-24T16:51:41.075Z","dependency_job_id":null,"html_url":"https://github.com/raub/geogen-raub","commit_stats":null,"previous_names":["node-3d/geogen-raub"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raub%2Fgeogen-raub","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raub%2Fgeogen-raub/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raub%2Fgeogen-raub/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raub%2Fgeogen-raub/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/raub","download_url":"https://codeload.github.com/raub/geogen-raub/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241072770,"owners_count":19904836,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["3d","generator","geometry","gl","graphics","heightmap","javascript","js","node-3d","planet","webgl"],"created_at":"2024-11-12T01:34:11.208Z","updated_at":"2026-05-16T07:35:54.184Z","avatar_url":"https://github.com/raub.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Geogen\n\nThis is a part of [Node3D](https://github.com/node-3d) project.\n\n![NPM](https://nodei.co/npm/geogen-raub.png?compact=true)\n\n![Build Status](https://travis-ci.com/node-3d/geogen-raub.svg?branch=master)\n\n\u003e npm i -s geogen-raub\n\n[Live DEMO](http://gsom.tech/geogen).\n\n\n## Synopsis\n\nFunction `geogen()` is exported (as `module.exports` or `window.geogen`).\nThis is a planetary geometry generator. It generates a dynamic LOD chunked\nsphere with vertices displaced according to the values of the `heightmap`.\nThe output is in form of raw number values, so it can be used with any\ngraphical library.\n\n![Example](example.png)\n\n\n## Function `geogen()`\n\nThe idea is to generate a cube, and then normalize each of the vertices, resulting\nin a spheric geometry. Regarding the LODs, the approach is to subdivide any chunk\ninto 4 equal pieces as soon as the LOD distance is reached.\n\nAs the geometry is indexed and each chunk has the same setup, the same index buffer\ncan be reused throughout all the chunks (being built only once).\nThe time required for generation of chunks is also reduced by that fact.\n\nAll the chunks have so called skirts. That is an additional geometry underneath\nthe surface, designed to hide any LODding seams. So the geometry is ready for use.\n\nThe texture coordinates are in planetary scale, [0; 1] for each side. However the\ndirections are a bit tricky, and probably require some experimenting and additional\ndocs. This snippet can probably help with texture generation, for now:\n\n```\nvec2 xy = varUv * (1024.0 + 1.0) - (512.0 + 0.5);\nvec3 coords;\nif (index == 0) {\n\tcoords = vec3(1024.0, -xy.y, xy.x);\n} else if (index == 1) {\n\tcoords = vec3(-1024.0, -xy.y, -xy.x);\n} else if (index == 2) {\n\tcoords = vec3(xy.x, 1024.0, -xy.y);\n} else if (index == 3) {\n\tcoords = vec3(-xy.x, -1024.0, -xy.y);\n} else if (index == 4) {\n\tcoords = vec3(-xy.y, xy.x, 1024.0);\n} else if (index == 5) {\n\tcoords = vec3(-xy.y, -xy.x, -1024.0);\n}\n```\n\nHere `index` is the side of the initial cube, as follows: [x, -x, y, -y, z, -z].\n\n\n### Args:\n\n```js\n{\n\tradius: number = 500,\n\theight: number = 100 / 255,\n\tthresholds: [number] = [1300, 900, 700, 400, 200], // any length\n\tresolution: number = 16, // int\n\theightmaps: [{\n\t\tresolution: number = 1,\n\t\tdata: TypedArray = Uint8Array.from([0]),\n\t\tat: number = 0,\n\t\tstep: number = 4,\n\t}], // 6 pieces\n\tonGeometry: GEOCALLBACK,\n\tculling: bool = false,\n}\n```\n\n* `radius` - base size of the sphere.\n* `height` - heightmap scale, here `/255` means normalising from `Uint8` [0; 255] range.\n* `thresholds` - a set of LOD distances.\n* `resolution` - the number of quads in a chunk (per side).\n* `heightmaps` - 6 heightmaps for each side of the sphere.\n* `onGeometry` - a callback to be called for each generated chunk, as described below.\n* `culling` - whether to cull the chunks on the back of the sphere.\n\n\n### Returns:\n\n```js\n{\n\tupdate: () =\u003e {},\n}\n```\n\n* `update` - has to be called in order to recalculate the LOD.\nIt can be called each frame or periodically.\nHowever, the more often it is called the less changes\nit has to manage, hence lower the latency.\n\n\n## Function `GEOCALLBACK`:\n\nThis user function is responsible for interaction with the generator.\nThe generator would call it each time a new chunk is created.\n\nThe function receives all the generated buffers along with the side index and\nthe chunk center initial position. This initial position can be used to later\ncalculate the world-space chunk position required for LOD update.\n\nThe function is expected to return several callbacks, that will be called during\nthe LOD update. The LOD controller will need the actual information about the camera\nposition, the chunk position and the position of the whole planet. The LOD\ncontroller will at some point decide to switch the visibility of a chunk ON or\nOFF, and expects the respective callback to do so.\n\n### Args:\n\n```js\n{\n\tindices: Uint16Array,\n\tvertices: Float32Array,\n\tnormals: Float32Array,\n\tuvs: Float32Array,\n\tindex: number, // 0 1 2 3 4 5 - cube-side index\n\tcenter: [number, number, number], // vec3\n}\n```\n\n* `indices` - index buffer.\n* `vertices` - vertex buffer.\n* `normals` - normal buffer.\n* `uvs` - texture coordinates buffer.\n* `index` - the side of the initial cube, as follows: [x, -x, y, -y, z, -z].\n* `center` - 3D position of the center of the chunk.\n\n### Returns:\n\n```js\n{\n\tgetChunkPos: () =\u003e [number, number, number],\n\tgetPlanetPos: () =\u003e [number, number, number],\n\tgetCameraPos: () =\u003e [number, number, number],\n\tsetVisible: v =\u003e {},\n}\n```\n\n* `getChunkPos` - get the current world position of the chunk.\n* `getPlanetPos` - get the current world position of the planet.\n* `getCameraPos` - get the current world position of the camera.\n* `setVisible` - show/hide the chunk.\n\nIt is important to understand those are the functions you provide into the generator,\nso it can do a good job. If those functions are setup incorrectly, it won't work\nas expected.\n\nHere is an example of such a set of callbacks:\n\n```js\nreturn {\n\tgetChunkPos : () =\u003e {\n\t\tconst v3 = anchor.getWorldPosition(new THREE.Vector3());\n\t\treturn [v3.x, v3.y, v3.z];\n\t},\n\tgetPlanetPos : () =\u003e {\n\t\tconst v3 = planet.position;\n\t\treturn [v3.x, v3.y, v3.z];\n\t},\n\tgetCameraPos : () =\u003e {\n\t\tconst v3 = camera.position;\n\t\treturn [v3.x, v3.y, v3.z];\n\t},\n\tsetVisible: v =\u003e {\n\t\tsurface.visible = v;\n\t},\n};\n```\n\nIn this example:\n\n* `anchor` - a THREE.Object3D earlier created at the `center` position.\n* `planet` - a THREE.Object3D representing the whole planet.\n* `camera` - a THREE.js camera.\n* `surface` - a THREE.Object3D representing this chunk.\n\nYou don't have to nest chunk objects to enforce hierarchical invisibility.\nNor that you could guess their nesting by the plain geometry values.\nThe generator does that implicitly and takes care of it.\n\n---\n\nA working integration of this generator can be found on the\n[Live DEMO](http://gsom.tech/geogen) website. The heightmap here is generated\nwith the help of [Texgen](https://github.com/node-3d/texgen-raub). The source\nof the demo is not obfuscated in any way so it can also be used as a reference.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fraub%2Fgeogen-raub","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fraub%2Fgeogen-raub","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fraub%2Fgeogen-raub/lists"}