Rebol3 Code Examplex
Draw a torus
Rebol [
title: "Rosetta code: Draw a torus"
file: %Draw_a_torus.r3
url: https://rosettacode.org/wiki/Draw_a_torus
needs: blend2d
]
draw-torus: function [
"Draw a shaded 3D torus using perspective projection."
canvas [image! pair!] "Target image or dimensions to draw on"
][
Rext: 150 ;; major radius (center of tube to center of torus)
Rint: 60 ;; minor radius (tube cross-section radius)
A: 0.5 ;; rotation angle around X axis (radians)
B: 0.5 ;; rotation angle around Z axis (radians)
;; precompute rotation sines/cosines
sinA: sin A cosA: cos A
sinB: sin B cosB: cos B
cx: 320 ;; canvas center X
cy: 330 ;; canvas center Y
scale: 600 ;; perspective scale factor
px: 1 ;; dot radius in pixels
drawings: copy [fill-all 0.0.0] ;; drawing commands, starting with black background
clr: 0.0.255 ;; reusable color tuple (R G 255)
;; iterate over tube angle j and revolution angle i (both 0..2π, scaled by 100)
jj: 0.0 while [jj <= 628] [
j: jj / 100
ii: 0.0 while [ii <= 628] [
i: ii / 100
sini: sin i cosi: cos i
sinj: sin j cosj: cos j
;; 3D point on torus surface after applying rotations A (X) and B (Z)
h: Rext + (Rint * cosj) ;; distance from Z axis
x: h * (cosB * cosi + (sinA * sinB * sini)) - (Rint * cosA * sinB * sinj)
y: h * (sinB * cosi - (sinA * cosB * sini)) + (Rint * cosA * cosB * sinj)
z: h * cosA * sini + (Rint * sinA * sinj)
;; luminance: dot product of surface normal with light direction (top-front)
tmp: cosj * cosi * sinB - (sinA * cosj * sini * cosB) - (cosA * sinj * cosB)
lum: 8 * (tmp - (cosi * sinj * sinA))
if lum > 0 [
clr/2: br: min 255 lum * 30 ;; green = brightness [0..255]
clr/1: br / 2 ;; red = half brightness (blue stays 255)
;; perspective projection onto 2D canvas
ooz: 1 / (z + 500) ;; reciprocal depth
x: cx + (x * ooz * scale)
y: cy - (y * ooz * scale) ;; Y flipped: screen coords grow downward
repend drawings ['fill-pen clr 'circle as-pair x y px]
]
ii: ii + 3
]
jj: jj + 1
]
draw canvas drawings
]
browse save %Draw_a_torus.jpg draw-torus 600x600