This is the best tutorial I have found that covers meshes lighting and rendering.
youtube link
imgur link to rotating logo
3dgifmaker.com is so much easier than learning blender though
Wednesday, October 22, 2025
how to make a rotating 3d svg in blender
Friday, October 17, 2025
Tuesday, October 14, 2025
one liner to reinstall xfce
I always end up breaking the desktop if i mess around with the settings long enough.
this one liner removes and then cleanly reinstalls xfce
sudo apt purge xfce4* xfdesktop4* thunar* xfwm4* && sudo apt autoremove --purge && sudo apt install xfce4 xfce4-goodies
Tuesday, October 7, 2025
Modularizing Your Bash Functions (Example: vicd with Vifm)
Step 1: Create a Modular Config Directory
Keep your Bash setup clean by separating custom scripts:
mkdir -p ~/.bashrc.d
This directory will store small .sh files instead of crowding your .bashrc.
Step 2: Add Your Function
Create a file just for your Vifm directory picker:
vim ~/.bashrc.d/vicd.sh
Paste this inside:
vicd() {
local dst
dst="$(command vifm --choose-dir - "$@")"
if [ -z "$dst" ]; then
echo 'Directory picking cancelled/failed'
return 1
fi
cd "$dst"
}
Step 3: Source All Scripts Automatically
At the end of your ~/.bashrc, add:
for f in ~/.bashrc.d/*.sh; do
[ -f "$f" ] && . "$f"
done
Reload your shell:
source ~/.bashrc
Now your vicd function (and any future ones) load automatically — tidy, modular, and easy to manage.
Saturday, October 4, 2025
fixed velocity for acorn masterkey on ios
streambyter has a fixed velocity script. It's supposed to be adjustable with cc 15 on channel one but it's not working for me.
Wednesday, September 24, 2025
Thursday, September 18, 2025
Tuesday, September 16, 2025
rp2040 breakout board for prototyping
its pretty cool you can just order the gerbers from pcbway, solder some headers and have easy access to those awkward pins to maximize the use of this tiny footprint
Monday, September 15, 2025
Friday, September 12, 2025
getting a usb qwerty to be a midi keyboard without a computer
samd2695 + esp32s3
akai mpk play has built in sounds and a speaker but wasnt a fan. you could get a qy100 or some other old midi module on ebay or a pawn shop. An mt-32, soundcanvas, maybe a proteus. but now for 30$ on ali you can get one of these
Wednesday, September 10, 2025
Tuesday, September 9, 2025
how to convert mkv to mp4
so you've recorded a video on linux with guvcview and now you want to play it/edit it on an iphone,
heres a one liner you can use with ffmpeg to convert it to mp4:
for f in *.mkv; do ffmpeg -i "$f" -c:v libx264 -profile:v high -level 4.1 -c:a aac -movflags +faststart "${f%.mkv}.mp4"; done
Tuesday, September 2, 2025
beam forming
pretty cool these days to be able to dip your toes into medical ultrasound technology using cheaply available microcontrollers and sensors.
diy sonar scanner
Saturday, August 30, 2025
adding more gpio to an arduino nano/ raspberry pi
the mcp3008 for adc good for adding pots
picoIO64
22$ some soldering required. gives you 64 gpio
modmypi mcp2308 pi zero hat adds 16 gpio 14.95$
Tuesday, August 26, 2025
Thursday, August 21, 2025
Tuesday, August 19, 2025
my sunvox shortcuts
reposting this because I put down sunvox for a while and had to relearn it.
- cyclic shift is #1 the most important shortcut to add.
- being able to move between patterns is another one.
- shift space to play from line
- doing chords with ctrl g b i
- ctrl p paste evenly
- ctrl t select track
Friday, August 15, 2025
remaping the f310 to send midi with watchdog for auto reload
#!/usr/bin/env python3
import evdev
import rtmidi
from evdev import ecodes
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
import os
import sys
DEVICE_PATH = '/dev/input/by-id/usb-Logitech_Logitech_Dual_Action_DF5CB332-event-joystick'
# ----------------------------
# Corrected human-readable button mappings
# ----------------------------
buttons = {
'A': 61, # physical A triggers MIDI note B
'B': 62, # physical B triggers MIDI note X
'X': 60, # physical X triggers MIDI note A
'Y': 63,
'L': 64,
'R': 65,
'Select': 66,
'Start': 67,
'Up': 68,
'Down': 69,
'Left': 70,
'Right': 71
}
evdev_button_map = {
288: 'A',
289: 'B',
290: 'X',
291: 'Y',
292: 'L',
293: 'R',
296: 'Select',
297: 'Start',
294: 'Up',
295: 'Down',
298: 'Left',
299: 'Right'
}
# ----------------------------
# Axis mappings
# ----------------------------
axes = {
'LX': (10, -32768, 32767),
'LY': (11, -32768, 32767),
'LT': (12, 0, 255),
'RT': (13, 0, 255),
'RX': (14, -32768, 32767),
'RY': (15, -32768, 32767)
}
evdev_axis_map = {0: 'LX', 1: 'LY', 2: 'LT', 5: 'RT', 3: 'RX', 4: 'RY'}
# ----------------------------
# MIDI setup
# ----------------------------
midi_out = rtmidi.MidiOut()
midi_out.open_virtual_port("F310 MIDI")
def scale(value, min_val, max_val):
return int((value - min_val) / (max_val - min_val) * 127)
# ----------------------------
# Main gamepad loop
# ----------------------------
def run():
gamepad = evdev.InputDevice(DEVICE_PATH)
print(f"Listening on {gamepad.name} ({gamepad.path})")
for event in gamepad.read_loop():
if event.type == ecodes.EV_KEY and event.code in evdev_button_map:
label = evdev_button_map[event.code]
note = buttons[label]
if event.value == 1:
midi_out.send_message([0x90, note, 112])
print(f"Button pressed: {label}")
elif event.value == 0:
midi_out.send_message([0x80, note, 0])
elif event.type == ecodes.EV_ABS and event.code in evdev_axis_map:
label = evdev_axis_map[event.code]
cc, min_val, max_val = axes[label]
val = scale(event.value, min_val, max_val)
midi_out.send_message([0xB0, cc, val])
# ----------------------------
# Watchdog for hot-reload
# ----------------------------
class ReloadHandler(FileSystemEventHandler):
def on_modified(self, event):
if event.src_path.endswith(os.path.basename(__file__)):
print("Script changed. Restarting...")
os.execv(sys.executable, ['python3'] + sys.argv)
observer = Observer()
observer.schedule(ReloadHandler(), path='.', recursive=False)
observer.start()
# ----------------------------
# Run forever
# ----------------------------
try:
while True:
run()
except KeyboardInterrupt:
observer.stop()
observer.join()
Thursday, August 14, 2025
1 liner gpg encryption + qr
gpg - c creates, gpg - d decodes
this uses python qrcode (pip install it if you dont have it)
read -p "Input GPG file: " infile; read -p "Output PNG file: " outfile; python3 -c "import qrcode, base64; f=open('$infile','rb'); data=base64.b64encode(f.read()).decode(); f.close(); qrcode.make(data).save('$outfile')"
this passes the input of the qr as input and decodes the gpg (requires pyzbar. opencv is good to have also
read -p "QR PNG file: " qrfile; read -p "Output file: " outfile; python3 -c "import cv2, pyzbar.pyzbar as pyzbar, base64, sys; img=cv2.imread('$qrfile'); data=pyzbar.decode(img)[0].data; sys.stdout.buffer.write(base64.b64decode(data))" | gpg -d > "$outfile"