spinning tetrahedron :3
This commit is contained in:
parent
69ceed6c28
commit
ec63b97756
52
kglobe.py
52
kglobe.py
@ -1,42 +1,26 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from kitty import draw_to_terminal
|
||||
from kitty import draw_to_terminal, get_position, set_position, hide_cursor, show_cursor #, draw_animation
|
||||
|
||||
from PIL import Image
|
||||
|
||||
import numpy as np
|
||||
import trimesh
|
||||
import pyrender
|
||||
import pyvista as pv
|
||||
|
||||
sphere = pv.Tetrahedron()# Sphere()
|
||||
pl=pv.Plotter(off_screen=True)
|
||||
pl.add_mesh(sphere, color='tan', show_edges=False)
|
||||
|
||||
sphere = trimesh.creation.icosphere(subdivisions=3, radius=1.0)
|
||||
# create mesh
|
||||
mesh = pyrender.Mesh.from_trimesh(sphere, smooth=True, wireframe=True)
|
||||
hide_cursor()
|
||||
y, x = get_position()
|
||||
print('\n' * 25, end='')
|
||||
|
||||
# Create a scene and add the mesh
|
||||
scene = pyrender.Scene(bg_color = [0, 0, 0, 0])
|
||||
scene.add(mesh)
|
||||
|
||||
# Add a directional light to illuminate the sphere
|
||||
light = pyrender.DirectionalLight(color=np.ones(3), intensity=3.0)
|
||||
light_pose = np.eye(4)
|
||||
light_pose[:3, 3] = [0, 2, 2] # light from above and in front
|
||||
scene.add(light, pose=light_pose)
|
||||
|
||||
# Add a camera
|
||||
camera = pyrender.PerspectiveCamera(yfov=np.pi / 3.0)
|
||||
camera_pose = np.array([
|
||||
[1.0, 0.0, 0.0, 0.0],
|
||||
[0.0, 1.0, 0.0, 0.0],
|
||||
[0.0, 0.0, 1.0, 3.0], # Pull camera back
|
||||
[0.0, 0.0, 0.0, 1.0]
|
||||
])
|
||||
scene.add(camera, pose=camera_pose)
|
||||
|
||||
r = pyrender.OffscreenRenderer(512, 512)
|
||||
flags = pyrender.RenderFlags.RGBA
|
||||
color, depth = r.render(scene, flags=flags)
|
||||
#
|
||||
im = Image.fromarray((color)) # .new("RGBA", (512, 512), (0, 0, 0, 0) )
|
||||
|
||||
draw_to_terminal(im)
|
||||
frames = []
|
||||
try:
|
||||
while True:
|
||||
pl.camera.Azimuth(1)
|
||||
image = pl.screenshot(transparent_background=True, window_size=(512, 512))
|
||||
frames.append(Image.fromarray(image))
|
||||
set_position(y-25, x)
|
||||
draw_to_terminal(Image.fromarray(image))
|
||||
finally:
|
||||
show_cursor()
|
||||
|
64
kitty.py
64
kitty.py
@ -1,5 +1,8 @@
|
||||
#!/usr/bin/env python3
|
||||
import re
|
||||
import sys
|
||||
import termios
|
||||
import tty
|
||||
from base64 import standard_b64encode
|
||||
from io import BytesIO
|
||||
|
||||
@ -8,7 +11,7 @@ from PIL import Image, ImageDraw
|
||||
def draw_to_terminal(img: Image.Image) -> None:
|
||||
buffer: BytesIO = BytesIO()
|
||||
img.save(buffer, format='PNG')
|
||||
write_chunked(a='T', f=100, data=buffer.getvalue())
|
||||
write_chunked(a='T', i=1, f=100, q=2, data=buffer.getvalue())
|
||||
|
||||
def serialize_gr_command(**cmd):
|
||||
payload = cmd.pop('payload', None)
|
||||
@ -32,6 +35,65 @@ def write_chunked(**cmd):
|
||||
sys.stdout.flush()
|
||||
cmd.clear()
|
||||
|
||||
def hide_cursor():
|
||||
sys.stdout.write("\x1b[?25l")
|
||||
sys.stdout.flush()
|
||||
|
||||
def show_cursor():
|
||||
sys.stdout.write("\x1b[?25h")
|
||||
sys.stdout.flush()
|
||||
|
||||
def set_position(y, x):
|
||||
sys.stdout.write(f"\x1b[{y};{x}H")
|
||||
sys.stdout.flush()
|
||||
|
||||
def get_position():
|
||||
# Save the current terminal settings
|
||||
fd = sys.stdin.fileno()
|
||||
old_settings = termios.tcgetattr(fd)
|
||||
|
||||
try:
|
||||
# Set terminal to raw mode
|
||||
tty.setraw(fd)
|
||||
|
||||
# Send the ESC[6n command to request cursor position
|
||||
sys.stdout.write("\x1b[6n")
|
||||
sys.stdout.flush()
|
||||
|
||||
# Read the response: ESC [ row ; col R
|
||||
response = ''
|
||||
while True:
|
||||
ch = sys.stdin.read(1)
|
||||
response += ch
|
||||
if ch == 'R':
|
||||
break
|
||||
|
||||
finally:
|
||||
# Restore the terminal settings
|
||||
termios.tcsetattr(fd, termios.TCSANOW, old_settings)
|
||||
|
||||
# Parse the response using regex
|
||||
match = re.search(r'\[(\d+);(\d+)R', response)
|
||||
if match:
|
||||
y, x = map(int, match.groups())
|
||||
return y, x
|
||||
else:
|
||||
raise ValueError("Failed to parse cursor position response")
|
||||
|
||||
|
||||
# sys.stdout.write("\x1b[6n")
|
||||
# sys.stdout.flush()
|
||||
# response = ''
|
||||
# while True:
|
||||
# ch = sys.stdin.read(1)
|
||||
# response += ch
|
||||
# if ch == 'R':
|
||||
# break
|
||||
# match = re.search(r'\[(\d+);(\d+)R', response)
|
||||
# if match:
|
||||
# y, x = map(int, match.groups())
|
||||
# return y, x
|
||||
|
||||
if __name__ == '__main__':
|
||||
i = Image.new("RGB", (100, 100), (0, 0, 0))
|
||||
d = ImageDraw.Draw(i)
|
||||
|
11
pyproject.toml
Normal file
11
pyproject.toml
Normal file
@ -0,0 +1,11 @@
|
||||
[project]
|
||||
name = "kglobe"
|
||||
version = "0.1.0"
|
||||
description = "Add your description here"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.13"
|
||||
dependencies = [
|
||||
"numpy<2",
|
||||
"pyrender>=0.1.45",
|
||||
"pyvista>=0.45.3",
|
||||
]
|
Loading…
Reference in New Issue
Block a user