Skip to content

Instantly share code, notes, and snippets.

@neftaly
neftaly / files.ts
Last active August 12, 2025 04:12
automerge filesystem
// root
{
"docs": [
{
"name": "Untitled",
"type": "essay",
"url": "automerge:3HVkHDJMBATJczaFwhKFH6cJhAm7"
},
{
"name": "Ghostscript_Tiger.svg",
@neftaly
neftaly / index.html
Last active August 6, 2025 12:45
Draco compression + gltf-transform + avif texture encoding in browser (with vite + ts)
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/webp" href="/favicon.webp" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- we have to manually download a copy of draco_encoder (or include it from three). Google does not CDN host encoder anywhere! only decoder -->
<script src="/draco_encoder.js"></script>
</head>
<body>
@neftaly
neftaly / wheel.js
Created June 13, 2025 22:53
wheel event handler for a 3d camera
addEventListener("wheel", (event) => { })
export const handleWheel = (event: PointerEvent, cameraConfig: Object) => (state) => {
// TODO: Add support for Safari touchpad gesture events
const {
altKey,
ctrlKey // `true` on trackpads when pinch-zooming (or ctrl key is pressed)
} = event
// Move camera (origin) when alt+wheeling
@neftaly
neftaly / BGSB.md
Last active June 13, 2025 22:39 — forked from Castux/BGSB.md

Multiplayer online board game sandbox

There are a few existing ones, with each their own characteristics. Which means of course I want to make my own.

Some design principles:

  • keep it simple but versatile
  • in browser, no install needed
  • click and drag 2D /3D interface, compatible with mobile
  • no account needed: join rooms by URL or room code
@neftaly
neftaly / LoadingSpinner.jsx
Created December 1, 2024 00:18
pmndrs react-three-fiber uikit animated loading spinner
import { Container } from "@react-three/uikit";
import { Loader } from '@react-three/uikit-lucide'
import { useRef } from 'react'
import { useFrame } from '@react-three/fiber'
const LoadingSpinner = ({ ...props }) => {
const ref = useRef()
useFrame(({ clock }) => {
ref.current.setStyle({ "transformRotateZ": clock.getElapsedTime() * -100 })
})

hello

@neftaly
neftaly / castShapeDown.js
Last active May 7, 2023 05:59
react-three-rapier scene query
import { Quaternion, Euler } from 'three'
// Reusuable objects to save on GC
const quaternion = new Quaternion()
const euler = new Euler()
// TODO: Do we need to do this or will Rapier just accept a Three quaternion?
const rotationToQuaternion = (rotation) => {
const { w, x, y, z } = quaternion.setFromEuler(euler.set(...rotation))
return { w, x, y, z }
@neftaly
neftaly / gist:55a0b569169a08b4500357ea7dca9abf
Created February 16, 2022 04:56
AXIS M7011 firmware v5.90.1 (10/2015)
AXIS M7011 firmware v5.90.1 (10/2015)
https://drive.google.com/file/d/1KCPKUMBI9H7JoiBssCY9Fnxe6oRkdFwP/view?usp=drive_web
@neftaly
neftaly / MapCamera.jsx
Last active February 19, 2023 08:40
react-three-fiber declarative map controls
import { useEffect, useRef } from 'react'
import { useThree } from '@react-three/fiber'
import { PerspectiveCamera } from '@react-three/drei'
import useCamera from './useCamera'
// Camera bound to origin/coords state
const MapCamera = props => {
const invalidate = useThree(s => s.invalidate)
const groupRef = useRef()
const cameraRef = useRef()
@neftaly
neftaly / ControlRig.jsx
Created July 9, 2020 03:45
rstream-gestures multitouch with react
import React, { useEffect } from 'react'
import { useThree } from 'react-three-fiber'
import { GestureType, gestureStream } from '@thi.ng/rstream-gestures'
import { map } from '@thi.ng/transducers'
import { tryCatch } from 'ramda'
// Calculate the difference between 2 [x,y] vectors
const calcDelta = (key, a, b) => [a[key][0] - b[key][0], a[key][1] - b[key][1]]
// Calculate the angle and distance between 2 pointers