{"id":22704304,"url":"https://github.com/quantum9innovation/sost","last_synced_at":"2025-04-13T09:44:47.205Z","repository":{"id":47681340,"uuid":"499696052","full_name":"quantum9Innovation/sost","owner":"quantum9Innovation","description":"Like the canvas, but in three dimensions","archived":false,"fork":false,"pushed_at":"2025-02-16T02:09:42.000Z","size":499,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-27T01:11:53.346Z","etag":null,"topics":["3d","3d-graphics","3d-graphing-calculator","canvas","canvas-3d","graphing-calculator","web"],"latest_commit_sha":null,"homepage":"https://quantum9innovation.github.io/sost/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/quantum9Innovation.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-06-04T01:35:46.000Z","updated_at":"2025-02-16T02:09:43.000Z","dependencies_parsed_at":"2024-04-17T01:46:51.448Z","dependency_job_id":"3999eac2-5aa5-40d0-a607-886a962da572","html_url":"https://github.com/quantum9Innovation/sost","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quantum9Innovation%2Fsost","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quantum9Innovation%2Fsost/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quantum9Innovation%2Fsost/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quantum9Innovation%2Fsost/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/quantum9Innovation","download_url":"https://codeload.github.com/quantum9Innovation/sost/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248694178,"owners_count":21146945,"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","3d-graphics","3d-graphing-calculator","canvas","canvas-3d","graphing-calculator","web"],"created_at":"2024-12-10T08:15:06.614Z","updated_at":"2025-04-13T09:44:47.177Z","avatar_url":"https://github.com/quantum9Innovation.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Sost\n\n\u003e IPA: /sost/, from Amharic: ሶስት \"three\"\n\nLike the canvas, but in three dimensions\n\n---\n\nAs of right now, Sost is still very much in the alpha stage of development.\nYou can track what needs to be done and what's getting done in the [todos](./TODOS.md).\nThis README will likely be updated as the project progresses to feature the latest developments.\n\n## Building\n\nThis project, due to its alpha status, has not yet been pushed to the npm registry, so you'll need to build it from the source.\nUnfortunately, there is no complete documentation for the package as internal structure is still rapidly changing.\nHowever, the guide presented [here](#guide) documents most of the common functions.\n\nTo start, clone the repo and install the required dependencies:\n\n```sh\ngit clone https://github.com/quantum9innovation/sost\ncd sost; yarn install\n```\n\nIf you plan on using Sost in native Node.js as opposed to in the browser, you'll need to install [`canvas`](https://www.npmjs.com/package/canvas) to create the initial 2D rendering context.\n\nSost is designed to work both in a native Node.js environment (through the [`canvas`](https://www.npmjs.com/package/canvas) package) and in a browser environment (using Browserify and Terser).\nTo see some examples of Sost running in Node.js, simply run `yarn test` from the project root directory and check [artifacts](./artifacts/) for the results.\nFor a web demonstration, serve the project root directory (`npx live-server` will work fine) and launch [index.html](./index.html) in the browser (drag to rotate the view).\n\n## Screenshots\n\nIf the tests work, you should see an image like the one below appear in the [artifacts](./artifacts/) directory.\n\n![](./artifacts/base.png)\n\n**Above**:\n\u003e The x, y, and z axes are displayed as red, blue, and green lines, respectively. In the center lies a white point demarcating the origin. The three planes intersecting that point trace out part of the xy, xz, and yz planes.\n\n## Guide\n\nAs the majority of time is being spent on development, this guide is quite brief and focused on the core functionality.\nMore details will be provided when formal documentation is available.\n\nThe first thing to do is to generate a 2D canvas. Even though Sost initializes its own canvas, it requires a base canvas to project the 3D objects onto. Sost works with both the [`canvas`](https://www.npmjs.com/package/canvas) package in Node.js and an actual HTML5 canvas.\n\nIf you're using a browser, you'll need to load the browser-ready version of Sost from [`dist/sost.min.js`](./dist/sost.min.js), which is generated by `yarn build`.\n\nNow, create the canvas and get its 2D rendering context to be passed into Sost:\n\n```js\nconst canvas = ...\nconst ctx = canvas.getContext('2d')\n```\n\nIn Sost, the canvas initializer is a function that takes a canvas context and three dimensional variables.\nAt this point, it's important to briefly outline the three main \"spaces\" in which Sost operates.\nThe first and most basic of which is the pixel space, which deals with actual 2D coordinates on the `ctx` variable.\nThe second is known as \"point space,\" because it is a user-defined 3D space, which Sost uses to project objects onto 2D pixel space.\nPoint space is defined by three dimensions: width, height, and depth, which in turn tells Sost how to scale the objects it draws in 3D space onto the 2D canvas.\nThe middle of the canvas represents the origin of the point space, which is the point $(0, 0, 0)$.\n\nAt this point you may be wondering what the third space is.\nThe third space is essentially the same as point space, except that it can be scaled and rotated in three dimensions.\nThis space is known as the Cartesian space.\nIn essence, every point that you tell Sost to draw in Cartesian space goes through two transformations before it is eventually drawn onto the Canvas. The first transformation transforms Cartesian space into point space, and the second transforms point space to pixel space.\nPoint space, in this sense, acts as a static intermediary between Cartesian and pixel space.\nObjects drawn in point space won't rotate, scale, or otherwise change while those in Cartesian space will.\nMost high-level objects in Sost are drawn in Cartesian space, while lower-level, more primitive objects are drawn in point space.\nBy default, point space has a scaling factor of 1, making it the same size as Cartesian space without any zoom applied, and a perspective such that rays from a viewer are perpendicular to the XZ plane.\n\nTo create a 3D canvas, we need to use the `Canvas3D` method and pass in the dimensions of our point space in the order of width (x), height (z), and depth (y).\nFor example, if we wanted to create a canvas defined by a cube with side length 2 centered at the origin, we would use:\n\n```js\nconst three = new sost.Canvas3D(ctx, 2, 2, 2)\n```\n\nThe eight corners of this cube are given by the vertices $(\\pm 1, \\pm 1, \\pm 1)$, with the center at the origin $(0, 0, 0)$.\n\nWe can set an initial perspective for our Cartesian space by accessing the built-in Camera object.\nPerspectives are passed in as an array of two angles, the first representing rotation over the xy plane ($\\theta$) and the second representing rotation over the yz plane ($\\phi$).\nScaling can be adjusted as well by accessing the `zoom` property.\nTranslating the origin can be achieved by setting the `center` property to the new origin coordinates.\n\nLet's set a perspective of $(\\theta, \\phi) = (\\frac{\\pi}{4}, \\frac{\\pi}{4} )$.\n\n```js\nthree.Camera.angle = [Math.PI / 4, Math.PI / 4]\n```\n\nSost currently supports three types of objects: points, lines, and polygons.\nPoints are drawn as a circle centered at the point's coordinates with a radius equal to `three.pointSize` and color `three.pointStyle`.\nLines are drawn between a pair of provided coordinates with thickness `three.lineWidth` and color `three.strokeStyle`.\nPolygons are drawn between three or more coordinates with color `three.fillStyle`.\nStroke/fill modes can be selectively enabled or disabled for polygons by switching the `three.fill` and `three.stroke` properties.\n\nLet's start by drawing the three axes of our point space.\n\n```js\n// Draw the x axis in red\nthree.strokeStyle = 'red'\nthree.line([-1, 0, 0], [1, 0, 0])\n\n// Draw the y axis in blue\nthree.strokeStyle = 'blue'\nthree.line([0, -1, 0], [0, 1, 0])\n\n// Draw the z axis in green\nthree.strokeStyle = 'green'\nthree.line([0, 0, -1], [0, 0, 1])\n```\n\nWe can also plot the origin in white:\n\n```js\nthree.pointSize = 5\nthree.pointStyle = 'white'\nthree.point([0, 0, 0])\n```\n\nLastly, we'll make use of the `polygon` method to draw the xy, xz, and yz planes.\n\n```js\n// Turn off stroke\nthree.stroke = false\n\n// Define plane endpoints as coordinate arrays\nconst XY = [\n  [-0.25, -0.25, 0], \n  [-0.25, 0.25, 0], \n  [0.25, 0.25, 0], \n  [0.25, -0.25, 0]\n]\nconst XZ = [\n  [-0.25, 0, -0.25], \n  [-0.25, 0, 0.25], \n  [0.25, 0, 0.25], \n  [0.25, 0, -0.25]\n]\nconst YZ = [\n  [0, -0.25, -0.25], \n  [0, -0.25, 0.25], \n  [0, 0.25, 0.25], \n  [0, 0.25, -0.25]\n]\n\n\n// Draw the xy plane in translucent purple\nthree.fillStyle = 'rgba(255, 0, 255, 0.25)'\nthree.polygon(XY)\n\n// Draw the xz plane in translucent yellow\nthree.fillStyle = 'rgba(255, 255, 0, 0.25)'\nthree.polygon(XZ)\n\n// Draw the yz plane in translucent teal\nthree.fillStyle = 'rgba(0, 255, 255, 0.25)'\nthree.polygon(YZ)\n```\n\n**Note**:\n\u003e If you are using TypeScript, you may get an error with the above code sample that tells you a type cannot be converted to `vec3d`, which is a special internal type used in the Sost library to store arrays of length `3`.\n\u003e When using a variable as a parameter, TypeScript is unable to ensure that the length of that variable is unchanged, and will therefore throw an error stating that the types passed are not compatible with `vec3d`.\n\u003e To fix this, you can either pass the arrays directly to the `polygon` method, or copy [`sost/primitives.d.ts`](./sost/primitives.d.ts), import the `vec3d` type, and assign `XY`, `XZ`, and `YZ` to have type `vec3d[]` when defined.\n\u003e You may need to do this whenever you use variables as arguments to Sost drawing functions.\n\nViola!\nWe get the output generated by our testing suite.\nFor comparison, see the [artifacts](./artifacts/base.png) directory.\n\nAs a more advanced sidenote, the `point`, `line`, and `polygon` methods have primitive equivalents (which operate in point space rather than Cartesian space) given by appending a `p_` prefix to each of their names: `p_point`, `p_line`, and `p_polygon`.\nThere's also a `clear` method, which completely clears all data drawn to the canvas, and is useful when you want to change perspective and need Sost to redraw the scene.\n\n## Future Work\n\nSost is very much still a work in progress and there is lots to be done.\nIf you want to help out, it is highly recommended that you fork the repository and view the [todos](./TODOS.md) as well as any open issues for work that you can help with.\nYour contribution is much appreciated!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fquantum9innovation%2Fsost","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fquantum9innovation%2Fsost","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fquantum9innovation%2Fsost/lists"}