View Single Post
Old 04-29-2012, 09:50 PM   #69
PoP
 curly᷂͓̫̙᷊̥̮̾ͯͤͭͬͦͨ ʎʌɹnɔ
PoP ought to be getting tired of karma fortunes by now.PoP ought to be getting tired of karma fortunes by now.PoP ought to be getting tired of karma fortunes by now.PoP ought to be getting tired of karma fortunes by now.PoP ought to be getting tired of karma fortunes by now.PoP ought to be getting tired of karma fortunes by now.PoP ought to be getting tired of karma fortunes by now.PoP ought to be getting tired of karma fortunes by now.PoP ought to be getting tired of karma fortunes by now.PoP ought to be getting tired of karma fortunes by now.PoP ought to be getting tired of karma fortunes by now.
 
PoP's Avatar
 
Posts: 3,002
Karma: 50506927
Join Date: Dec 2010
Location: ♁ ᴺ₄₅°₃₀' ᵂ₇₃°₃₇' ±₆₀"
Device: K3₃.₄.₃ PW3&4₅.₁₃.₃
3D - An Interactive animated projection of an object on a 2D screen

Click image for larger version

Name:	3D.png
Views:	515
Size:	3.8 KB
ID:	85869

After seeing geekmaster's "eink algorithmic art" demos, I fancied and dusted off a 30 years old demo -- see the included original Byte Magazine extract! (with a bonus p486 rescan to fix original download URL )

Teaser code for illustrative purpose only,
Spoiler:
PHP Code:
#!/bin/sh
#=============================
# 3D - Projects a 3D object to a 2D screen
# Inspired by "eink algorithmic art" thread at https://www.mobileread.com/forums/showthread.php?t=172182
# usage: 3D
# Only tested on Kindle3 (firmware 3.3, Busybox 1.7.2 Almquist Shell)
#------------------------------
# Copyright (c) 2012 PoP under MIT License:
# Copyright (c) 2012 geekmaster under MIT License:
# http://www.opensource.org/licenses/mit-license.php
#------------------------------
# Revision History:
# v4.0  2012-04-05 PoP            ported to Kindle3                  
# v3.0  1986-12-20 PoP            ported to IBM PC
# v2.0  1983-09-14 PoP            ported to C=64
# v1.0  1982-11-11 PoP            ported to Apple][
# v0.0  1981-01-01 A. Pickholtz   see pp 474-505 BYTE magazine: http://malus.exotica.org.uk/~buzz/byte/pdf/BYTE%20Vol%2007-11%201982-11%20Graphics.pdf
#------------------------------
# Global vars:
# B    bank -PI..PI scaled
# CB    cos(bank)
# CH    cos(heading)
# CM    var C of 3d matrix  scaled
# CP    cos(pitch)
# BLOCK vectors of this object scaled
# D    distance from camera scaled
# DF    device frame buffer
# DK    device keyboard
# DM    var D of 3d matrix scaled
# DN    device null
# DODECA vectors of this object scaled
# EM    var E of 3d matrix scaled
# EDGE    absolute value of EDGEi
# EDGEi    OBJ current edge
# EDGE$i OBJ $i'th edge $i i-1..NE
# FP    floating point scaling 10^4
# FH    floating point rounding FP/2
# FM    var F of 3d matrix scaled
# GM    var G of 3d matrix scaled
# H    heading -PI..PI scaled
# HX    middle x screen pos 300
# HY    middle y screen pos 400
# HM    var H of 3d matrix scaled
# IM    var I of 3d matrix scaled
# KQ    bytes per pixel, 2 for Kindle3
# MX    max x pos 0:599
# MY    max y pos 0:799
# NE    OBJ number of edges
# NV    OBJ number of points
# OBJ   current object scaled
# OCTA  vectors of this object
# P    pitch -PI..PI scaled
# P2    2*PI scaled
# PI    PI scaled
# PN    -PI scaled
# SB    sin(bank)
# SH    sin(heading)
# SP    sin(pitch)
# TK    device temporary key
# TETRA vectors of this object scaled
# U    computing 2D projection scaled
# V    computing 2D projection scaled
# VECTX$i OBJ $i'th X coord i=1..NV scaled
# VECTY$i OBJ $i'th Y coord i=1..NV scaled
# VECTZ$i OBJ $i'th Z coord i=1..NV scaled
# VX    virtual x size, 300 for Kindle 3
# XX    computing 2D projection scaled
# YY    computing 2D projection scaled
# ZZ    computing 2D projection scaled
# x1    temp coordinate scaled
# x2    temp coordinate scaled
# X3    computing 2D projection scaled
# y1    temp coordinate scaled
# y2    temp coordinate scaled
# Y3    computing 2D projection scaled
# Z3    computing 2D projection scaled
#-----------------------------

#=============================
# initvar - init global vars
#-----------------------------
initvar() {
  
DN=/dev/null DF=/dev/fb0 DK=/dev/input/event0 MX=599 MY=799 HX=300 HY=400
  TK
=/tmp/key; echo > $TK
  
set $(eips -i|grep line_length); VX=$4
  FP
=10000 # fixed-point scale factor
  
FH=5000 # FP/2 (for rounding)
  
PI=31416 # PI (scaled)
  
P2=62832 # 2*PI (scaled)
  
PN=-31416 # -PI (scaled)
  
KQ=# K3 pixels per byte
  
P=0 B=0 H=0 D=135000
  BLOCK
="
     8
      52500     -20000      32500
     -52500     -20000      32500
     -52500     -20000     -32500
      52500     -20000     -32500
      52500      20000      32500
     -52500      20000      32500
     -52500      20000     -32500
      52500      20000     -32500
     17
     -1 2 3 4 1 5 6 7 8 5
     -2 6 3 7 2
     -4 8"
  
DODECA="
     20
          0     -21408      56052
      34644     -34644      34644
      56052          0      21408
      34644      34644      34644
          0      21408      56052
     -34644      34644      34644
     -56052          0      21408
     -34644     -34644      34644
     -21408     -56052          0
      21408     -56052          0
      21408      56052          0
     -21408      56052          0
     -34644     -34644     -34644
          0     -21408     -56052
      34644     -34644     -34644
      56052          0     -21408
      34644      34644     -34644
          0      21408     -56052
     -34644      34644     -34644
     -56052          0     -21408
    40
     -1 2 3 4 5 6 7 8 1 5
     -14 15 16 17 18 19 20 13 14 18
     -8 9 10 2
     -13 9
     -15 10
     -4 11 12 6
     -17 11
     -19 12
     -16 3
     -7 20"
  
OCTA="
     6
          0      75000          0
          0          0     -25000
     -25000          0          0
          0          0      25000
      25000          0          0
          0     -75000          0
     14
     -1 2 6 4 1 3 6 5 1
     -2 3 4 5 2"
  
TETRA="
     4
     -45000     -45000     -45000
      45000     -45000     -45000
          0      45000          0
          0      45000     -45000
     8
     -1 2 3 1 4 2 3 4"
}

#===========================
# eupd - eink update display
#---------------------------
eupd() {
  echo 
>/proc/eink_fb/update_display # (for k3 and earlier)
#  eips '' # (for k4 and newer)
}

#=============================
# line - Bresenham's line algorithm
# usage: line x0 y0 x y
#-----------------------------
line() {
  
local x0=$(($1/$KQ)) y0=$2 x=$(($3/$KQ)) y=$4local dx dy sx sy e e2 xw xp=$x0
  
if [[ $x -gt $x0 ]];then dx=$((x-x0));sx=1; else dx=$((x0-x));sx=-1;fi
  
if [[ $y -gt $y0 ]];then dy=$((y0-y));sy=1; else dy=$((y-y0));sy=-1;fi
  e
=$((dx+dy)); echo -en "\xff${b#?}" | dd of=$DF bs=1 count=1 seek=$((y*VX+x)) 2>$DN
  
while [[ $x0 -ne $x -o $y0 -ne $y ]];do
    
xw=$((x0-xp)); [[ $xw -lt 0 ]]&& xw=$((-xw))
    echo -
en "\xff${b#?}" | dd  of=$DF bs=1 count=1 seek=$((y0*VX+x0)) 2>$DN
    
e2=$((e+e))
    if [[ 
$e2 -gt $dy ]];then e=$((e+dy));x0=$((x0+sx));fi
    
if [[ $e2 -lt $dx ]];then
      xp
=$x0;e=$((e+dx));y0=$((y0+sy))
    
fi
  done
;
}


#=============================
# sin - Taylor series sine function
# sin x ~= x - x^3/3! + x^5/5! - x^7/7!
# usage: sin x  (-PI..PI)
# STDOUT: sin(x)  (0..10K)
# O(5) @ +-90 deg, O(7) @ +-180 deg
# 10K fixed-point scale factor 
#------------------------------
sin() {
  local x=$1
  while [[ 
$x -gt $PI ]];do x=$((x-$P2));done
  while [[ 
$x -lt $PN ]];do x=$((x+$P2));done
  local a=
$x xs=$(((x*x+FH)/FP))
  local xn=$(((x*xs+FH)/FP)) fn=6 # O(3)
  a=$((a-(xn+fn/2)/fn)) xn=$(((xn*xs+FH)/FP)) fn=$((fn*20)) # O(5)
  a=$((a+(xn+fn/2)/fn)) xn=$(((xn*xs+FH)/FP)) fn=$((fn*42)) # O(7)
  a=$((a-(xn+fn/2)/fn)); echo 
$a
}

#=============================
# cos(x) = sin(pi/2-x) function
# usage: cos x  (-PI..PI)
# STDOUT: cos(x)  (0..10K)
# 10K fixed-point scale factor 
#------------------------------
cos() {
sin $((PI/2+$(mult -10000 $1)))
}

#=============================
# mult -  multiply scaled numbers
# usage: mult x y
# STDOUT: x * y  (0..10K)
# 10K fixed-point scale factor 
#------------------------------
mult() {
echo $((($1*$2+FH)/FP))
}

#=============================
# mat3d - compute projection matrix coefficients
# usage: mat3d 
#-----------------------------
mat3d() {
  CH=$(cos 
$H) SH=$(sin $H)
  CP=$(cos 
$P) SP=$(sin $P)
  CB=$(cos 
$B) SB=$(sin $B)
  AM=$(( $(mult CB CH) - $(mult $(mult SH SP) SB)));    #   cos(B) cos(H) - sin(P) sin(B) sin(H)
  BM=$((-$(mult CB SH) - $(mult $(mult SP CH) SB)));    # - cos(B) sin(H) - sin(P) sin(B) cos(H)
  CM=$(( $(mult CP SB)));                #   sin(B) cos(P)
  DM=$(( $(mult CP SH)));                #   sin(H) cos(P)
  EM=$(( $(mult CP CH)));                #   cos(P) cos(H)
  FM=
$SP;                        #   sin(P)
  GM=$((-$(mult SB CH) - $(mult $(mult SH SP) CB)));    # - cos(H) sin(B) - sin(H) sin(P) cos(B)
  HM=$(( $(mult SB SH) - $(mult $(mult CH SP) CB)));    #   sin(H) sin(B) - sin(P) cos(H) cos(B)
  IM=$(( $(mult CP CB)));                #   cos(P) cos(B)
}

#==============================
# proj2d - project a vector
# usage: proj2d 
#------------------------------
proj2d() {
  XX=$((XX-XV))
  YY=$((YY-YV))
  ZZ=$((ZZ-ZV))
  X3=$(($(mult AM XX)+$(mult BM YY)+$(mult CM ZZ)))
  Y3=$(($(mult DM XX)+$(mult EM YY)+$(mult FM ZZ)))
  Z3=$(($(mult GM XX)+$(mult HM YY)+$(mult IM ZZ)))
  U=$((HX+ $(mult $(mult 300000 D)/Y3 X3))); # 30 horiz ppu adjustment
  V=$((HY+ $(mult $(mult 300000 D)/Y3 Z3))); # 30 vert ppu adjustment
}

#=============================
# plot 3D object on 2D screen
# usage: plot object
#-----------------------------
plot() {
  # read object vectors and edges:
  NV=$1; shift; # number of points
  for i in $(seq 
$NV); do
    echo $((VECTX
$i=$1)) $((VECTY$i=$2)) $((VECTZ$i=$3)) > $DN
    shift; shift; shift
  done
  NE=$1; shift  # number of edges
  for i in $(seq 
$NE); do
    echo $((EDGE
$i=$1)) > $DN; shift
  done

  while :; do

    # project object:
    eips -c
    eips  0 39 "
P=$P H=$H B=$B D=$D"
    mat3d
    XV=$((-$(mult $(mult D CP) SH)))
    YV=$((-$(mult $(mult D CP) CH)))
    ZV=$((-$(mult D SP)))
    for i in $(seq 
$NE); do
      echo $((EDGEi=EDGE
$i))>$DN
      EDGE=
$EDGEi
      [[ 
$EDGE -le 0 ]]&& EDGE=$((-EDGE)) # ABS(EDGE)
      echo $((XX=VECTX
$EDGE))>$DN; echo $((YY=VECTY$EDGE))>$DN; echo $((ZZ=VECTZ$EDGE))>$DN
      proj2d
      if [[ 
$EDGEi -gt 0 ]]; then
        x2=
$U  y2=$V
        line 
$x1 $y1 $x2 $y2; eupd
      fi
      x1=
$U  y1=$V
    done

    if [[ -s 
$TK ]];then # get new Pitch, Heading, Bank, or Distance from keyboard input  
      set $(cat 
$TK); local k=$1; echo > $TK; waitforkey > $TK &
      case 
$k in
        25)    P=$((P+P2/36));;    # p +10dg
        35)    H=$((H+P2/36));;    # h +10dg
        48)    B=$((B+P2/36));;    # b +10dg
        44)    D=$((D-2*FP));;        # z zoom in
        22)    D=$((D+2*FP));;        # u zoom out
        19)    P=0 H=0 B=0 D=135000;;    # r home
        102)    return;;        # HOME quit program
      esac
    fi 
   
  done
}

#=============================
# main program entry point
#-----------------------------                  
lipc-set-prop com.lab126.powerd preventScreenSaver 1
killall -stop cvm # pause framework
initvar # init global vars
while :; do
  eips -c 
  eips 15  4 "    
_/_/_/    3D"
  eips 15  5 "         
_/  4.0 _/_/_/"
  eips 15  6 "    
_/_/    by  _/    _/"
  eips 15  7 "       
_/  PoP _/    _/"
  eips 15  8 "
_/_/_/        _/    _/"
  eips 15  9 "             
_/_/_/"
  eips 15 15 "
Select object to plot:"
  eips 15 16 "
Q    BLOCK"
  eips 15 17 "
W    OCTAHEDRON"
  eips 15 18 "
E    TETRAHEDRON"
  eips 15 19 "
R    DODECAHEDRON"
  eips 15 20 "
Home Quit"
  eips 15 28 "
While object is being plot:"
  eips 15 29 "
R      reset view"
  eips 15 30 "
P      pitch"
  eips 15 31 "
H      heading"
  eips 15 32 "
B      bank"
  eips 15 33 "
Z      zoom"
  eips 15 34 "
U      un zoom"
  eips 15 35 "
Home Select new object"
  waitforkey > 
$TK; set $(cat $TK); local k=$1;  echo > $TK;
  case 
$k in
    16)    plot 
$BLOCK;;
    17)    plot 
$OCTA;;
    18)    plot 
$TETRA;; 
    19)    plot 
$DODECA;;
   102) killall -cont cvm; lipc-set-prop com.lab126.powerd preventScreenSaver 0; exit;;
  esac 
done 
extract the attached zip to preserve tabs, escaped characters, etc.

In particular, note the echo $((VECTX$i=$1))>$DN construct to dynamically define and assign VECTOR$i variables in absence of shell arrays .

I have included definitions for a couple of objects. It should be somewhat easy to modify and define vectors for more.

Use the keyboard to interactively control viewing angles and distance. When in trouble, press Home key twice to exit.

WARNINGS:

Well, this script is certainly not fast, and only meant for as a fun demo in /bin/sh education. It will only work on the K3, when started from an ssh session or from a launchpad shortcut. I have not thoroughly tested it (I am a bit surprised that it even works at all given the /bin/sh quirks I encountered). A "C formula'42" implementation would be a relief.

It will fail displaying correctly when zooming too close. Proper clipping is not implemented.

And Oh, sorry for too much white space... I felt it was cryptic enough without "optimizing" further.
Attached Files
File Type: zip 3D_4.0.zip (3.38 MB, 198 views)
PoP is offline   Reply With Quote