Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

Voxel Rendering in Symta

Name: Anonymous 2020-07-04 11:38

https://www.youtube.com/watch?v=SB6NXGXBhsE

//for testing purposes; including from main.s
use fxn gui gfx util macros rgb

WD = No

D = 50
Cube = dup D: dup D: 0
//projections
PF =
PT =
PS =

voxelator.init InitWD =
| WD <= InitWD
| PF <= gfx "[WD]disc.png"
| PT <= PF
| PS <= PT

voxelator.get_d = D

//cut by projecions
prjcut =
| times Y D: times X D:
| when PF.get{X Y}&&&#FF000000:
| Cube.X.Y <= 0
| pass
| Zs = 0
| times Z D:
| B = (PT.get{D-1-Z X}&&&#FF000000)><0
and (PS.get{D-1-Z Y}&&&#FF000000)><0
| Zs <= Zs.bitSet{Z B}
| Cube.X.Y <= Zs

cuberender_xy G =
| G.clear{0}
| G.pixels //sync
| times Y D: times X D:
| Zs = Cube.X.Y
| times Z D:
| B = Zs.bit{Z}
| C = #FF*Z/D
| Color = rgb{C C C}
| when B: G.set{X Y Color}


//vector cross product
list.cross V = [$1*V.2 - $2*V.1
$2*V.0 - $0*V.2
$0*V.1 - $1*V.0]

list.dot V = $0*V.0 + $1*V.1 + $2*V.2

list.angle V = $dot{V}/($abs*V.abs)

//to rotate around specific origin use: (P-O).rotate3d{I A}+O
list.rotate3d Axis A =
| DX,DY,DZ = Me
| CosA = A.cos
| SinA = A.sin
| if Axis >< 0 then
//| NY = DY*CosA - DZ*SinA
//| NZ = DY*SinA + DZ*CosA
| NY = DZ*SinA + DY*CosA
| NZ = DZ*CosA - DY*SinA
| DX,NY,NZ
else if Axis >< 1 then
| NX = DX*CosA + DZ*SinA
| NZ = DZ*CosA - DX*SinA
| NX,DY,NZ
else
| NX = DX*CosA - DY*SinA
| NY = DX*SinA + DY*CosA
| NX,NY,DZ

rotatePlane O Angle Plane =
| Vs = Plane.deep_copy
| Vs.1 += Vs.0 //basis vectors are relative to the origin
| Vs.2 += Vs.0
| Rs = map P Vs:
| times I 3:
| A = Angle.I
| when A<>0.0: P <= (P-O).rotate3d{I A}+O //rotate around origin O
| P
| Rs.1 <= Rs.1-Rs.0
| Rs.2 <= Rs.2-Rs.0
| Rs

MarchXYZ = [0 0 0]
march_fn X Y Z =
| when X<0 or Y<0 or Z<0 or X>>D or Y>>D or Z>>D: leave 1
| Zs = Cube.X.Y
| B = Zs.bit{Z}
| less B: leave 1
| 0

sample_cube Src Dir L =
| P = Src.copy
| while L>0:
| less march_fn P.0.int P.1.int P.2.int: done
| L--
| P.0 += Dir.0
| P.1 += Dir.1
| P.2 += Dir.2
| less L>0: leave 0
| MarchXYZ.init{P}
| (MarchXYZ-Src).abs

cuberender Angle G =
| G.clear{0}
| G.pixels //sync
| O = [D.float*0.5 D.float*0.5 D.float*0.5] //scene origin
| Camera = [[O.0 O.1 -10.0] [1.0 0.0 0.0] [0.0 1.0 0.0]]
| Angle <= Angle{?*PI2/360.0}
| SO,SBX,SBY = rotatePlane O Angle Camera
| SBZ = SBX.cross{SBY}
/*| say SO
| say SBX
| say SBY
| say SBZ*/
| Scale = 2.0
| SBX *= Scale
| SBY *= Scale
| SYP = SO.copy
| SYP -= SBX*(G.w.float/2.0)
| SYP -= SBY*(G.h.float/2.0)
| SXP = [0.0 0.0 0.0]
| MarchL = D
| times SY G.h:
| SXP.init{SYP}
| times SX G.w:
| Dist = sample_cube SXP SBZ MarchL
| if Dist then
| B = 110.0-Dist
| when B<0.0: B <= 0.0
| C = @int B*255.0/110.0
| G.set{SX SY C}
else
| G.set{SX SY #000000}
| SXP.init{SXP + SBX}
| SYP.init{SYP + SBY}

NeedsCut = 1

voxelator.render_hm =
| when NeedsCut:
| prjcut
| NeedsCut <= 0
| Angle = [35.264+($cycle*4).float 45.0+($cycle*6).float ($cycle*3).float]
//| Angle = [35.264 45.0 0.0]
//| Angle = [0.0 0.0 0.0]
//| Angle = [90.0 90.0 0.0]
//| Angle = [0.0 0.0 0.0]
| cuberender Angle $hm

type voxelator.widget{} cm hm cycle mice_x mice_y d
| $d <= $get_d
| $init{WD}
| $hm <= gfx $d $d

voxelator.w = 256
voxelator.h = 256

voxelator.input In =
| case In
[mice_move _ X,Y]
| $mice_x <= X
| $mice_y <= Y

//calculate angle between the point light and the surface normal
calc_angle X0 Y0 Z0 X1 Y1 Z1 X2 Y2 Z2 L =
| V0 = [X0.float Y0.float Z0.float]
| A = fxn [X1-X0 Y1-Y0 Z1-Z0]
| B = fxn [X2-X0 Y2-Y0 Z2-Z0]
| N = (A.float).cross{B.float} //surface normal
| LDir = L-V0
| LDir.angle{N} //sin of angle with normal is the light intensity

voxelator.lighten_hm Color =
//| BG = $cm
| HM = $hm
| HMW = HM.w
| HMH = HM.h
| Out = gfx HMW HMH
| Out.clear{#B000B0}
| Out.pixels
| LX = $mice_x*HM.w/$w
| LY = $mice_y*HM.h/$h
| LZ = 500
| Light = [LX LY LZ].float
| Intensity = 2.0
| Y = 1
| fxn: while Y < HMH:
| SY = Y-1
| X = 1
| while X < HMW:
| NC = HM.get{X Y}
//| Color = BG.get{X Y}
| unrgba Color R G B A
| when A: _goto end
| when NC:
| SX = X-1
| NX = HM.get{SX Y}
| NY = HM.get{X SY}
| esc
| Angle = calc_angle X Y NC SX Y NX X SY NY Light
| Light = Angle*Intensity
| R <= @int R.float*Light
| G <= @int G.float*Light
| B <= @int B.float*Light
| when R>255: R<=255
| when G>255: G<=255
| when B>255: B<=255
| when R<0: R<=0
| when G<0: G<=0
| when B<0: B<=0
| Out.set{X Y rgb{R G B}}
| _label end
| X++
| Y++
| Out

voxelator.draw FB BX BY =
//| FB.clear{#B000B0}
| $render_hm
//| $hm.quad{[-3 -3] [FB.w -3] [-3 FB.h] [FB.w FB.h]}
//| FB.blit{0 0 $hm}
//| leave
| Out = $lighten_hm{#639bff}
| FB.pixels
| Out.quad{[-3 -3] [FB.w -3] [-3 FB.h] [FB.w FB.h]}
| FB.blit{0 0 Out}
| Out.free
| 0

voxelator.render =
| get_gui{}.sleep{1.0/48.0}
| $cycle++
| Me

invert_gfx G =
| for Y G.h: for X G.w: G.set{X Y 255-G.get{X Y}}
| G

hm_to_gray HM =
| for Y HM.h: for X HM.w:
| unrgb HM.get{X Y} R G B
| HM.set{X Y (R+G+B)/3}
| HM

voxelator_run =
| CH = gfx "[WD]ch.png"
| T = voxelator
| gui T cursor/CH

Name: Anonymous 2020-07-04 13:08

Still boolean operations are something that can be easily done in voxels.

Signed Distance Fields are better in every way.
The only real use of voxels is minecraft clones or 3D modeling software.

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List