Draw a sphere

From Rosetta Code
Jump to: navigation, search
Task
Draw a sphere
You are encouraged to solve this task according to the task description, using any language you may know.

The task is to draw a sphere.

The sphere can be represented graphically, or in ascii art, depending on the language capabilities.

Either static or rotational projection is acceptable for this task.

Contents

[edit] Ada

Library: GtkAda

Translation from the C code at http://cairographics.org/samples/gradient Uses the Cairo component of GtkAda to create and save as png

SphereAda.png
with Glib;                use Glib;
with Cairo; use Cairo;
with Cairo.Png; use Cairo.Png;
with Cairo.Pattern; use Cairo.Pattern;
with Cairo.Image_Surface; use Cairo.Image_Surface;
with Ada.Numerics;
 
procedure Sphere is
subtype Dub is Glib.Gdouble;
 
Surface  : Cairo_Surface;
Cr  : Cairo_Context;
Pat  : Cairo_Pattern;
Status_Out : Cairo_Status;
M_Pi  : constant Dub := Dub (Ada.Numerics.Pi);
 
begin
Surface := Create (Cairo_Format_ARGB32, 512, 512);
Cr  := Create (Surface);
Pat  :=
Cairo.Pattern.Create_Radial (230.4, 204.8, 51.1, 204.8, 204.8, 256.0);
Cairo.Pattern.Add_Color_Stop_Rgba (Pat, 0.0, 1.0, 1.0, 1.0, 1.0);
Cairo.Pattern.Add_Color_Stop_Rgba (Pat, 1.0, 0.0, 0.0, 0.0, 1.0);
Cairo.Set_Source (Cr, Pat);
Cairo.Arc (Cr, 256.0, 256.0, 153.6, 0.0, 2.0 * M_Pi);
Cairo.Fill (Cr);
Cairo.Pattern.Destroy (Pat);
Status_Out := Write_To_Png (Surface, "SphereAda.png");
pragma Assert (Status_Out = Cairo_Status_Success);
end Sphere;
Library: Display

This uses a very loose binding to SDL as found in any GPS installation. For it to work, you must choose New Project From Templte|Empty Game

 
with Display; use Display;
with Display.Basic; use Display.Basic;
 
procedure Main is
Ball : Shape_Id := New_Circle
(X => 0.0,
Y => 0.0,
Radius => 20.0,
Color => Blue);
begin
null;
end Main;
 

[edit] AutoHotkey

Library: GDIP
#NoEnv
SetBatchLines, -1
#SingleInstance, Force
 
; Uncomment if Gdip.ahk is not in your standard library
#Include, Gdip.ahk
 
; Settings
X := 200, Y := 200, Width := 200, Height := 200 ; Location and size of sphere
rotation := -30 ; degrees
ARGB := 0xFFFF0000 ; Color=Solid Red
 
If !pToken := Gdip_Startup() ; Start gdi+
{
MsgBox, 48, gdiplus error!, Gdiplus failed to start. Please ensure you have gdiplus on your system
ExitApp
}
OnExit, Exit
 
Gui, -Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs ; Create GUI
Gui, Show, NA ; Show GUI
hwnd1 := WinExist() ; Get a handle to this window we have created in order to update it later
hbm := CreateDIBSection(A_ScreenWidth, A_ScreenHeight) ; Create a gdi bitmap drawing area
hdc := CreateCompatibleDC() ; Get a device context compatible with the screen
obm := SelectObject(hdc, hbm) ; Select the bitmap into the device context
pGraphics := Gdip_GraphicsFromHDC(hdc) ; Get a pointer to the graphics of the bitmap, for use with drawing functions
Gdip_SetSmoothingMode(pGraphics, 4) ; Set the smoothing mode to antialias = 4 to make shapes appear smother
 
Gdip_TranslateWorldTransform(pGraphics, X, Y)
Gdip_RotateWorldTransform(pGraphics, rotation)
 
; Base ellipse
pBrush := Gdip_CreateLineBrushFromRect(0, 0, Width, Height, ARGB, 0xFF000000)
Gdip_FillEllipse(pGraphics, pBrush, 0, 0, Width, Height)
 
; First highlight ellipse
pBrush := Gdip_CreateLineBrushFromRect(Width*0.1, Height*0.01, Width*0.8, Height*0.6, 0x33FFFFFF, 0x00FFFFFF)
Gdip_FillEllipse(pGraphics, pBrush, Width*0.1, Height*0.01, Width*0.8, Height*0.6)
 
; Second highlight ellipse
pBrush := Gdip_CreateLineBrushFromRect(Width*0.3, Height*0.02, Width*0.3, Height*0.2, 0xBBFFFFFF, 0x00FFFFFF)
Gdip_FillEllipse(pGraphics, pBrush, Width*0.3, Height*0.02, Width*0.3, Height*0.2)
 
 
UpdateLayeredWindow(hwnd1, hdc, 0, 0, A_ScreenWidth, A_ScreenHeight)
SelectObject(hdc, obm) ; Select the object back into the hdc
Gdip_DeletePath(Path)
Gdip_DeleteBrush(pBrush)
DeleteObject(hbm) ; Now the bitmap may be deleted
DeleteDC(hdc) ; Also the device context related to the bitmap may be deleted
Gdip_DeleteGraphics(G) ; The graphics may now be deleted
Return
 
Exit:
; gdi+ may now be shutdown on exiting the program
Gdip_Shutdown(pToken)
ExitApp

[edit] BASIC

[edit] QBasic

SCREEN 13 ' enter high-color graphic mode
 
' sets palette colors B/N
FOR i = 0 TO 255
PALETTE 255 - i, INT(i / 4) + INT(i / 4) * 256 + INT(i / 4) * 65536
NEXT i
PALETTE 0, 0
 
' draw the sphere
FOR i = 255 TO 0 STEP -1
x = 50 + i / 3
y = 99
CIRCLE (x, y), i / 3, i
PAINT (x, y), i
NEXT i
 
' wait until keypress
DO: LOOP WHILE INKEY$ = ""
END

[edit] DarkBASIC

Some simple 3D objects are built into DarkBASIC. Creating a sphere only takes 1 line:

MAKE OBJECT SPHERE 1,1

[edit] BBC BASIC

Using Direct3D.

      MODE 8
INSTALL @lib$+"D3DLIB"
D3DTS_VIEW = 2
D3DTS_PROJECTION = 3
D3DRS_SPECULARENABLE = 29
 
SYS "LoadLibrary", @lib$+"D3DX8BBC.DLL" TO d3dx%
IF d3dx%=0 ERROR 100, "Couldn't load D3DX8BBC.DLL"
SYS "GetProcAddress", d3dx%, "D3DXCreateSphere" TO `D3DXCreateSphere`
SYS "GetProcAddress", d3dx%, "D3DXMatrixLookAtLH" TO `D3DXMatrixLookAtLH`
SYS "GetProcAddress", d3dx%, "D3DXMatrixPerspectiveFovLH" TO `D3DXMatrixPerspectiveFovLH`
 
DIM eyepos%(2), lookat%(2), up%(2), mat%(3,3)
 
DIM D3Dlight8{Type%, Diffuse{r%,g%,b%,a%}, Specular{r%,g%,b%,a%}, \
\ Ambient{r%,g%,b%,a%}, Position{x%,y%,z%}, Direction{x%,y%,z%}, \
\ Range%, Falloff%, Attenuation0%, Attenuation1%, Attenuation2%, \
\ Theta%, Phi%}
 
DIM D3Dmaterial8{Diffuse{r%,g%,b%,a%}, Ambient{r%,g%,b%,a%}, \
\ Specular{r%,g%,b%,a%}, Emissive{r%,g%,b%,a%}, Power%}
 
DIM D3Dbasemesh8{QueryInterface%, Addref%, Release%, \
\ DrawSubset%, GetNumFaces%, GetNumVertices%, GetFVF%, \
\ GetDeclaration%, GetOptions%, GetDevice%, \
\ CloneMeshFVF%, CloneMesh%, GetVertexBuffer%, GetIndexBuffer%, \
\ LockVertexBuffer%, UnlockVertexBuffer%, LockIndexBuffer%, \
\ UnlockIndexBuffer%, GetAttributeTable%}
 
DIM D3Ddevice8{QueryInterface%, AddRef%, Release%, TestCooperativeLevel%, \
\ GetAvailableTextureMem%, ResourceManagerDiscardBytes%, GetDirect3D%, \
\ GetDeviceCaps%, GetDisplayMode%, GetCreationParameters%, SetCursorProperties%, \
\ SetCursorPosition%, ShowCursor%, CreateAdditionalSwapChain%, Reset%, \
\ Present%, GetBackBuffer%, GetRasterStatus%, SetGammaRamp%, GetGammaRamp%, \
\ CreateTexture%, CreateVolumeTexture%, CreateCubeTexture%, CreateVertexBuffer%, \
\ CreateIndexBuffer%, CreateRenderTarget%, CreateDepthStencilSurface%, \
\ CreateImageSurface%, CopyRects%, UpdateTexture%, GetFrontBuffer%, \
\ SetRenderTarget%, GetRenderTarget%, GetDepthStencilSurface%, BeginScene%, \
\ EndScene%, Clear%, SetTransform%, GetTransform%, MultiplyTransform%, \
\ SetViewport%, GetViewport%, SetMaterial%, GetMaterial%, SetLight%, GetLight%, \
\ LightEnable%, GetLightEnable%, SetClipPlane%, GetClipPlane%, SetRenderState%, \
\ GetRenderState%, BeginStateBlock%, EndStateBlock%, ApplyStateBlock%, \
\ CaptureStateBlock%, DeleteStateBlock%, CreateStateBlock%, SetClipStatus%, \
\ GetClipStatus%, GetTexture%, SetTexture%, GetTextureStageState%, \
\ SetTextureStageState%, ValidateDevice%, GetInfo%, SetPaletteEntries%, \
\ GetPaletteEntries%, SetCurrentTexturePalette%, GetCurrentTexturePalette%, \
\ DrawPrimitive%, DrawIndexedPrimitive%, DrawPrimitiveUP%, \
\ DrawIndexedPrimitiveUP%, ProcessVertices%, CreateVertexShader%, \
\ SetVertexShader%, GetVertexShader%, DeleteVertexShader%, \
\ SetVertexShaderConstant%, GetVertexShaderConstant%, GetVertexShaderDeclaration%, \
\ GetVertexShaderFunction%, SetStreamSource%, GetStreamSource%, SetIndices%, \
\ GetIndices%, CreatePixelShader%, SetPixelShader%, GetPixelShader%, \
\ DeletePixelShader%, SetPixelShaderConstant%, GetPixelShaderConstant%, \
\ GetPixelShaderFunction%, DrawRectPatch%, DrawTriPatch%, DeletePatch%}
 
pDevice%=FN_initd3d(@hwnd%, 1, 1)
IF pDevice%=0 ERROR 100, "Couldn't create Direct3D8 device"
 !(^D3Ddevice8{}+4) = !pDevice%
 
SYS `D3DXCreateSphere`, pDevice%, FN_f4(1), 50, 50, ^meshSphere%, 0
IF meshSphere% = 0 ERROR 100, "D3DXCreateSphere failed"
 !(^D3Dbasemesh8{}+4) = !meshSphere%
 
REM. Point-source light:
D3Dlight8.Type%=1 : REM. point source
D3Dlight8.Diffuse.r% = FN_f4(1)
D3Dlight8.Diffuse.g% = FN_f4(1)
D3Dlight8.Diffuse.b% = FN_f4(1)
D3Dlight8.Specular.r% = FN_f4(1)
D3Dlight8.Specular.g% = FN_f4(1)
D3Dlight8.Specular.b% = FN_f4(1)
D3Dlight8.Position.x% = FN_f4(2)
D3Dlight8.Position.y% = FN_f4(1)
D3Dlight8.Position.z% = FN_f4(4)
D3Dlight8.Range% = FN_f4(10)
D3Dlight8.Attenuation0% = FN_f4(1)
 
REM. Material:
D3Dmaterial8.Diffuse.r% = FN_f4(0.2)
D3Dmaterial8.Diffuse.g% = FN_f4(0.6)
D3Dmaterial8.Diffuse.b% = FN_f4(1.0)
D3Dmaterial8.Specular.r% = FN_f4(0.4)
D3Dmaterial8.Specular.g% = FN_f4(0.4)
D3Dmaterial8.Specular.b% = FN_f4(0.4)
D3Dmaterial8.Power% = FN_f4(100)
 
fovy = RAD(30)
aspect = 5/4
znear = 1
zfar = 1000
bkgnd% = &7F7F7F
eyepos%() = 0, 0, FN_f4(6)
lookat%() = 0, 0, 0
up%() = 0, FN_f4(1), 0
 
SYS D3Ddevice8.Clear%, pDevice%, 0, 0, 3, bkgnd%, FN_f4(1), 0
SYS D3Ddevice8.BeginScene%, pDevice%
SYS D3Ddevice8.SetLight%, pDevice%, 0, D3Dlight8{}
SYS D3Ddevice8.LightEnable%, pDevice%, 0, 1
SYS D3Ddevice8.SetMaterial%, pDevice%, D3Dmaterial8{}
SYS D3Ddevice8.SetRenderState%, pDevice%, D3DRS_SPECULARENABLE, 1
 
SYS `D3DXMatrixLookAtLH`, ^mat%(0,0), ^eyepos%(0), ^lookat%(0), ^up%(0)
SYS D3Ddevice8.SetTransform%, pDevice%, D3DTS_VIEW, ^mat%(0,0)
 
SYS `D3DXMatrixPerspectiveFovLH`, ^mat%(0,0), FN_f4(fovy), \
\ FN_f4(aspect), FN_f4(znear), FN_f4(zfar)
SYS D3Ddevice8.SetTransform%, pDevice%, D3DTS_PROJECTION, ^mat%(0,0)
 
SYS D3Dbasemesh8.DrawSubset%, meshSphere%, 0
SYS D3Ddevice8.EndScene%, pDevice%
SYS D3Ddevice8.Present%, pDevice%, 0, 0, 0, 0
 
SYS D3Ddevice8.Release%, pDevice%
SYS D3Dbasemesh8.Release%, meshSphere%
SYS "FreeLibrary", d3dx%
END
 
Output:

Sphere BBC.jpeg

[edit] Brlcad

opendb balls.g y            # Create a database to hold our shapes
units cm # Set the unit of measure
in ball.s sph 0 0 0 3 # Create a sphere of radius 3 cm named ball.s with its centre at 0,0,0

[edit] C

The lighting calculation is somewhere between crude and bogus, but hey, I'm shading it with ASCII characters, don't expect too much.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
 
const char *shades = ".:!*oe&#%@";
 
double light[3] = { 30, 30, -50 };
void normalize(double * v)
{
double len = sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
v[0] /= len; v[1] /= len; v[2] /= len;
}
 
double dot(double *x, double *y)
{
double d = x[0]*y[0] + x[1]*y[1] + x[2]*y[2];
return d < 0 ? -d : 0;
}
 
void draw_sphere(double R, double k, double ambient)
{
int i, j, intensity;
double b;
double vec[3], x, y;
for (i = floor(-R); i <= ceil(R); i++) {
x = i + .5;
for (j = floor(-2 * R); j <= ceil(2 * R); j++) {
y = j / 2. + .5;
if (x * x + y * y <= R * R) {
vec[0] = x;
vec[1] = y;
vec[2] = sqrt(R * R - x * x - y * y);
normalize(vec);
b = pow(dot(light, vec), k) + ambient;
intensity = (1 - b) * (sizeof(shades) - 1);
if (intensity < 0) intensity = 0;
if (intensity >= sizeof(shades) - 1)
intensity = sizeof(shades) - 2;
putchar(shades[intensity]);
} else
putchar(' ');
}
putchar('\n');
}
}
 
 
int main()
{
normalize(light);
draw_sphere(20, 4, .1);
draw_sphere(10, 2, .4);
 
return 0;
}
Output:
                               #############%%%%                                 
                       ##&&eeeeeeeeee&&&&&&&####%%%%%%%%                         
                   &&eeooooooooooooooeeeee&&&&######%%%%%%%%                     
                 eeoo**************oooooooeeee&&&&####%%%%%%%%                   
             &&oo**!!!!!!::!!!!!!!!****oooooee&&&&######%%%%%%%%%%               
           eeoo!!!!::::::::::::::!!!!*****ooeeee&&&&####%%%%%%%%%%%%             
         ee**!!::::............::::!!!!***ooooeeee&&######%%%%%%%%%%%%           
       &&oo!!::..................::!!!!*****ooeeee&&&&####%%%%%%%%%%%%%%         
       oo!!::....................::::!!*****ooeeee&&&&####%%%%%%%%%%%%%%         
     ee**!!::....................::::!!*****ooeeee&&&&####%%%%%%%%%%%%%%%%       
   &&oo!!::......................::::!!*****ooeeee&&&&######%%%%%%%%%%%%%%%%     
   ee**!!::......................::::!!*****ooeeee&&&&######%%%%%%%%%%%%%%%%     
 ##oo**!!::......................::!!!!*****ooeeee&&&&####%%%%%%%%%%%%%%%%%%%%   
 &&oo**::::....................::::!!!!***ooooeeee&&&&####%%%%%%%%%%%%%%%%%%%%   
 eeoo**!!::..................::::!!!!*****ooooee&&&&######%%%%%%%%%%%%%%%%%%%%   
 eeoo**!!::................::::!!!!****oooooeeee&&&&######%%%%%%%%%%%%%%%%%%%%   
#eeoo**!!::::............::::!!!!!!****oooeeee&&&&&&######%%%%%%%%%%%%%%%%%%%%%% 
#eeoo**!!!!::::::::::::::::!!!!!!****oooooeeee&&&&######%%%%%%%%%%%%%%%%%%%%%%%% 
#eeoooo**!!!!!!::::::::!!!!!!******ooooeeeee&&&&&&######%%%%%%%%%%%%%%%%%%%%%%%% 
#&&eeoo****!!!!!!!!!!!!!!!!******ooooeeeee&&&&&&######%%%%%%%%%%%%%%%%%%%%%%%%%% 
#&&eeoooo********************ooooooeeee&&&&&&&######%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
#&&&&eeoooooo************ooooooeeeeee&&&&&&&########%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
%##&&eeeeeeooooooooooooooooooeeeeee&&&&&&&########%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
%####&&&&eeeeeeeeeeeeeeeeeeeeee&&&&&&&&#########%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
 %%##&&&&&&eeeeeeeeeeeeeeee&&&&&&&&&&#########%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%   
 %%######&&&&&&&&&&&&&&&&&&&&&&&&###########%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%   
 %%%%########&&&&&&&&&&&&&&############%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%   
 %%%%%%##############################%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%   
   %%%%%%%%######################%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%     
   %%%%%%%%%%%%%%%%####%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%     
     %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%       
       %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%         
       %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%         
         %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%           
           %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%             
             %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%               
                 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%                   
                   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%                     
                       %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%                         
                               %%%%%%%%%%%%%%%%%                                 
                                                                                 
             ::..:::::!!**               
         .............::!!**oo           
     ...................::!!**ooee       
   .......................::!!ooeeee     
   .......................::!!**ooee     
 .........................::!!**ooeeee   
 .........................::!!**ooeeee   
:.........................::!!**ooeeeeee 
........................::!!**ooooeeeeee 
:.......................::!!**ooeeeeeeee 
:.....................::!!****ooeeeeeeee 
!::................:::!!****ooeeeeeeeeee 
*!!::..........::::!!!****ooooeeeeeeeeee 
 **!!::::::::::!!!!*****ooooeeeeeeeeee   
 oo**!!!!!!!!!!*******ooooeeeeeeeeeeee   
   oooo********oooooooeeeeeeeeeeeeee     
   eeeeooooooooooeeeeeeeeeeeeeeeeeee     
     eeeeeeeeeeeeeeeeeeeeeeeeeeeee       
         eeeeeeeeeeeeeeeeeeeee           
             eeeeeeeeeeeee               

[edit] Fun with 3D noise texture

Sphere-perlin.png

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
 
#define MAXD 8
int g[] = { -1, 1, -1, 1 };
/* Perlin-like noise */
inline void
hashed(int *data, int *out, int len) {
# define ror(a, d) ((a << (d)) | (a >> (32 - d)))
register unsigned int h = 0x12345678, tmp;
unsigned int *d = (void*)data;
int i = len;
 
while (i--) {
tmp = *d++;
h += ror(h, 15) ^ ror(tmp, 5);
}
 
h ^= ror(h, 7);
h += ror(h, 23);
h ^= ror(h, 19);
h += ror(h, 11);
h ^= ror(h, 13);
h += ror(h, 17);
# undef ror
for (i = len; i--; ) {
out[i] = g[h & 3];
h >>= 2;
}
}
 
double scale[MAXD], scale_u[MAXD];
void noise_init()
{
int i;
for (i = 1; i < MAXD; i++) {
scale[i] = 1 / (1 + sqrt(i + 1));
scale_u[i] = scale[i] / sqrt(i + 1);
}
}
 
double noise(double *x, int d)
{
# define sum(s, x) for (s = 0, j = 0; j < d; j++) s += x
register int i, j;
int n[MAXD], o[MAXD], g[MAXD], tmp;
double s, r, t, w, ret, u[MAXD];
 
sum(s, x[j]);
s *= scale[d];
 
for (i = 0; i < d; i++) {
o[i] = i;
t = x[i] + s;
u[i] = t - (n[i] = floor(t));
}
o[d] = 0;
 
for (i = 0; i < d - 1; i++)
for (j = i; j < d; j++)
if (u[o[i]] < u[o[j]])
tmp = o[i], o[i] = o[j], o[j] = tmp;
 
ret = w = 0, r = 1;
for (s = 0, j = 0; j < d; j++) s += n[j];
s *= scale_u[d];
 
for (i = 0; i <= d; i++) {
for (j = 0; j < d; j++)
u[j] = x[j] + s - n[j];
 
for (t = (d + 1.) / (2 * d), j = 0; j < d; j++) {
t -= u[j] * u[j];
if (t <= 0) break;
}
 
if (t >= 0) {
r = 0;
hashed(n, g, d);
for (j = 0; j < d; j++)
if (g[j]) r += (g[j] == 1 ? u[j] : -u[j]);
t *= t;
ret += r * t * t;
}
 
if (i < d) {
n[o[i]]++;
s += scale_u[d];
}
}
return ret * (d * d);
}
 
double get_noise2(double x, double y)
{
int i, ws;
double r = 0, v[2];
 
for (i = 1, ws = 0; i <= 128; i <<= 1) {
v[0] = x * i, v[1] = y * i;
r += noise(v, 2);
ws ++;
}
r /= ws;
return r;
}
 
double get_noise3(double x, double y, double z)
{
int i, ws;
double r = 0, v[3], w;
 
for (i = 1, ws = 0; i <= 32; i <<= 1) {
v[0] = x * i, v[1] = y * i, v[2] = z * i;
w = 1./sqrt(i);
r += noise(v, 3) * w;
ws += w;
}
return r / ws;
}
 
 
int main(int c, char** v)
{
unsigned char pix[256 * 256], *p;
int i, j;
double x, y, z, w;
FILE *fp;
 
noise_init();
 
for (p = pix, i = 0; i < 256 * 256; i++) *p++ = 0;
 
for (p = pix, i = 0; i < 256; i++) {
y = (i - 128) / 125.;
for (j = 0; j < 256; j++, p++) {
x = (j - 128) / 125.;
*p = (get_noise2(i/256., j/256.) + 1) / 6 * i;
 
z = 1- x*x - y*y;
if (z < 0) continue;
 
z = sqrt(z);
 
w = get_noise3(x, y, z);
 
w = (w + 1) / 2;
w *= (1 + x - y + z) / 3.5;
if (w < 0) w = 0;
 
*p = w * 255;
}
}
 
fp = fopen("out.pgm", "w+");
fprintf(fp, "P5\n256 256\n255\n");
fwrite(pix, 1, 256 * 256, fp);
fclose(fp);
 
return 0;
}

[edit] C#

Translation of: C
using System;
 
namespace Sphere {
internal class Program {
private const string Shades = ".:!*oe%&#@";
private static readonly double[] Light = {30, 30, -50};
 
private static void Normalize(double[] v) {
double len = Math.Sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
v[0] /= len;
v[1] /= len;
v[2] /= len;
}
 
private static double Dot(double[] x, double[] y) {
double d = x[0]*y[0] + x[1]*y[1] + x[2]*y[2];
return d < 0 ? -d : 0;
}
 
public static void DrawSphere(double r, double k, double ambient) {
var vec = new double[3];
for(var i = (int)Math.Floor(-r); i <= (int)Math.Ceiling(r); i++) {
double x = i + .5;
for(var j = (int)Math.Floor(-2*r); j <= (int)Math.Ceiling(2*r); j++) {
double y = j/2.0 + .5;
if(x*x + y*y <= r*r) {
vec[0] = x;
vec[1] = y;
vec[2] = Math.Sqrt(r*r - x*x - y*y);
Normalize(vec);
double b = Math.Pow(Dot(Light, vec), k) + ambient;
int intensity = (b <= 0)
? Shades.Length - 2
: (int)Math.Max((1 - b)*(Shades.Length - 1), 0);
Console.Write(Shades[intensity]);
}
else
Console.Write(' ');
}
Console.WriteLine();
}
}
 
private static void Main() {
Normalize(Light);
DrawSphere(6, 4, .1);
DrawSphere(10, 2, .4);
Console.ReadKey();
}
}
}

[edit] Clojure

Library: quil
 
(use 'quil.core)
 
(def w 500)
(def h 400)
 
(defn setup []
(background 0))
 
(defn draw []
(push-matrix)
(translate 250 200 0)
(sphere 100)
(pop-matrix))
 
(defsketch main
 :title "sphere"
 :setup setup
 :size [w h]
 :draw draw
 :renderer :opengl)
 
Output:

[1]

[edit] D

Translation of: C
import std.stdio, std.math, std.algorithm, std.numeric;
 
alias V3 = double[3];
immutable light = normalize([30.0, 30.0, -50.0]);
 
V3 normalize(V3 v) pure @nogc {
v[] /= dotProduct(v, v) ^^ 0.5;
return v;
}
 
double dot(in ref V3 x, in ref V3 y) pure nothrow @nogc {
immutable double d = dotProduct(x, y);
return d < 0 ? -d : 0;
}
 
void drawSphere(in double R, in double k, in double ambient) @nogc {
enum shades = ".:!*oe&#%@";
foreach (immutable i; cast(int)floor(-R) .. cast(int)ceil(R) + 1) {
immutable double x = i + 0.5;
foreach (immutable j; cast(int)floor(-2 * R) ..
cast(int)ceil(2 * R) + 1) {
immutable double y = j / 2. + 0.5;
if (x ^^ 2 + y ^^ 2 <= R ^^ 2) {
immutable vec = [x, y, (R^^2 - x^^2 - y^^2) ^^ 0.5]
.normalize;
immutable double b = dot(light, vec) ^^ k + ambient;
int intensity = cast(int)((1 - b) * (shades.length-1));
intensity = min(shades.length - 1, max(intensity, 0));
shades[intensity].putchar;
} else
' '.putchar;
}
'\n'.putchar;
}
}
 
void main() {
drawSphere(20, 4, 0.1);
drawSphere(10, 2, 0.4);
}

[edit] Delphi

Translation of: C

Under Microsoft Windows: If you notice the big sphere loses its roundness, then try increasing the width of the Windows console. By default it’s 80; so put it to something bigger, let’s say 90.

Steps: Run the CMD Windows shell. Then follow this path to setup the new width: Main Menu-> Properties -> Layout -> Window Size -> Width.

 
program DrawASphere;
 
{$APPTYPE CONSOLE}
 
uses
SysUtils,
Math;
 
type
TDouble3 = array[0..2] of Double;
TChar10 = array[0..9] of Char;
 
var
shades: TChar10 = ('.', ':', '!', '*', 'o', 'e', '&', '#', '%', '@');
light: TDouble3 = (30, 30, -50 );
 
procedure normalize(var v: TDouble3);
var
len: Double;
begin
len:= sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
v[0] := v[0] / len;
v[1] := v[1] / len;
v[2] := v[2] / len;
end;
 
function dot(x, y: TDouble3): Double;
begin
Result:= x[0]*y[0] + x[1]*y[1] + x[2]*y[2];
Result:= IfThen(Result < 0, -Result, 0 );
end;
 
procedure drawSphere(R, k, ambient: Double);
var
vec: TDouble3;
x, y, b: Double;
i, j,
intensity: Integer;
begin
for i:= Floor(-R) to Ceil(R) do
begin
x := i + 0.5;
for j:= Floor(-2*R) to Ceil(2 * R) do
begin
y:= j / 2 + 0.5;
if(x * x + y * y <= R * R) then
begin
vec[0]:= x;
vec[1]:= y;
vec[2]:= sqrt(R * R - x * x - y * y);
normalize(vec);
b:= Power(dot(light, vec), k) + ambient;
intensity:= IfThen(b <= 0,
Length(shades) - 2,
Trunc(max( (1 - b) * (Length(shades) - 1), 0 )));
Write(shades[intensity]);
end
else
Write(' ');
end;
Writeln;
end;
end;
 
begin
normalize(light);
drawSphere(19, 4, 0.1);
drawSphere(10, 2, 0.4);
Readln;
end.
 
Output:
                             &&&&&&&&&&#######
                       &eeeeeooeeeeeeee&&&&&&#######
                   eeooo*********oooooeeeee&&&&&#######%
                eo***!!!!!!!!!!!*****ooooeeee&&&&&#######%%
             eo**!!!::::::::::!!!!!****ooooeeee&&&&########%%%
           eo*!!::::........:::::!!!!****oooeeee&&&&########%%%%
         eo*!!::..............:::::!!!***ooooeeee&&&&#########%%%%
       eo*!!::..................:::!!!!***oooeeee&&&&&########%%%%%%
      eo*!::....................::::!!!***ooooeeee&&&&#########%%%%%%
     o**!::.....................::::!!!***ooooeeee&&&&#########%%%%%%%
    eo*!::......................::::!!!***ooooeeee&&&&##########%%%%%%%
   eo*!!::......................:::!!!!***ooooeee&&&&&##########%%%%%%%%
  eo**!!::.....................:::!!!!***ooooeeee&&&&&##########%%%%%%%%%
 &eo**!!::...................::::!!!!****oooeeeee&&&&&##########%%%%%%%%%%
 eeo**!!:::................:::::!!!!****ooooeeee&&&&&##########%%%%%%%%%%%
&eoo**!!!::::............:::::!!!!****oooooeeee&&&&&###########%%%%%%%%%%%%
&eeo***!!!::::::::::::::::::!!!!!****ooooeeeee&&&&&&##########%%%%%%%%%%%%%
&eeoo***!!!!::::::::::::!!!!!!*****oooooeeeee&&&&&&###########%%%%%%%%%%%%%
&&eeoo****!!!!!!!!!!!!!!!!!!*****oooooeeeee&&&&&&############%%%%%%%%%%%%%%
&&eeeooo*****!!!!!!!!!!*******ooooooeeeeee&&&&&&############%%%%%%%%%%%%%%%
#&&eeeoooo*****************oooooooeeeeee&&&&&&&############%%%%%%%%%%%%%%%%
#&&&eeeeoooooooooooooooooooooooeeeeeee&&&&&&&#############%%%%%%%%%%%%%%%%%
##&&&&eeeeeoooooooooooooooeeeeeeeee&&&&&&&&##############%%%%%%%%%%%%%%%%%%
 ###&&&&eeeeeeeeeeeeeeeeeeeeeee&&&&&&&&&&##############%%%%%%%%%%%%%%%%%%%
 ####&&&&&&&eeeeeeeeeeeeeee&&&&&&&&&&&################%%%%%%%%%%%%%%%%%%%%
  #####&&&&&&&&&&&&&&&&&&&&&&&&&&&&#################%%%%%%%%%%%%%%%%%%%%%
   ########&&&&&&&&&&&&&&&&&&&####################%%%%%%%%%%%%%%%%%%%%%%
    ############################################%%%%%%%%%%%%%%%%%%%%%%%
     %#######################################%%%%%%%%%%%%%%%%%%%%%%%%%
      %%##################################%%%%%%%%%%%%%%%%%%%%%%%%%%%
       %%%%###########################%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
         %%%%%%#################%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
           %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
             %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                       %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                             %%%%%%%%%%%%%%%%%

             ::...:::!!!*o
         ..............::!!*oo
      ..................::!!**ooe
    .....................::!!**ooee
   .......................::!!**ooee
  ........................::!!**oooee
 .........................::!!**oooeee
:........................::!!!**oooeeee
........................::!!!**ooooeeee
:......................::!!!***oooeeeee
:....................:::!!!***oooeeeeee
!:.................:::!!!****oooeeeeeee
*!:::...........::::!!!!***ooooeeeeeeee
 *!!!:::::::::::!!!!!****oooooeeeeeeee
  o**!!!!!!!!!!!!!*****oooooeeeeeeeee
   oo**************ooooooeeeeeeeeeee
    eoooooooooooooooooeeeeeeeeeeeee
      eeeooooooooeeeeeeeeeeeeeeee
         eeeeeeeeeeeeeeeeeeeee
             eeeeeeeeeeeee

[edit] DWScript

PBM output magnified 5 times
Translation of: C
but adapted to spit out a PGM image
 
type
TFloat3 = array[0..2] of Float;
 
var
light : TFloat3 = [ 30, 30, -50 ];
 
procedure normalize(var v : TFloat3);
var
len: Float;
begin
len := sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
v[0] /= len;
v[1] /= len;
v[2] /= len;
end;
 
function dot(x, y : TFloat3) : Float;
begin
Result := x[0]*y[0] + x[1]*y[1] + x[2]*y[2];
if Result<0 then
Result:=-Result
else Result:=0;
end;
 
procedure drawSphere(R, k, ambient : Float);
var
vec : TFloat3;
x, y, b : Float;
i, j, size, intensity : Integer;
begin
size:=Trunc(Ceil(R)-Floor(-R)+1);
PrintLn('P2');
PrintLn(IntToStr(size)+' '+IntToStr(size));
PrintLn('255');
for i := Floor(-R) to Ceil(R) do begin
x := i + 0.5;
for j := Floor(-R) to Ceil(R) do begin
y := j + 0.5;
if (x * x + y * y <= R * R) then begin
vec[0] := x;
vec[1] := y;
vec[2] := sqrt(R * R - x * x - y * y);
normalize(vec);
b := Power(dot(light, vec), k) + ambient;
intensity := ClampInt( Round(b*255), 0, 255);
Print(intensity);
Print(' ')
end else Print('0 ');
end;
PrintLn('');
end;
end;
 
normalize(light);
drawSphere(19, 4, 0.1);
 

[edit] Go

Output png
Translation of: C

Using image library rather than ASCII art.

package main
 
import (
"fmt"
"image"
"image/color"
"image/png"
"math"
"os"
)
 
type vector [3]float64
 
func normalize(v *vector) {
invLen := 1 / math.Sqrt(dot(v, v))
v[0] *= invLen
v[1] *= invLen
v[2] *= invLen
}
 
func dot(x, y *vector) float64 {
return x[0]*y[0] + x[1]*y[1] + x[2]*y[2]
}
 
func drawSphere(r int, k, amb float64, dir *vector) *image.Gray {
w, h := r*4, r*3
img := image.NewGray(image.Rect(-w/2, -h/2, w/2, h/2))
vec := new(vector)
for x := -r; x < r; x++ {
for y := -r; y < r; y++ {
if z := r*r - x*x - y*y; z >= 0 {
vec[0] = float64(x)
vec[1] = float64(y)
vec[2] = math.Sqrt(float64(z))
normalize(vec)
s := dot(dir, vec)
if s < 0 {
s = 0
}
lum := 255 * (math.Pow(s, k) + amb) / (1 + amb)
if lum < 0 {
lum = 0
} else if lum > 255 {
lum = 255
}
img.SetGray(x, y, color.Gray{uint8(lum)})
}
}
}
return img
}
 
func main() {
dir := &vector{-30, -30, 50}
normalize(dir)
img := drawSphere(200, 1.5, .2, dir)
f, err := os.Create("sphere.png")
if err != nil {
fmt.Println(err)
return
}
if err = png.Encode(f, img); err != nil {
fmt.Println(err)
}
if err = f.Close(); err != nil {
fmt.Println(err)
}
}

[edit] HTML

See Draw_a_sphere#Javascript

[edit] Haskell

Sphere Haskell.png
import Graphics.Rendering.OpenGL.GL
import Graphics.UI.GLUT.Objects
import Graphics.UI.GLUT
 
setProjection :: IO ()
setProjection = do
matrixMode $= Projection
ortho (-1) 1 (-1) 1 0 (-1)
 
grey1,grey9,red,white :: Color4 GLfloat
grey1 = Color4 0.1 0.1 0.1 1
grey9 = Color4 0.9 0.9 0.9 1
red = Color4 1 0 0 1
white = Color4 1 1 1 1
 
setLights :: IO ()
setLights = do
let l = Light 0
ambient l $= grey1
diffuse l $= white
specular l $= white
position l $= Vertex4 (-4) 4 3 (0 :: GLfloat)
light l $= Enabled
lighting $= Enabled
 
setMaterial :: IO ()
setMaterial = do
materialAmbient Front $= grey1
materialDiffuse Front $= red
materialSpecular Front $= grey9
materialShininess Front $= (32 :: GLfloat)
 
display :: IO()
display = do
clear [ColorBuffer]
renderObject Solid $ Sphere' 0.8 64 64
swapBuffers
 
main :: IO()
main = do
_ <- getArgsAndInitialize
_ <- createWindow "Sphere"
clearColor $= Color4 0.0 0.0 0.0 0.0
setProjection
setLights
setMaterial
displayCallback $= display
mainLoop

[edit] Icon and Unicon

Unicon provides a built-in interface to openGL including some higher level abstractions (for more information see Unicon Technical References, 3D Graphics). The example below draws a blue sphere on a black background and waits for input to quit.
Unicon Sphere
procedure main()
W := open("Demo", "gl", "size=400,400", "bg=black") | stop("can't open window!")
WAttrib(W, "slices=40", "rings=40", "light0=on, ambient white; diffuse gold; specular gold; position 5, 0, 0" )
Fg(W, "emission blue")
DrawSphere(W, 0, 0, -5, 1)
Event(W)
end

[edit] J

J Sphere

The simplest way to draw a sphere is to run the sphere demo code from J's simple demos. (This assumes J version 6.)

Normally you would bring up this demo by using the menu system:

Studio
 > Demos...
  > opengl simple... [ok]
    > sphere [Run]
load 'system/examples/graphics/opengl/simple/sphere.ijs'

[edit] Raytracing Solution

Here's a version using raytracing computed in J. luminosity is an array of luminosity values with theoretical maximum 1 and minimum 0, and viewmat is used to display this.

'R k ambient' =. 10 2 0.4
light =. (% +/&.:*:) 30 30 _50
pts =. (0&*^:(0={:))@:(,,(0>.(*:R)-+)&.*:)"0/~ i:15j200
luminosity =. (>:ambient) %~ (ambient * * +/&.:*:"1 pts) + k^~ 0>. R%~ pts +/@:*"1 -light
 
load 'viewmat'
togreyscale =. 256 #. [: <. 255 255 255 *"1 0 ]
'rgb' viewmat togreyscale luminosity

[edit] Java

Translation of: C
public class Sphere{
static char[] shades = {'.', ':', '!', '*', 'o', 'e', '&', '#', '%', '@'};
 
static double[] light = { 30, 30, -50 };
private static void normalize(double[] v){
double len = Math.sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
v[0] /= len; v[1] /= len; v[2] /= len;
}
 
private static double dot(double[] x, double[] y){
double d = x[0]*y[0] + x[1]*y[1] + x[2]*y[2];
return d < 0 ? -d : 0;
}
 
public static void drawSphere(double R, double k, double ambient){
double[] vec = new double[3];
for(int i = (int)Math.floor(-R); i <= (int)Math.ceil(R); i++){
double x = i + .5;
for(int j = (int)Math.floor(-2 * R); j <= (int)Math.ceil(2 * R); j++){
double y = j / 2. + .5;
if(x * x + y * y <= R * R) {
vec[0] = x;
vec[1] = y;
vec[2] = Math.sqrt(R * R - x * x - y * y);
normalize(vec);
double b = Math.pow(dot(light, vec), k) + ambient;
int intensity = (b <= 0) ?
shades.length - 2 :
(int)Math.max((1 - b) * (shades.length - 1), 0);
System.out.print(shades[intensity]);
} else
System.out.print(' ');
}
System.out.println();
}
}
 
public static void main(String[] args){
normalize(light);
drawSphere(20, 4, .1);
drawSphere(10, 2, .4);
}
}
Output:
                               &&&&&&&&&&#######                                 
                        &eeeeeeeeeeeeeeee&&&&&&#######%                          
                    &eoooo*******oooooooeeeee&&&&&########%                      
                 eoo****!!!!!!!!******oooooeeee&&&&&########%%                   
              eoo**!!!!::::::::!!!!!*****ooooeeee&&&&&########%%%                
            eo**!!::::::...:::::::!!!!!***ooooeeee&&&&&########%%%%              
          eo*!!:::.............:::::!!!!***ooooeeee&&&&&########%%%%%            
        eo*!!:::.................::::!!!!***ooooeeee&&&&#########%%%%%%          
       eo*!!::....................::::!!!****oooeeee&&&&&#########%%%%%%         
     &o**!::......................::::!!!****oooeeee&&&&&##########%%%%%%%       
    &o**!::.......................::::!!!****oooeeee&&&&&##########%%%%%%%%      
   &oo*!!::.......................:::!!!!***ooooeeee&&&&&##########%%%%%%%%%     
  &eo*!!::.......................::::!!!****ooooeeee&&&&&##########%%%%%%%%%%    
  eo**!!::......................::::!!!!***ooooeeeee&&&&&##########%%%%%%%%%%    
 &eo**!!:::...................:::::!!!!****ooooeeee&&&&&###########%%%%%%%%%%%   
 eeo**!!::::................:::::!!!!!****ooooeeee&&&&&&###########%%%%%%%%%%%   
&eeo***!!:::::...........::::::!!!!!****oooooeeee&&&&&&###########%%%%%%%%%%%%%  
&eeoo**!!!!::::::::::::::::::!!!!!*****ooooeeeee&&&&&&############%%%%%%%%%%%%%  
&eeooo***!!!!::::::::::::!!!!!!!*****oooooeeeee&&&&&&############%%%%%%%%%%%%%%  
&&eeooo***!!!!!!!!!!!!!!!!!!!******oooooeeeeee&&&&&&############%%%%%%%%%%%%%%%  
&&eeeooo******!!!!!!!!!!********ooooooeeeeee&&&&&&&############%%%%%%%%%%%%%%%%  
#&&eeeooooo******************oooooooeeeeee&&&&&&&#############%%%%%%%%%%%%%%%%%  
#&&&eeeeoooooooo******oooooooooooeeeeeee&&&&&&&&#############%%%%%%%%%%%%%%%%%%  
##&&&&eeeeeooooooooooooooooooeeeeeeee&&&&&&&&&##############%%%%%%%%%%%%%%%%%%%  
 ##&&&&&eeeeeeeeeeeeeeeeeeeeeeeeee&&&&&&&&&################%%%%%%%%%%%%%%%%%%%   
 ####&&&&&&eeeeeeeeeeeeeeeeeee&&&&&&&&&&&################%%%%%%%%%%%%%%%%%%%%%   
  #####&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&#################%%%%%%%%%%%%%%%%%%%%%%    
  %#######&&&&&&&&&&&&&&&&&&&&&&&&###################%%%%%%%%%%%%%%%%%%%%%%%%    
   %###########&&&&&&&&&&&&&#######################%%%%%%%%%%%%%%%%%%%%%%%%%     
    %############################################%%%%%%%%%%%%%%%%%%%%%%%%%%      
     %%#######################################%%%%%%%%%%%%%%%%%%%%%%%%%%%%       
       %%#################################%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%         
        %%%%%#########################%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%          
          %%%%%%%%#############%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%            
            %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%              
              %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%                
                 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%                   
                    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%                      
                        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%                          
                               %%%%%%%%%%%%%%%%%                                 
                                                                                 
             ::...:::!!!*o               
         ..............::!!*oo           
      ..................::!!**ooe        
    .....................::!!**ooee      
   .......................::!!**ooee     
  ........................::!!**oooee    
 .........................::!!**oooeee   
:........................::!!!**oooeeee  
........................::!!!**ooooeeee  
:......................::!!!***oooeeeee  
:....................:::!!!***oooeeeeee  
!:.................:::!!!****oooeeeeeee  
*!:::...........::::!!!!***ooooeeeeeeee  
 *!!!:::::::::::!!!!!****oooooeeeeeeee   
  o**!!!!!!!!!!!!!*****oooooeeeeeeeee    
   oo**************ooooooeeeeeeeeeee     
    eoooooooooooooooooeeeeeeeeeeeee      
      eeeooooooooeeeeeeeeeeeeeeee        
         eeeeeeeeeeeeeeeeeeeee           
             eeeeeeeeeeeee               
                                         

[edit] JavaScript

Translation of: C

This Javascript entry uses an HTML wrapper to offer easy running and some interactivity. It is made as such, though, that the entire HTML wrapper can be removed (except for a canvas with id c) and still work. If you remove the HTML, call the draw_sphere function to draw the thing.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Draw a sphere</title>
<script>
var light=[30,30,-50],gR,gk,gambient;
 
function normalize(v){
var len=Math.sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
v[0]/=len;
v[1]/=len;
v[2]/=len;
return v;
}
 
function dot(x,y){
var d=x[0]*y[0]+x[1]*y[1]+x[2]*y[2];
return d<0?-d:0;
}
 
function draw_sphere(R,k,ambient){
var i,j,intensity,b,vec,x,y,cvs,ctx,imgdata,idx;
cvs=document.getElementById("c");
ctx=cvs.getContext("2d");
cvs.width=cvs.height=2*Math.ceil(R)+1;
imgdata=ctx.createImageData(2*Math.ceil(R)+1,2*Math.ceil(R)+1);
idx=0;
for(i=Math.floor(-R);i<=Math.ceil(R);i++){
x=i+.5;
for(j=Math.floor(-R);j<=Math.ceil(R);j++){
y=j+.5;
if(x*x+y*y<=R*R){
vec=[x,y,Math.sqrt(R*R-x*x-y*y)];
vec=normalize(vec);
b=Math.pow(dot(light,vec),k)+ambient;
intensity=(1-b)*256;
if(intensity<0)intensity=0;
if(intensity>=256)intensity=255;
imgdata.data[idx++]=imgdata.data[idx++]=255-~~(intensity); //RG
imgdata.data[idx++]=imgdata.data[idx++]=255; //BA
} else {
imgdata.data[idx++]=imgdata.data[idx++]=imgdata.data[idx++]=imgdata.data[idx++]=255; //RGBA
}
}
}
ctx.putImageData(imgdata,0,0);
}
 
light=normalize(light);
</script>
</head>
<body onload="gR=200;gk=4;gambient=.2;draw_sphere(gR,gk,gambient)">
R=<input type="range" id="R" name="R" min="5" max="500" value="200" step="5" onchange="document.getElementById('lR').innerHTML=gR=parseFloat(this.value);draw_sphere(gR,gk,gambient)">
<label for="R" id="lR">200</label><br>
k=<input type="range" id="k" name="k" min="0" max="10" value="4" step=".25" onchange="document.getElementById('lk').innerHTML=gk=parseFloat(this.value);draw_sphere(gR,gk,gambient)">
<label for="k" id="lk">4</label><br>
ambient=<input type="range" id="ambient" name="ambient" min="0" max="1" value=".2" step=".05" onchange="document.getElementById('lambient').innerHTML=gambient=parseFloat(this.value);draw_sphere(gR,gk,gambient)">
<label for="ambient" id="lambient">0.2</label><br>
<canvas id="c">Unsupportive browser...</canvas><br>
</body>
</html>

[edit]

Drawing a sphere is actually very simple in logo, using the perspective function to make life easier.

Works with: MSWlogo
to sphere :r
cs perspective ht ;making the room ready to use
repeat 180 [polystart circle :r polyend down 1]
polyview
end

[edit] Liberty BASIC

 
WindowWidth =420
WindowHeight =460
 
nomainwin
 
open "Sphere" for graphics_nsb_nf as #w
 
#w "down ; fill lightgray"
 
xS =200
yS =200
for radius =150 to 0 step -1
level$ =str$( int( 256 -256 *radius /150))
c$ =level$ +" " +level$ +" " +level$
#w "color "; c$
#w "backcolor "; c$
#w "place "; xS; " "; yS
xS =xS -0.5
yS =yS -0.2
#w "circlefilled "; radius
next radius
 
#w "flush"
wait
close #w
end
 

[edit] Lua

Translation of: C
Works with: Lua version 5.1.4
require ("math")
 
shades = {'.', ':', '!', '*', 'o', 'e', '&', '#', '%', '@'}
 
function normalize (vec)
len = math.sqrt(vec[1]^2 + vec[2]^2 + vec[3]^2)
return {vec[1]/len, vec[2]/len, vec[3]/len}
end
 
light = normalize{30, 30, -50}
 
function dot (vec1, vec2)
d = vec1[1]*vec2[1] + vec1[2]*vec2[2] + vec1[3]*vec2[3]
return d < 0 and -d or 0
end
 
function draw_sphere (radius, k, ambient)
for i = math.floor(-radius),-math.floor(-radius) do
x = i + .5
local line = ''
for j = math.floor(-2*radius),-math.floor(-2*radius) do
y = j / 2 + .5
if x^2 + y^2 <= radius^2 then
vec = normalize{x, y, math.sqrt(radius^2 - x^2 - y^2)}
b = dot(light,vec) ^ k + ambient
intensity = math.floor ((1 - b) * #shades)
line = line .. (shades[intensity] or shades[1])
else
line = line .. ' '
end
end
print (line)
end
end
 
draw_sphere (20, 4, 0.1)
draw_sphere (10, 2, 0.4)
Output:
                               &&&&&&&&&&&&#####                                 
                        &eeeoooooooooeeeeee&&&&&#######                          
                    eooo*************oooooeeee&&&&&########                      
                 eo**!!!!!!!!!!!!!!!*****ooooeeee&&&&#########                   
              eo*!!!:::::...:::::::!!!!****oooeeee&&&&&##########                
            o**!:::..............::::!!!!***ooooeee&&&&&###########              
          o*!!::...................::::!!!***ooooeee&&&&&############            
        eo*!::......................::::!!!***oooeeee&&&&&#############          
       o*!::.........................:::!!!***ooooeee&&&&&##############         
     &o*!::..........................:::!!!***ooooeeee&&&&###############%       
    eo*!::...........................:::!!!***ooooeeee&&&&&###############%      
   eo*!::............................:::!!!***ooooeeee&&&&&###############%%     
  &o*!!::...........................:::!!!!***oooeeee&&&&&#################%%    
  eo*!!:...........................::::!!!***ooooeeee&&&&&#################%%    
 eo**!!::.........................::::!!!****oooeeee&&&&&&#################%%%   
 eo**!!::.......................::::!!!!****oooeeeee&&&&&##################%%%   
&eo**!!:::....................:::::!!!!***ooooeeeee&&&&&&##################%%%%  
&eoo**!!::::................:::::!!!!****ooooeeeee&&&&&&###################%%%%  
&eoo***!!!:::::........:::::::!!!!!****oooooeeeee&&&&&&###################%%%%%  
&eeoo***!!!!:::::::::::::::!!!!!!*****ooooeeeee&&&&&&&####################%%%%%  
&&eeoo****!!!!!!!!!!!!!!!!!!!!*****oooooeeeeee&&&&&&######################%%%%%  
&&eeeooo******!!!!!!!!!!!*******ooooooeeeeee&&&&&&&######################%%%%%%  
#&&eeeooooo******************oooooooeeeeee&&&&&&&#######################%%%%%%%  
##&&&eeeeoooooooooo*ooooooooooooeeeeeeee&&&&&&&&#######################%%%%%%%%  
 ##&&&eeeeeeooooooooooooooooeeeeeeeee&&&&&&&&&########################%%%%%%%%   
 ###&&&&&eeeeeeeeeeeeeeeeeeeeeeee&&&&&&&&&&##########################%%%%%%%%%   
  ####&&&&&&&eeeeeeeeeeeeeee&&&&&&&&&&&&############################%%%%%%%%%    
  ######&&&&&&&&&&&&&&&&&&&&&&&&&&&&&##############################%%%%%%%%%%    
   ########&&&&&&&&&&&&&&&&&&&&&&################################%%%%%%%%%%%     
    ###############&&&&&#######################################%%%%%%%%%%%%      
     #########################################################%%%%%%%%%%%%       
       #####################################################%%%%%%%%%%%%         
        #################################################%%%%%%%%%%%%%%          
          #############################################%%%%%%%%%%%%%%            
            ########################################%%%%%%%%%%%%%%%              
              ##################################%%%%%%%%%%%%%%%%%                
                 %##########################%%%%%%%%%%%%%%%%%%                   
                    %%%%############%%%%%%%%%%%%%%%%%%%%%%%                      
                        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%                          
                               %%%%%%%%%%%%%%%%%                                 
                                                                                 
             ........::!!*               
         ...............::!!*o           
      ....................::!**oo        
    .......................::!**ooo      
   ........................::!!**ooo     
  .........................::!!**oooo    
 ..........................::!!**ooooe   
...........................::!!**ooooee  
..........................::!!***ooooee  
.........................::!!!**oooooee  
.......................:::!!!**oooooeee  
:.....................::!!!***ooooooeee  
!::................:::!!!!***ooooooeeee  
 !!::..........:::::!!!****ooooooeeeee   
  *!!!::::::::::!!!!!****oooooooeeeee    
   o***!!!!!!!!!******ooooooooeeeeee     
    ooo***********ooooooooooeeeeeee      
      oooooooooooooooooooeeeeeeee        
         eooooooooooeeeeeeeeee           
             eeeeeeeeeeeee               
                                         

[edit] Mathematica

Mathematica has many 3D drawing capabilities. To create a sphere with radius one centered at (0,0,0):

Graphics3D[Sphere[{0,0,0},1]]

[edit] Maxima

/* Two solutions */
plot3d(1, [theta, 0, %pi], [phi, 0, 2 * %pi],
[transform_xy, spherical_to_xyz], [grid, 30, 60],
[box, false], [legend, false])$
 
load(draw)$
draw3d(xu_grid=30, yv_grid=60, surface_hide=true,
parametric_surface(cos(phi)*sin(theta),
sin(phi)*sin(theta),
cos(theta),
theta, 0, %pi, phi, 0, 2 * %pi))$

[edit] Nimrod

Translation of: C
import math
 
type Point = tuple[x,y,z: float]
 
const shades = ".:!*oe&#%@"
 
proc normalize(x, y, z: float): Point =
let len = sqrt(x*x + y*y + z*z)
(x / len, y / len, z / len)
 
proc dot(a, b: Point): float =
result = max(0, - a.x*b.x - a.y*b.y - a.z*b.z)
 
let light = normalize(30.0, 30.0, -50.0)
 
proc drawSphere(r, k, ambient) =
for i in -r .. r:
let x = i.float + 0.5
for j in -2*r .. 2*r:
let y = j.float / 2.0 + 0.5
if x*x + y*y <= float r*r:
let
v = normalize(x, y, sqrt(float(r*r) - x*x - y*y))
b = pow(dot(light, v), k) + ambient
i = clamp(int((1.0 - b) * shades.high.float), 0, shades.high)
stdout.write shades[i]
else: stdout.write ' '
stdout.write "\n"
 
drawSphere 20, 4.0, 0.1
drawSphere 10, 2.0, 0.4
Output:
                               &&&&&&&&&&#######                                 
                        &eeeeeeeeeeeeeeee&&&&&&#######%                          
                    &eoooo*******oooooooeeeee&&&&&########%                      
                 eoo****!!!!!!!!******oooooeeee&&&&&########%%                   
              eoo**!!!!::::::::!!!!!*****ooooeeee&&&&&########%%%                
            eo**!!::::::...:::::::!!!!!***ooooeeee&&&&&########%%%%              
          eo*!!:::.............:::::!!!!***ooooeeee&&&&&########%%%%%            
        eo*!!:::.................::::!!!!***ooooeeee&&&&#########%%%%%%          
       eo*!!::....................::::!!!****oooeeee&&&&&#########%%%%%%         
     &o**!::......................::::!!!****oooeeee&&&&&##########%%%%%%%       
    &o**!::.......................::::!!!****oooeeee&&&&&##########%%%%%%%%      
   &oo*!!::.......................:::!!!!***ooooeeee&&&&&##########%%%%%%%%%     
  &eo*!!::.......................::::!!!****ooooeeee&&&&&##########%%%%%%%%%%    
  eo**!!::......................::::!!!!***ooooeeeee&&&&&##########%%%%%%%%%%    
 &eo**!!:::...................:::::!!!!****ooooeeee&&&&&###########%%%%%%%%%%%   
 eeo**!!::::................:::::!!!!!****ooooeeee&&&&&&###########%%%%%%%%%%%   
&eeo***!!:::::...........::::::!!!!!****oooooeeee&&&&&&###########%%%%%%%%%%%%%  
&eeoo**!!!!::::::::::::::::::!!!!!*****ooooeeeee&&&&&&############%%%%%%%%%%%%%  
&eeooo***!!!!::::::::::::!!!!!!!*****oooooeeeee&&&&&&############%%%%%%%%%%%%%%  
&&eeooo***!!!!!!!!!!!!!!!!!!!******oooooeeeeee&&&&&&############%%%%%%%%%%%%%%%  
&&eeeooo******!!!!!!!!!!********ooooooeeeeee&&&&&&&############%%%%%%%%%%%%%%%%  
#&&eeeooooo******************oooooooeeeeee&&&&&&&#############%%%%%%%%%%%%%%%%%  
#&&&eeeeoooooooo******oooooooooooeeeeeee&&&&&&&&#############%%%%%%%%%%%%%%%%%%  
##&&&&eeeeeooooooooooooooooooeeeeeeee&&&&&&&&&##############%%%%%%%%%%%%%%%%%%%  
 ##&&&&&eeeeeeeeeeeeeeeeeeeeeeeeee&&&&&&&&&################%%%%%%%%%%%%%%%%%%%   
 ####&&&&&&eeeeeeeeeeeeeeeeeee&&&&&&&&&&&################%%%%%%%%%%%%%%%%%%%%%   
  #####&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&#################%%%%%%%%%%%%%%%%%%%%%%    
  %#######&&&&&&&&&&&&&&&&&&&&&&&&###################%%%%%%%%%%%%%%%%%%%%%%%%    
   %###########&&&&&&&&&&&&&#######################%%%%%%%%%%%%%%%%%%%%%%%%%     
    %############################################%%%%%%%%%%%%%%%%%%%%%%%%%%      
     %%#######################################%%%%%%%%%%%%%%%%%%%%%%%%%%%%       
       %%#################################%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%         
        %%%%%#########################%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%          
          %%%%%%%%#############%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%            
            %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%              
              %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%                
                 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%                   
                    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%                      
                        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%                          
                               %%%%%%%%%%%%%%%%%                                 
                                                                                 
             ::...:::!!!*o               
         ..............::!!*oo           
      ..................::!!**ooe        
    .....................::!!**ooee      
   .......................::!!**ooee     
  ........................::!!**oooee    
 .........................::!!**oooeee   
:........................::!!!**oooeeee  
........................::!!!**ooooeeee  
:......................::!!!***oooeeeee  
:....................:::!!!***oooeeeeee  
!:.................:::!!!****oooeeeeeee  
*!:::...........::::!!!!***ooooeeeeeeee  
 *!!!:::::::::::!!!!!****oooooeeeeeeee   
  o**!!!!!!!!!!!!!*****oooooeeeeeeeee    
   oo**************ooooooeeeeeeeeeee     
    eoooooooooooooooooeeeeeeeeeeeee      
      eeeooooooooeeeeeeeeeeeeeeee        
         eeeeeeeeeeeeeeeeeeeee           
             eeeeeeeeeeeee

[edit] Openscad

Drawing a sphere is easy in openscad:

// This will produce a sphere of radius 5
sphere(5);

[edit] Pascal

Works with: Free_Pascal

After changing "{$APPTYPE CONSOLE}" to "{$mode delphi}" or "{$mode objfpc}" the Delphi example works with FreePascal.


[edit] Perl

Translation of: Perl 6

This produces a PGM image which can't be uploaded on rosettacode at the moment. It looks similar as the Perl 6 solution, though.

use strict;
use warnings;
 
my $x = my $y = 255;
$x |= 1; # must be odd
my $depth = 255;
 
my $light = Vector->new(rand, rand, rand)->normalized;
 
print "P2\n$x $y\n$depth\n";
 
my ($r, $ambient) = (($x - 1)/2, 0);
my ($r2) = $r ** 2;
{
for my $x (-$r .. $r) {
my $x2 = $x**2;
for my $y (-$r .. $r) {
my $y2 = $y**2;
my $pixel = 0;
if ($x2 + $y2 < $r2) {
my $v = Vector->new($x, $y, sqrt($r2 - $x2 - $y2))->normalized;
my $I = $light . $v + $ambient;
$I = $I < 0 ? 0 : $I > 1 ? 1 : $I;
$pixel = int($I * $depth);
}
print $pixel;
print $y == $r ? "\n" : " ";
}
}
}
 
package Vector {
sub new {
my $class = shift;
bless ref($_[0]) eq 'Array' ? $_[0] : [ @_ ], $class;
}
sub normalized {
my $this = shift;
my $norm = sqrt($this . $this);
ref($this)->new( map $_/$norm, @$this );
}
use overload q{.} => sub {
my ($a, $b) = @_;
my $sum = 0;
for (0 .. @$a - 1) {
$sum += $a->[$_] * $b->[$_]
}
return $sum;
},
q{""} => sub { sprintf "Vector:[%s]", join ' ', @{shift()} };
}

[edit] Perl 6

Translation of: C

The C code is modified to output a .pgm file.

Sphere-perl6.png
my $x = my $y = 255;
$x +|= 1; # must be odd
 
my @light = normalize([ 3, 2, -5 ]);
 
my $depth = 255;
 
sub MAIN ($outfile = 'sphere-perl6.pgm') {
my $out = open( $outfile, :w, :bin ) or die "$!\n";
$out.say("P5\n$x $y\n$depth"); # .pgm header
$out.write( Blob.new(draw_sphere( ($x-1)/2, .9, .2) ) );
$out.close;
}
 
sub normalize (@vec) { return @vec »/» ([+] @vec Z* @vec).sqrt }
 
sub dot (@x, @y) { return -([+] @x Z* @y) max 0 }
 
sub draw_sphere ( $rad, $k, $ambient ) {
my @pixels;
my $r2 = $rad * $rad;
my @range = -$rad .. $rad;
for @range X @range -> $x, $y {
if (my $x2 = $x * $x) + (my $y2 = $y * $y) < $r2 {
my @vector = normalize([$x, $y, ($r2 - $x2 - $y2).sqrt]);
my $intensity = dot(@light, @vector) ** $k + $ambient;
my $pixel = (0 max ($intensity * $depth).Int) min $depth;
@pixels.push($pixel);
}
else {
@pixels.push(0);
}
}
return @pixels;
}

[edit] PicoLisp

Library: GLUT

This is for the 64-bit version.

(load "@lib/openGl.l")
 
(glutInit)
(glutInitDisplayMode (| GLUT_RGBA GLUT_DOUBLE GLUT_ALPHA GLUT_DEPTH))
(glutInitWindowSize 400 400)
(glutCreateWindow "Sphere")
 
(glEnable GL_LIGHTING)
(glEnable GL_LIGHT0)
(glLightiv GL_LIGHT0 GL_POSITION (10 10 -10 0))
 
(glEnable GL_COLOR_MATERIAL)
(glColorMaterial GL_FRONT_AND_BACK GL_AMBIENT_AND_DIFFUSE)
 
(glClearColor 0.3 0.3 0.5 0)
(glColor4f 0.0 0.8 0.0 1.0)
 
(displayPrg
(glClear (| GL_COLOR_BUFFER_BIT GL_DEPTH_BUFFER_BIT))
(glutSolidSphere 0.9 40 32)
(glFlush)
(glutSwapBuffers) )
 
# Exit upon mouse click
(mouseFunc '((Btn State X Y) (bye)))
(glutMainLoop)
Translation of: C
(scl 24)
 
(setq *Shades
(list "." ":" "!" "*" "o" "e" "&" "#" "%" "@"))
 
(setq *Light
(list 30.0 30.0 -50.0))
 
(de normalize (V)
(let Len
(sqrt
(sum
(quote (X)
(** X 2))
V))
(mapcar
(quote (X)
(*/ X 1.0 Len))
V)))
 
(de dot (X Y)
(let D (sum (quote (A B) (*/ A B 1.0)) X Y)
(if (< D 0) (- D) 0)))
 
(de floor (N)
(* 1.0 (*/ (- N 0.5) 1.0)))
 
(de ceil (N)
(* 1.0 (*/ (+ N 0.5) 1.0)))
 
(de drawSphere (R K Ambient)
(let Vec NIL
(for (I (floor (- R)) (<= I (ceil R)) (+ I 1.0))
(let X (+ I 0.5)
(for (J (floor (* -2 R)) (<= J (ceil (* 2 R))) (+ J 1.0))
(let Y (+ (/ J 2) 0.5)
(if (<= (+ (*/ X X 1.0) (*/ Y Y 1.0)) (*/ R R 1.0))
(prog
(setq Vec
(list X Y
(sqrt
(* 1.0
(- (*/ R R 1.0)
(*/ X X 1.0)
(*/ Y Y 1.0))))))
(setq Vec (normalize Vec))
(let (B NIL
Intensity NIL)
(setq B (+ (/ (** (dot *Light Vec) K) (** 1.0 (- K 1))) Ambient))
(setq Intensity
(if (<= B 0)
(- (length *Shades) 2)
(max (format (round (*/ (- 1.0 B) (* (- (length *Shades) 1) 1.0) 1.0) 0)) 0)))
(prin (nth *Shades (+ Intensity 1) 1))))
(prin " "))))
(prinl)))))
 
(setq *Light (normalize *Light))
(drawSphere 20.0 4 0.1)
(drawSphere 10.0 2 0.4)
Output:
                               ##############%%%                                  
                        #&&eeeeeeeeeee&&&&&&######%%%%%                           
                    &eeeoooooooooooooeeeee&&&&&######%%%%%%                       
                 &eooo**************oooooeeee&&&&&#####%%%%%%%                    
              &eoo**!!!!!!!!!!!!!!*****ooooeeee&&&&######%%%%%%%%                 
            eoo**!!!::::::::::::!!!!****ooooeeee&&&&######%%%%%%%%%               
          eoo*!!!::::.......::::::!!!!****oooeeee&&&&######%%%%%%%%%%             
        &eo*!!:::..............::::!!!!***ooooeeee&&&&######%%%%%%%%%%%           
       eo**!!::.................::::!!!****oooeeee&&&&######%%%%%%%%%%%%          
     &eo*!!:::..................::::!!!!***oooeeee&&&&&######%%%%%%%%%%%%%        
    &eo*!!:::...................::::!!!!***oooeeee&&&&&######%%%%%%%%%%%%%%       
   &eo**!!::....................::::!!!****oooeeee&&&&&######%%%%%%%%%%%%%%%      
  #eoo*!!:::...................::::!!!!***ooooeeee&&&&#######%%%%%%%%%%%%%%%%     
  &eo**!!:::.................:::::!!!!****oooeeee&&&&&#######%%%%%%%%%%%%%%%%     
 &eoo**!!::::...............:::::!!!!****ooooeeee&&&&#######%%%%%%%%%%%%%%%%%%    
 &eoo**!!!::::...........::::::!!!!*****ooooeeee&&&&&#######%%%%%%%%%%%%%%%%%%    
#&eoo***!!!::::::::::::::::::!!!!!****ooooeeeee&&&&&#######%%%%%%%%%%%%%%%%%%%%   
#&eeoo***!!!!::::::::::::!!!!!!!*****ooooeeeee&&&&&#######%%%%%%%%%%%%%%%%%%%%%   
#&eeooo****!!!!!!!!!!!!!!!!!!******ooooeeeee&&&&&&#######%%%%%%%%%%%%%%%%%%%%%%   
#&&eeooo******!!!!!!!!!!!*******ooooooeeeee&&&&&&#######%%%%%%%%%%%%%%%%%%%%%%%   
#&&&eeooooo******************ooooooeeeeee&&&&&&########%%%%%%%%%%%%%%%%%%%%%%%%   
##&&&eeeooooooo********oooooooooeeeeeee&&&&&&#########%%%%%%%%%%%%%%%%%%%%%%%%%   
###&&&eeeeeooooooooooooooooooeeeeeee&&&&&&&&#########%%%%%%%%%%%%%%%%%%%%%%%%%%   
%###&&&&eeeeeeeeeeeoeeeeeeeeeeeee&&&&&&&&##########%%%%%%%%%%%%%%%%%%%%%%%%%%%%   
 %####&&&&&eeeeeeeeeeeeeeeeee&&&&&&&&&&##########%%%%%%%%%%%%%%%%%%%%%%%%%%%%%    
 %%#####&&&&&&&&&&&&&&&&&&&&&&&&&&&############%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%    
  %%#######&&&&&&&&&&&&&&&&&&&&##############%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%     
  %%%%############&&&&&###################%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%     
   %%%%%##############################%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%      
    %%%%%%%#######################%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%       
     %%%%%%%%%%%%%#########%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%        
       %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%          
        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%           
          %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%             
            %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%               
              %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%                 
                 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%                    
                    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%                       
                        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%                           
                               %%%%%%%%%%%%%%%%%                                  
                                                                                  
                                                                                  
             !::::::!!!**o                
         ............:::!!**oe            
      :................::!!**ooee         
    :...................::!!**ooeee       
   ......................::!!**ooeee      
  .......................::!!**ooeeee     
 .......................:::!!**ooeeeee    
:.......................::!!***ooeeeeee   
:......................::!!!**oooeeeeee   
:....................:::!!!**oooeeeeeee   
!:..................:::!!***oooeeeeeeee   
!!:..............::::!!!***oooeeeeeeeee   
*!!::::.....::::::!!!!***ooooeeeeeeeeee   
 o*!!!!::::::!!!!!!****ooooeeeeeeeeeee    
  o****!!!!!!!******oooooeeeeeeeeeeee     
   eooo********oooooooeeeeeeeeeeeeee      
    eeeoooooooooooeeeeeeeeeeeeeeeee       
      eeeeeeeeeeeeeeeeeeeeeeeeeee         
         eeeeeeeeeeeeeeeeeeeee            
             eeeeeeeeeeeee                
                                          
                                          

[edit] PostScript

Gradient filled circle:

%!PS-Adobe-3.0
%%BoundingBox 0 0 300 300
 
150 150 translate 0 0 130 0 360 arc
 
/Pattern setcolorspace
<< /PatternType 2
/Shading <<
/ShadingType 3
/ColorSpace /DeviceRGB
/Coords [-60 60 0 0 0 100]
/Function <<
/FunctionType 2
/Domain [0 1]
/C0 [1 1 1]
/C1 [0 0 0]
/N 2
>>
>>
>> matrix makepattern setcolor fill
 
showpage
%%EOF
 

[edit] POV-Ray

This is what POVray was made for. An example with a sky, surface and transparency:

 
camera { location <0.0 , .8 ,-3.0> look_at 0}
 
light_source{< 3,3,-3> color rgb 1}
 
sky_sphere { pigment{ gradient <0,1,0> color_map {[0 color rgb <.2,.1,0>][.5 color rgb 1]} scale 2}}
 
plane {y,-2 pigment { hexagon color rgb .7 color rgb .5 color rgb .6 }}
 
sphere { 0,1
texture {
pigment{ color rgbft <.8,1,1,.4,.4> }
finish { phong 1 reflection {0.40 metallic 0.5} }
}
interior { ior 1.5}
}
 

Yields this:

PovRay-sphere.jpg

[edit] Processing

3D rendering is built into Processing.

void setup() {
size(500,500,P3D);
background(200);
}
 
void draw() {
stroke(200);
translate(250,250);
lights();
sphere(100);
}

[edit] PureBasic

3D Sphere animation.

; Original by Comtois @ 28/03/06
;
; Updated/Formated by Fluid Byte @ March.24,2009
;
; http://www.purebasic.fr/english/viewtopic.php?p=281258#p281258
 
Declare CreateSphere(M,P)
Declare UpdateMesh()
 
#_SIZEVERT = 36
#_SIZETRIS = 6
#FULLSCREEN = 0
 
Structure VECTOR
X.f
Y.f
Z.f
EndStructure
 
Structure VERTEX
X.f
Y.f
Z.f
NX.f
NY.f
NZ.f
Color.l
U.f
V.f
EndStructure
 
Structure TRIANGLE
V1.w
V2.w
V3.w
EndStructure
 
Macro CALC_NORMALS
*PtrV\NX = *PtrV\X
*PtrV\NY = *PtrV\Y
*PtrV\NZ = *PtrV\Z
EndMacro
 
Global *VBuffer, *IBuffer
Global Meridian = 50, Parallele = 50, PasLength = 4, Length
 
Define EventID, i, NbSommet, CameraMode, Angle.f, Pas.f = 0.5
 
InitEngine3D() : InitSprite() : InitKeyboard()
 
Add3DArchive(GetTemporaryDirectory(),#PB_3DArchive_FileSystem)
Add3DArchive(#PB_Compiler_Home + "Examples\Sources\Data\",#PB_3DArchive_FileSystem)
 
If #FULLSCREEN
OpenScreen(800,600,32,"Sphere 3D")
Else
OpenWindow(0,0,0,800,600,"Sphere 3D",#PB_Window_SystemMenu | 1)
OpenWindowedScreen(WindowID(0),0,0,800,600,0,0,0)
EndIf
 
;-Texture
CreateImage(0,128,128)
StartDrawing(ImageOutput(0))
For i = 0 To 127 Step 4
Box(0,i,ImageWidth(0),2,RGB(255,255,255))
Box(0,i + 2,ImageWidth(0),2,RGB(0,0,155))
Next i
StopDrawing()
SaveImage(0,GetTemporaryDirectory() + "temp.bmp") : FreeImage(0)
 
;-Material
CreateMaterial(0,LoadTexture(0,"temp.bmp"))
RotateMaterial(0,0.1,#PB_Material_Animated)
 
;-Mesh
CreateSphere(Meridian,Parallele)
 
;-Entity
CreateEntity(0,MeshID(0),MaterialID(0))
ScaleEntity(0,60,60,60)
 
;-Camera
CreateCamera(0,0,0,100,100)
MoveCamera(0,0,0,-200)
CameraLookAt(0,EntityX(0),EntityY(0),EntityZ(0))
 
;-Light
AmbientColor(RGB(105, 105, 105))
CreateLight(0, RGB(255, 255, 55), EntityX(0) + 150, EntityY(0) , EntityZ(0))
CreateLight(1, RGB( 55, 255, 255), EntityX(0) - 150, EntityY(0) , EntityZ(0))
CreateLight(2, RGB( 55, 55, 255), EntityX(0) , EntityY(0) + 150, EntityZ(0))
CreateLight(3, RGB(255, 55, 255), EntityX(0) , EntityY(0) - 150, EntityZ(0))
 
; ----------------------------------------------------------------------------------------------------
; MAINLOOP
; ----------------------------------------------------------------------------------------------------
 
Repeat
If #FULLSCREEN = 0
Repeat
EventID = WindowEvent()
 
Select EventID
Case #PB_Event_CloseWindow : End
EndSelect
Until EventID = 0
EndIf
 
Angle + Pas
RotateEntity(0, Angle, Angle,Angle)
 
If PasLength > 0 : UpdateMesh() : EndIf
 
If ExamineKeyboard()
If KeyboardReleased(#PB_Key_F1)
CameraMode = 1 - CameraMode
CameraRenderMode(0, CameraMode)
EndIf
EndIf
 
RenderWorld()
FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape)
 
; ----------------------------------------------------------------------------------------------------
; FUNCTIONS
; ----------------------------------------------------------------------------------------------------
 
Procedure CreateSphere(M,P)
; M = Meridian
; P = Parallele
; The radius is 1. Front to remove it later, it's just for the demo.
 
If M < 3 Or P < 2  : ProcedureReturn 0 : EndIf
 
Protected Normale.VECTOR, NbSommet, i, j, Theta.f, cTheta.f, sTheta.f
Protected Alpha.f, cAlpha.f, sAlpha.f, *PtrV.VERTEX, *PtrF.TRIANGLE, NbTriangle
 
NbSommet = 2 + ((M + 1) * P)
*VBuffer = AllocateMemory(#_SIZEVERT * Nbsommet)
 
For i = 0 To M
Theta = i * #PI * 2.0 / M
cTheta = Cos(theta)
sTheta = Sin(theta)
 
For j = 1 To P
Alpha = j * #PI / (P + 1)
cAlpha = Cos(Alpha)
sAlpha = Sin(Alpha)
*PtrV = *VBuffer + #_SIZEVERT * ((i * P) + (j - 1))
*PtrV\X = sAlpha * cTheta
*PtrV\Y = sAlpha * sTheta
*PtrV\Z = cAlpha
*PtrV\U = Theta / (2.0 * #PI)
*PtrV\V = Alpha / #PI
CALC_NORMALS
Next j
Next i
 
; Southpole
*PtrV = *VBuffer + #_SIZEVERT * ((M + 1) * P)
*PtrV\X = 0
*PtrV\Y = 0
*PtrV\Z = -1
*PtrV\U = 0
*PtrV\V = 0
CALC_NORMALS
 
; Northpole
*PtrV + #_SIZEVERT
*PtrV\X = 0
*PtrV\Y = 0
*PtrV\Z = 1
*PtrV\U = 0
*PtrV\V = 0
CALC_NORMALS
 
; Les facettes
NbTriangle = 4 * M * P
*IBuffer = AllocateMemory(#_SIZETRIS * NbTriangle)
*PtrF = *IBuffer
 
For i = 0 To M - 1
For j = 1 To P - 1
*PtrF\V1 = ((i + 1) * P) + j
*PtrF\V2 = ((i + 1) * P) + (j - 1)
*PtrF\V3 = (i * P) + (j - 1)
*PtrF + #_SIZETRIS
*PtrF\V3 = ((i + 1) * P) + j ;Recto
*PtrF\V2 = ((i + 1) * P) + (j - 1) ;Recto
*PtrF\V1 = (i * P) + (j - 1) ;Recto
*PtrF + #_SIZETRIS
*PtrF\V1 = i * P + j
*PtrF\V2 = ((i + 1) * P) + j
*PtrF\V3 = (i * P) + (j - 1)
*PtrF + #_SIZETRIS
*PtrF\V3 = i * P + j ;Recto
*PtrF\V2 = ((i + 1) * P) + j ;Recto
*PtrF\V1 = (i * P) + (j - 1) ;Recto
*PtrF + #_SIZETRIS
Next j
Next i
 
; The Poles
For i = 0 To M - 1
*PtrF\V3 = (M + 1) * P + 1
*PtrF\V2 = (i + 1) * P
*PtrF\V1 = i * P
*PtrF + #_SIZETRIS
*PtrF\V1 = (M + 1) * P + 1 ;Recto
*PtrF\V2 = (i + 1) * P ;Recto
*PtrF\V3 = i * P ;Recto
*PtrF + #_SIZETRIS
Next i
 
For i = 0 To M - 1
*PtrF\V3 = (M + 1) * P
*PtrF\V2 = i * P + (P - 1)
*PtrF\V1 = (i + 1) * P + (P - 1)
*PtrF + #_SIZETRIS
*PtrF\V1 = (M + 1) * P ;Recto
*PtrF\V2 = i * P + (P - 1) ;Recto
*PtrF\V3 = (i + 1) * P + (P - 1) ;Recto
*PtrF + #_SIZETRIS
Next i
 
If CreateMesh(0,100)
Protected Flag = #PB_Mesh_Vertex | #PB_Mesh_Normal | #PB_Mesh_UVCoordinate | #PB_Mesh_Color
SetMeshData(0,Flag,*VBuffer,NbSommet)
SetMeshData(0,#PB_Mesh_Face,*IBuffer,NbTriangle)
ProcedureReturn 1
EndIf
 
ProcedureReturn 0
EndProcedure
 
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Procedure UpdateMesh()
Protected NbTriangle = 4 * Meridian * Parallele
 
Length + PasLength
 
If Length >= NbTriangle
PasLength = 0
Length = Nbtriangle
EndIf
 
SetMeshData(0,#PB_Mesh_Face,*IBuffer,Length)
EndProcedure

PB Animated sphere.png

[edit] Python

[edit] Ascii-Art

Translation of: C
import math
 
shades = ('.',':','!','*','o','e','&','#','%','@')
 
def normalize(v):
len = math.sqrt(v[0]**2 + v[1]**2 + v[2]**2)
return (v[0]/len, v[1]/len, v[2]/len)
 
def dot(x,y):
d = x[0]*y[0] + x[1]*y[1] + x[2]*y[2]
return -d if d < 0 else 0
 
def draw_sphere(r, k, ambient, light):
for i in range(int(math.floor(-r)),int(math.ceil(r)+1)):
x = i + 0.5
line = ''
 
for j in range(int(math.floor(-2*r)),int(math.ceil(2*r)+1)):
y = j/2 + 0.5
if x*x + y*y <= r*r:
vec = normalize((x,y,math.sqrt(r*r - x*x - y*y)))
b = dot(light,vec)**k + ambient
intensity = int((1-b)*(len(shades)-1))
line += shades[intensity] if 0 <= intensity < len(shades) else shades[0]
else:
line += ' '
 
print(line)
 
light = normalize((30,30,-50))
draw_sphere(20,4,0.1, light)
draw_sphere(10,2,0.4, light)
Output:
                                &&&&&&&&&&######                                 
                        &&eeeeeeeeeeeeeeee&&&&&&######%%                         
                    &&oooo********ooooooeeeeee&&&&########%%                     
                  oo****!!!!!!!!******ooooooeeee&&&&########%%                   
              eeoo**!!!!::::::::!!!!******ooooeeee&&&&########%%%%               
            ee**!!::::::....::::::!!!!!!**ooooeeee&&&&&&########%%%%             
          ee**!!::..............::::!!!!****ooooeeee&&&&########%%%%%%           
        ee**!!::..................::::!!!!**ooooeeee&&&&##########%%%%%%         
        oo!!::....................::::!!!!****ooeeee&&&&&&########%%%%%%         
      oo**::......................::::!!!!****ooeeee&&&&&&##########%%%%%%       
    &&**!!::......................::::!!!!****ooeeee&&&&&&##########%%%%%%%%     
    oo**!!::......................::::!!!!**ooooeeee&&&&&&##########%%%%%%%%     
  &&oo!!::........................::::!!****ooooeeee&&&&&&##########%%%%%%%%%%   
  ee**!!::......................::::!!!!****ooooeeee&&&&&&##########%%%%%%%%%%   
  ee**!!::::..................::::::!!!!****ooooeeee&&&&############%%%%%%%%%%   
  ee**!!::::................::::::!!!!****ooooeeee&&&&&&############%%%%%%%%%%   
&&ee****!!::::............::::::!!!!****ooooooeeee&&&&&&##########%%%%%%%%%%%%%% 
&&eeoo**!!!!::::::::::::::::::!!!!******ooooeeee&&&&&&############%%%%%%%%%%%%%% 
&&eeoo****!!!!::::::::::::!!!!!!******ooooeeeeee&&&&&&############%%%%%%%%%%%%%% 
&&eeoooo**!!!!!!!!!!!!!!!!!!!!******ooooeeeeee&&&&&&############%%%%%%%%%%%%%%%% 
&&eeeeoo******!!!!!!!!!!********ooooooeeeeee&&&&&&&&############%%%%%%%%%%%%%%%% 
##&&eeoooooo******************ooooooeeeeee&&&&&&&&############%%%%%%%%%%%%%%%%%% 
##&&eeeeoooooooo******ooooooooooooeeeeee&&&&&&&&##############%%%%%%%%%%%%%%%%%% 
##&&&&eeeeeeooooooooooooooooooeeeeeeee&&&&&&&&##############%%%%%%%%%%%%%%%%%%%% 
  ##&&&&eeeeeeeeeeeeeeeeeeeeeeeeee&&&&&&&&&&################%%%%%%%%%%%%%%%%%%   
  ####&&&&&&eeeeeeeeeeeeeeeeee&&&&&&&&&&&&################%%%%%%%%%%%%%%%%%%%%   
  ######&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&##################%%%%%%%%%%%%%%%%%%%%%%   
  %%######&&&&&&&&&&&&&&&&&&&&&&&&####################%%%%%%%%%%%%%%%%%%%%%%%%   
    ############&&&&&&&&&&&&########################%%%%%%%%%%%%%%%%%%%%%%%%     
    %%############################################%%%%%%%%%%%%%%%%%%%%%%%%%%     
      %%######################################%%%%%%%%%%%%%%%%%%%%%%%%%%%%       
        %%################################%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%         
        %%%%%%########################%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%         
          %%%%%%%%##############%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%           
            %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%             
              %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%               
                  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%                   
                    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%                     
                        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%                         
                                %%%%%%%%%%%%%%%%                                 
                                                                                 
              ::..::::!!**               
          ..............::!!oo           
      ..................::!!**ooee       
    ......................::!!**ooee     
    ......................::!!**ooee     
  ........................::!!**ooooee   
  ........................::!!**ooooee   
::........................::!!**ooooeeee 
........................::!!!!**ooooeeee 
::......................::!!****ooeeeeee 
::....................::!!!!**ooooeeeeee 
!!..................::!!!!****ooeeeeeeee 
**::::..........::::!!!!****ooooeeeeeeee 
  !!!!::::::::::!!!!!!****ooooeeeeeeee   
  oo**!!!!!!!!!!!!******ooooeeeeeeeeee   
    oo**************ooooooeeeeeeeeee     
    eeooooooooooooooooeeeeeeeeeeeeee     
      eeeeooooooooeeeeeeeeeeeeeeee       
          eeeeeeeeeeeeeeeeeeee           
              eeeeeeeeeeee

[edit]
Library: Pygame

Python Sphere

Renders a sphere with random Perlin noise.
This code contains unnecessary functions which are part of a 3D graphics library I wrote.
Uses Pygame and Python 3.2.2

 
import pygame
from pygame.locals import *
import time
import sys
import random
import math
 
 
class Tricubic:
def __init__(self,pts):
self.coefficients = []
for plane in pts:
planecoeffs = []
for line in plane:
p = (line[3]-line[2])-(line[0]-line[1])
q = (line[0]-line[1])-p
r = line[2]-line[0]
s = line[1]
planecoeffs.append([p,q,r,s])
self.coefficients.append(planecoeff)
def Eval(at):
return Misc.Cubic([CoeffBicubic(coeffs[0],d),CoeffBicubic(coeffs[1],d),CoeffBicubic(coeffs[2],d),CoeffBicubic(coeffs[3],d)],d.z)
def CoeffCubic(coeffs,d):
return (coeffs[0]*(d.x**3))+(coeffs[1]*(d.x**2))+(coeffs[2]*d.x)+coeffs[3]
def CoeffBicubic(coeffs,d):
return Misc.Cubic([CoeffCubic(coeffs[0],d),CoeffCubic(coeffs[1],d),CoeffCubic(coeffs[2],d),CoeffCubic(coeffs[3],d)],d.y)
class Misc:
def LinePara(line,t):
return Vector3.Add(line[0],Vector3.Scale(Vector3.Subtract(line[1],line[0]),t))
def LUR(at,above):
look = at.Unit()
right = Vector3.Cross(look,above).Unit()
up = Vector3.Scale(Vector3.Cross(look,right),-1)
return [look,up,right]
def LinePlane(line,triangle,cp=True):
try:
u = Vector3.Subtract(triangle.points[1].point,triangle.points[0])
v = Vector3.Subtract(triangle.points[2],triangle.points[0])
n = Vector3.Cross(u,v)
r = (Vector3.Dot(n,Vector3.Subtract(triangle.points[0],line.start))/Vector3.Dot(n,line.direction))
if stp:
point = Vector3.Add(Vector3.Scale(line.direction,r),line.start)
w = Vector3.Subtract(point,triangle.points[0])
udv = Vector3.Dot(u,v)
wdv = Vector3.Dot(w,v)
vdv = Vector3.Dot(v,v)
wdu = Vector3.Dot(w,u)
udu = Vector3.Dot(u,u)
denominator = (udv**2)-(udu*vdv)
s = ((udv*wdv)-(vdv*wdu))/denominator
t = ((udv*wdu)-(udu*wdv))/denominator
return [r,Vector2(s,t),point]
print('hooray')
else:
return [r]
except:
return None
def Cubic(pts,d):
p = (pts[3]-pts[2])-(pts[0]-pts[1])
q = (pts[0]-pts[1])-p
r = pts[2]-pts[0]
s = pts[1]
return (p*(d**3))+(q*(d**2))+(r*d)+s
def Bicubic(pts,d):
return Misc.Cubic([Misc.Cubic(pts[0],d.x),Misc.Cubic(pts[1],d.x),Misc.Cubic(pts[2],d.x),Misc.Cubic(pts[3],d.x)],d.y)
def Tricubic(pts,d):
return Misc.Cubic([Misc.Bicubic(pts[0],d),Misc.Bicubic(pts[1],d),Misc.Bicubic(pts[2],d),Misc.Bicubic(pts[3],d)],d.z)
def Quadcubic(pts,d):
return Misc.Cubic([Misc.Tricubic(pts[0],d),Misc.Tricubic(pts[1],d),Misc.Tricubic(pts[2],d),Misc.Tricubic(pts[3],d)],d.w)
def Linear(pts,d):
return (pts[2]*d)+(pts[1]*(1-d))
def Bilinear(pts,d):
return Misc.Linear([0,Misc.Linear(pts[1],d.x),Misc.Linear(pts[2],d.x)],d.y)
def Trilinear(pts,d):
return Misc.Linear([0,Misc.Bilinear(pts[1],d),Misc.Bilinear(pts[2],d)],d.z)
def LP2(line,triangle,cp=True):
try:
bla = triangle.points[1]
bla = triangle.points[0]
u = Vector3.Subtract(triangle.points[1].point,triangle.points[0].point)
v = Vector3.Subtract(triangle.points[2].point,triangle.points[0].point)
n = Vector3.Cross(u,v)
d = Vector3.Subtract(line[1],line[0])
r = (Vector3.Dot(n,Vector3.Subtract(triangle.points[0].point,line[0]))/Vector3.Dot(n,d))
if cp:
point = Vector3.Add(Vector3.Scale(d,r),line[0])
w = Vector3.Subtract(point,triangle.points[0].point)
udv = Vector3.Dot(u,v)
wdv = Vector3.Dot(w,v)
vdv = Vector3.Dot(v,v)
wdu = Vector3.Dot(w,u)
udu = Vector3.Dot(u,u)
denominator = (udv**2)-(udu*vdv)
s = ((udv*wdv)-(vdv*wdu))/denominator
t = ((udv*wdu)-(udu*wdv))/denominator
return (r,Vector2(s,t),point)
else:
return (r)
except:
return None
def Phong(normal,viewer,light,material,term):
# light (vector_to,diffuse,specular)
# material (ambient,diffuse,specular,shininess)
n = normal.Unit()
v = viewer.Unit()
l = light[0].Unit()
ldn = Vector3.Dot(l,n)
#print(ldn)
val = 0
if ldn > 0:
val += material[1][term]*ldn*light[1][term]
rdv = Vector3.Dot(Vector3.Subtract(Vector3.Scale(n,2*ldn),l),v)
if rdv > 0:
val += (material[2][term]*(rdv**material[3])*light[2][term])
#print(val)
return val
def Lighting(ambient,normal,viewer,lights,material,term):
# lights [(vector_to,diffuse,specular)]
# material (ambient,diffuse,specular,shininess)
val = material[0][term]*ambient[term]
for light in lights:
val += Misc.Phong(normal,viewer,light,material,term)
return val
def Lighting2(start,direction,ambient,intersect,triangle,lights):
coord = intersect[1]
val = Color.Add(Color.Multiply(ambient,Color.Multiply(triangle.material.color['ambient'],triangle.Map('ambient',coord))),
Color.Multiply(triangle.material.color['glow'],triangle.Map('glow',coord)))
for light in lights:
for n in range(3):
val[n] += Misc.Phong(triangle.InterpolatedNormal(coord),
Vector3.Scale(direction,-1),
(light.To(intersect[2]),light.Diffuse(intersect[2]),light.Specular(intersect[2])),
(Color(),
Color.Multiply(triangle.material.color['diffuse'],triangle.Map('diffuse',coord)),
Color.Multiply(triangle.material.color['specular'],triangle.Map('specular',coord)),
triangle.material.shiny),n)
return val
def Ray(start,direction,scene,color=True,sector=None):
intersect = None
intersected = None
col = None
for triangle in scene.triangles:
possible = True
if sector != None:
possible = False
for point in triangle.points:
if not(point.sector.x < sector.x):
possible = True
if possible:
possible = False
for point in triangle.points:
if not(point.sector.x > sector.x):
possible = True
if possible:
possible = False
for point in triangle.points:
if not(point.sector.y < sector.y):
possible = True
if possible:
possible = False
for point in triangle.points:
if not(point.sector.y > sector.y):
possible = True
possible = True
if possible:
tmp = Misc.LP2([start,Vector3.Add(start,direction)],triangle,color)
write = False
if type(tmp) == type(5.1):
tmp = None
if (tmp != None):
if (intersect == None):
if (tmp[0] > 0) and (tmp[1].x >= 0) and (tmp[1].y >= 0) and (tmp[1].x+tmp[1].y <= 1):
write = True
elif (tmp[0] > 0) and (tmp[0] < intersect[0]) and (tmp[1].x >= 0) and (tmp[1].y >= 0) and (tmp[1].x+tmp[1].y <= 1):
write = True
if write:
intersect = tmp
intersected = triangle
if color and (intersect != None):
applicable = []
for light in scene.lights:
block = Misc.Ray(intersect[2],light.To(intersect[2]),scene,False)
if block == None:
applicable.append(light)
elif light.location != None:
if Vector3.Subtract(light.location,intersect[2]).Magnitude() < block[0]:
applicable.append(light)
col = Misc.Lighting2(start,direction,scene.ambient,intersect,intersected,applicable)
return (intersect,col)
else:
return intersect
class DirLight:
def __init__(self,direction,diffuse,specular):
self.location = None
self.direction = direction.Unit()
self.diffuse = diffuse
self.specular = specular
def To(self,frm):
return Vector3.Scale(self.direction,-1)
def Diffuse(self,to):
return self.diffuse
def Specular(self,to):
return self.specular
class Material:
def __init__(self):
self.color = {'ambient':Color(1,1,1),
'diffuse':Color(1,1,1),
'specular':Color(1,1,1),
'glow':Color(1,1,1)}
self.maps = {'ambient':Map(),
'diffuse':Map(),
'specular':Map(),
'glow':Map(),
'bump':Map()}
self.shiny = 10
class Map:
def __init__(self,surface=None):
self.surface = surface
if self.surface != None:
self.width = self.surface.get_width()
self.height = self.surface.get_height()
def __getitem__(self,index):
if self.surface == None:
return Color(1,1,1)
else:
try:
return Color.From255(self.surface.get_at((int(index.x*(self.width-1)),int(index.y*(self.height-1)))))
except:
return Color(0,0,1)
class Color:
def __init__(self,r=0,g=0,b=0):
self.r = r
self.g = g
self.b = b
def __getitem__(self,index):
if index == 0:
return self.r
elif index == 1:
return self.g
elif index == 2:
return self.b
def __setitem__(self,index,value):
if index == 0:
self.r = value
elif index == 1:
self.g = value
elif index == 2:
self.b = value
def Multiply(A,B):
return Color(A.r*B.r,A.g*B.g,A.b*B.b)
def Add(A,B):
return Color(A.r+B.r,A.g+B.g,A.b+B.b)
def From255(A):
return Color(A.r/255,A.g/255,A.b/255)
class Vertex:
def __init__(self,point,normal,maps):
self.bpoint = point
self.bnormal = normal
self.maps = maps
for name in ['ambient','diffuse','specular','glow','bump']:
try:
bla = self.maps[name]
except:
self.maps[name] = Vector2()
self.sector = None
def Transform(self,points,norms):
self.point = Matrix2.Multiply(self.bpoint.Horizontal(),points).Vectorize()
self.normal = Matrix2.Multiply(self.bnormal.Horizontal(),norms).Vectorize()
class Triangle:
def __init__(self,vertices,material=Material()):
self.points = vertices
self.material = material
def Map(self,name,coord):
pts = []
for n in range(3):
pts.append(self.points[n].maps[name])
loc = Vector2.Add(pts[0],
Vector2.Add(Vector2.Scale(Vector2.Subtract(pts[1],pts[0]),coord.x),
Vector2.Scale(Vector2.Subtract(pts[2],pts[0]),coord.y)))
#print(loc.x,loc.y)
return self.material.maps[name][loc]
def InterpolatedNormal(self,coord):
return Vector3.Add(Vector3.Scale(self.points[0].normal,1-coord.x-coord.y),
Vector3.Add(Vector3.Scale(self.points[1].normal,coord.x),Vector3.Scale(self.points[2].normal,coord.y))).Unit()
class Line:
def __init__(self,A,B=None,direction=None):
self.start = A
if B != None:
self.direction = Vector3.Subtract(B,A).Unit()
elif direction != None:
self.direction = direction
else:
raise RuntimeError('Neither B nor direction are specified')
class Scene:
def __init__(self):
self.triangles = []
self.vertices = []
self.lights = []
self.exterior = []
self.ambient = 0
class Matrix2:
def __init__(self,data=[[]]):
self.FromData(data)
def __getitem__(self,index):
return self.data[index[1]][index[0]]
def __setitem__(self,index,value):
self.data[index[1]][index[0]]=value
def Dimension(self):
self.rows = len(self.data)
self.cols = len(self.data[0])
def FromData(self,data):
self.data = data
length=len(data[0])
for row in data:
if len(row)!=length:
self.data=None
raise RuntimeError('Data rows are not of uniform length.')
self.Dimension()
def Multiply(A,B):
if A.cols!=B.rows:
raise RuntimeError('Column count of Matrix2 \"A\" does not match row count of Matrix2 \"B\".')
matrix = Matrix2.Empty(B.cols,A.rows)
x=0
while x<matrix.cols:
y=0
while y<matrix.rows:
val=0
n=0
while n<A.cols:
val+=A[(n,y)]*B[(x,n)]
n+=1
matrix[(x,y)]=val
y+=1
x+=1
return matrix
def Scalar(A,n):
pass
def Empty(rows,cols):
data = []
row = [0]*rows
n = 0
while n < cols:
data.append(row[:])
n+=1
matrix=Matrix2(data)
matrix.Dimension()
return matrix
def Identity(cols):
matrix = Matrix2.Empty(cols,cols)
n = 0
while n < cols:
matrix[(n,n)]=1
n += 1
return matrix
def Vectorize(self):
if self.cols==1:
if self.rows!=4:
raise RuntimeError('Only 1 by 4 or 4 by 1 Matrix2s can be cast to Vector3s.')
vertical=True
elif self.rows==1:
if self.cols!=4:
raise RuntimeError('Only 1 by 4 or 4 by 1 Matrix2s can be cast to Vector3s.')
vertical = False
else:
raise RuntimeError('Only 1 by 4 or 4 by 1 Matrix2s can be cast to Vector3s.')
vector=[0]*4
n=0
while n<4:
if vertical:
vector[n]=self[(0,n)]
else:
vector[n]=self[(n,0)]
n+=1
return Vector3(vector[0],vector[1],vector[2],vector[3])
def Print(self,decimals,spaces):
length=0
for row in self.data:
for val in row:
string=str(round(val,decimals))
if length<len(string):
length=len(string)
text=''
for row in self.data:
temp=''
for value in row:
val=str(round(float(value),decimals))
pads=length-len(val)
pad=int(pads/2)
temp+=(' '*pad)+val+(' '*(pads-pad))+(' '*spaces)
text+=(' '*spaces)+temp[0:len(temp)-1]+(' '*spaces)+'\n'
return(text[0:len(text)-1])
def RotX(angle):
return Matrix2([
[1,0,0,0],
[0,math.cos(angle),0-math.sin(angle),0],
[0,math.sin(angle),math.cos(angle),0],
[0,0,0,1]])
def RotY(angle):
return Matrix2([
[math.cos(angle),0,0-math.sin(angle),0],
[0,1,0,0],
[math.sin(angle),0,math.cos(angle),0],
[0,0,0,1]])
def RotZ(angle):
return Matrix2([
[math.cos(angle),0-math.sin(angle),0,0],
[math.sin(angle),math.cos(angle),0,0],
[0,0,1,0],
[0,0,0,1]])
def Translate(vector):
return Matrix2([
[1,0,0,0],
[0,1,0,0],
[0,0,1,0],
[vector.x,vector.y,vector.z,1]])
def Scale(vector):
return Matrix2([
[vector.x,0,0,0],
[0,vector.y,0,0],
[0,0,vector.z,0],
[0,0,0,1]])
def Clone(self):
data = []
for row in self.data:
data.append(row[:])
return Matrix2(data)
def Inverse(self):
adjoint = self.Adjoint()
det = self.Determinant()
if det == 0:
raise RuntimeError('Cannot find the inverse of a matrix with a determinant of 0')
inverse = Matrix2.Empty(self.rows,self.cols)
x = 0
while x < self.cols:
y = 0
while y < self.rows:
inverse[(x,y)] = adjoint[(x,y)]/det
y += 1
x += 1
return inverse
def Transpose(self):
transpose = Matrix2.Empty(self.cols,self.rows)
x = 0
while x < self.cols:
y = 0
while y < self.rows:
transpose[(y,x)] = self[(x,y)]
y += 1
x += 1
return transpose
def Adjoint(self):
return self.Cofactors().Transpose()
def Determinant(self):
if self.rows != self.cols:
raise RuntimeError('Cannot find the determinant of a non-square matrix')
if self.rows == 1:
return self[(0,0)]
cofactors = self.Cofactors()
determinant = 0
n = 0
while n < self.cols:
determinant += self[(n,0)]*cofactors[(n,0)]
n += 1
return determinant
def Minors(self):
if self.rows != self.cols:
raise RuntimeError('Cannot find the minors of a non-square matrix')
if self.rows == 1:
raise RuntimeError('Cannot find the minors of a 1 by 1 matrix')
minors = Matrix2.Empty(self.rows,self.cols)
lines = range(self.rows)
x = 0
while x < self.cols:
y = 0
while y < self.cols:
tiny = Matrix2.Empty(self.rows-1,self.cols-1)
ox = 0
nx = 0
while ox < self.cols:
oy = 0
ny = 0
while oy < self.cols:
if not((ox == x) or (oy == y)):
tiny[(nx,ny)] = self[(ox,oy)]
if oy != y:
ny += 1
oy += 1
if ox != x:
nx += 1
ox += 1
minors[(x,y)] = tiny.Determinant()
y += 1
x += 1
return minors
def Cofactors(self):
minors = self.Minors()
cofactors = Matrix2.Empty(self.rows,self.cols)
x = 0
while x < self.cols:
y = 0
while y < self.rows:
if int((x+y)/2) == ((x+y)/2):
cofactors[(x,y)] = minors[(x,y)]
else:
cofactors[(x,y)] = -1*minors[(x,y)]
y += 1
x += 1
return cofactors
def Perspective(e):
return Matrix2([
[1,0,0,0],
[0,1,0,0],
[0,0,1,1/e[2]],
[-e[0],-e[1],0,0]])
def Add(A,B):
if A.rows != B.rows:
RuntimeError('The row counts of Matrix \"A\" and Matrix \"B\" are not identical.')
if A.cols != B.cols:
RuntimeError('The column counts of Matrix \"A\" and Matrix \"B\" are not identical.')
matrix = Matrix.Empty(A.rows,A.cols)
for x in range(A.cols):
for y in range(A.rows):
matrix[(x,y)] = A[(x,y)]+B[(x,y)]
return matrix
def Subtract(A,B):
if A.rows != B.rows:
RuntimeError('The row counts of Matrix \"A\" and Matrix \"B\" are not identical.')
if A.cols != B.cols:
RuntimeError('The column counts of Matrix \"A\" and Matrix \"B\" are not identical.')
matrix = Matrix.Empty(A.rows,A.cols)
for x in range(A.cols):
for y in range(A.rows):
matrix[(x,y)] = A[(x,y)]+B[(x,y)]
return matrix
def DivHomogeneous(self):
if (self.cols,self.rows) == (1,4):
for y in range(3):
self[(0,y)] = self[(0,y)]/self[(0,3)]
self[(0,3)] = 1
if (self.cols,self.rows) == (4,1):
for x in range(3):
self[(x,0)] = self[(x,0)]/self[(3,0)]
self[(3,0)] = 1
else:
raise RuntimeError('1 by 4 or 4 by 1 Matrix2 expected')
def Object(pos,look,up,right):
return Matrix2([
[right.x,right.y,right.z,0],
[up.x,up.y,up.z,0],
[look.x,look.y,look.z,0],
[pos.x,pos.y,pos.z,1]])
def Camera(eye,look,up,right):
return Matrix2([
[right.x,up.x,look.x,0],
[right.y,up.y,look.y,0],
[right.z,up.z,look.z,0],
[-Vector3.Dot(eye,right),
-Vector3.Dot(eye,up),
-Vector3.Dot(eye,look),1]])
def YPR(rot):
return Matrix2.Multiply(
Matrix2.Multiply(Matrix2.RotZ(rot.z),
Matrix2.RotX(rot.x)),
Matrix2.RotY(rot.y))
class Vector2:
def __init__(self,data=0,y=0):
if (type(data) == type(5)) or (type(data) == type(5.1)):
self.x = data
self.y = y
else:
self.x = data[0]
self.y = data[1]
def __getitem__(self,index):
if index == 0:
return self.x
elif index == 1:
return self.y
def __setitem__(self,index,value):
if index == 0:
self.x = value
elif index == 1:
self.y = 1
def Add(A,B):
return Vector2(A.x+B.x,A.y+B.y)
def Subtract(A,B):
return Vector2(A.x-B.x,A.y-B.y)
def Scale(A,n):
return Vector2(A.x*n,A.y*n)
def Magnitude(self):
return ((self.x**2)+(self.y**2))**.5
def Unit(self):
return Vector2.Scale(self,1/self.Magnitude())
def Clone(self):
return Vector2(self.x,self.y)
class Vector3:
def __init__(self,data=0,y=0,z=0,w=1):
if (type(data) == type(5)) or (type(data) == type(5.1)):
self.x = data/w
self.y = y/w
self.z = z/w
else:
try:
temp = data[3]
except:
temp = 1
self.x = data[0]/temp
self.y = data[1]/temp
self.z = data[2]/temp
def __getitem__(self,index):
if index == 0:
return self.x
elif index == 1:
return self.y
elif index == 2:
return self.z
def __setitem__(self,index,value):
if index == 0:
self.x = value
elif index == 1:
self.y = value
elif index == 2:
self.z = value
def Vertical(self):
return Matrix2([[self.x],[self.y],[self.z],[1]])
def Horizontal(self):
return Matrix2([[self.x,self.y,self.z,1]])
def Dot(A,B):
return (A.x*B.x)+(A.y*B.y)+(A.z*B.z)
def Cross(A,B):
return Vector3([
(A.y*B.z)-(A.z*B.y),
(A.z*B.x)-(A.x*B.z),
(A.x*B.y)-(A.y*B.x)])
def Add(A,B):
return Vector3(A.x+B.x,A.y+B.y,A.z+B.z)
def Subtract(A,B):
return Vector3(A.x-B.x,A.y-B.y,A.z-B.z)
def Scale(A,n):
return Vector3(A.x*n,A.y*n,A.z*n)
def Magnitude(self):
return ((self.x**2)+(self.y**2)+(self.z**2))**.5
def Print(self,decimals,spaces):
return self.Horizontal().Print(decimals,spaces)
def Same(A,B):
same = False
if A.x == B.x:
if A.y == B.y:
if A.z == B.z:
same = True
return same
def Unit(self):
return Vector3.Scale(self,1/self.Magnitude())
def Clone(self):
return Vector3(self.x,self.y,self.z)
class Vector4:
def __init__(self,data=0,y=0,z=0,w=0):
if (type(data) == type(5)) or (type(data) == type(5.1)):
self.x = data
self.y = y
self.z = z
self.w = w
else:
self.x = data[0]
self.y = data[0]
self.z = data[0]
self.w = data[0]
 
points = [Vector3([-1,-1,0]),Vector3([1,-1,0]),Vector3([0,1,0])]
width = 255
height = width
screen = pygame.display.set_mode((width,height),0,32)
scl = 2
pos = Vector3([0,0,5])
view = Vector3([0,0,1])
frames = 0
 
def Transform(point,mat):
return Matrix2.Multiply(point.Horizontal(),mat).Vectorize()
 
def RV():
return Vector3([random.random(),random.random(),random.random()])
 
green = pygame.Color(0,255,0)
def XY(bla):
return (((width*bla[0])+width)/2,((height*bla[1])+width)/2)
 
screen.fill(pygame.Color(0,0,0))
size = 255
 
world = Matrix2.Identity(4)
inv = world.Inverse()
invt = world.Inverse().Transpose()
center = Vector3(0,0,2)
 
 
def Texture(size):
texture = []
for pa in range(size):
plane = []
for pb in range(size):
line = []
for pc in range(size):
line.append(random.random())
plane.append(line)
texture.append(plane)
return texture
 
lights = [(Vector3(-10,6,-9),[.7,.7*.9,.7*.8],[.7,.7*.9,.9*.8])]
lights = [(Vector3(-10,6,-9),[.8,.8,.8],[.7,.7,.7])]
 
depth = 3
groups = []
for n in range(1):
textures = []
for n in range(depth):
textures.append(Texture(4**(n+1)))
groups.append(textures)
 
def Select(texture,at):
sel = []
for pa in range(4):
aplane = texture[pa+math.floor(at.z)]
bplane = []
for pb in range(4):
aline = aplane[pb+math.floor(at.y)]
bline = []
for pc in range(4):
bline.append(aline[pc+math.floor(at.x)])
bplane.append(bline)
sel.append(bplane)
return (sel,Vector3(at.x%1,at.y%1,at.z%1))
def Round(val):
return val-(val-math.floor(val))
 
theta = math.tan(70*math.pi/360)
for x in range(width):
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
pass
for y in range(height):
l = Vector3(theta*2*((x/width)-.5),theta*2*((y/width)-.5),1).Unit()
ldc = Vector3.Dot(l,center)
d = ldc-(((ldc**2)-Vector3.Dot(center,center)+1)**.5)
if type(d) != type((-1)**.5):
intersection = Vector3.Scale(l,d)
normal = Vector3.Subtract(intersection,center).Unit()
point = Transform(normal,world)
 
s = Vector3.Scale(Vector3.Add(point,Vector3(1,1,1)),.5)
val = 0
for i in range(depth):
sel = Select(groups[0][i],Vector3.Scale(s,4**i))
val += Misc.Tricubic(sel[0],sel[1])*((1/2)**i)/4
 
val = (25*val)%1
vals = [0,Misc.Linear([0,.3,1],val),1]
 
coloring = []
for i in range(3):
#light = Misc.Lighting([1,1,1],normal,Vector3.Scale(intersection,-1),lights,([0,.03*val,.03],[0,.7*val,.7],[.3,.3,.3],7),i)
light = Misc.Lighting([.1,.1,.1],normal,Vector3.Scale(intersection,-1),lights,(vals,vals,[1,1,1],10),i)
if light > 1:
light = 1
elif light < 0:
light = 0
coloring.append(round(255*light))
screen.set_at((x,height-y),pygame.Color(coloring[0],coloring[1],coloring[2]))
pygame.display.update()
pygame.image.save(screen,"PythonSphere.png")
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
pass
 

[edit]
Library: VPython

Works with: Python version 2.7.5

Short version:

from visual import *
scene.title = "VPython: Draw a sphere"
sphere() # using defaults, see http://www.vpython.org/contents/docs/defaults.html defaults]

Regular version, with some window-dressing:

 
from __future__ import print_function, division
from visual import *
 
title = "VPython: Draw a sphere"
scene.title = title
print( "%s\n" % title )
 
print( 'Drag with right mousebutton to rotate view' )
print( 'Drag up+down with middle mousebutton to zoom')
 
scene.autocenter = True
 
# uncomment any (or all) of those variants:
S1 = sphere(pos=(0.0, 0.0, 0.0), radius=1.0, color=color.blue)
#S2 = sphere(pos=(2.0, 0.0, 0.0), radius=1.0, material=materials.earth)
#S3 = sphere(pos=(0.0, 2.0, 0.0), radius=1.0, material=materials.BlueMarble)
#S4 = sphere(pos=(0.0, 0.0, 2.0), radius=1.0,
# color=color.orange, material=materials.marble)
 
while True: # Animation-loop
rate(100)
pass # no animation in this demo
 

[edit] Racket

Racket-sphere-plot.png

Using the Typed Racket language with the plot library:

 
#lang typed/racket
 
(require plot/typed)
(plot3d (polar3d (λ (θ ρ) 1)) #:altitude 25)
 

[edit] REXX

This program is modeled after the   C   version.
The REXX language doesn't have a   SQRT   function, so a version is included here.
Same with the   CEILing   and   FLOOR   functions.

Programming note:   the output will appear slightly different when executed on an EBCDIC machine   (due to different dithering characters).

/*REXX program expresses a lighted sphere with simple chars for shading.*/
call drawSphere 19, 4, 2/10 /*draw a sphere with radius 19. */
call drawSphere 10, 2, 4/10 /*draw a sphere with radius ten. */
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────DRAWSPHERE subroutine───────────────*/
drawSphere: procedure; parse arg r, k, ambient /*get the arguments*/
if 1=='f1'x then shading='.:!*oe&#%@' /*EBCDIC dithering.*/
else shading='·:!°oe@░▒▓' /*ASCII " */
lightSource = '30 30 -50' /*the light source.*/
parse value norm(lightSource) with s1 s2 s3 /*normalize light S*/
sLen=length(shading); sLen1=sLen-1; rr=r*r /*handy-dandy vars.*/
 
do i=floor(-r) to ceil(r)  ; x= i+.5; xx=x**2; aLine=
do j=floor(-2*r) to ceil(2*r); y=j/2+.5; yy=y**2
if xx+yy<=rr then do /*within the phere?*/
parse value norm(x y sqrt(rr-xx-yy)) with v1 v2 v3
dot=s1*v1 + s2*v2 + s3*v3 /*dot product of Vs*/
if dot>0 then dot=0 /*if pos, make it 0*/
b=abs(dot)**k + ambient /*calc. brightness.*/
if b<=0 then brite=sLenm1
else brite=trunc( max( (1-b) * sLen1, 0) )
aLine=aLine || substr(shading,brite+1,1) /*build.*/
end
else aLine=aLine' ' /*append a blank. */
end /*j*/
say strip(aLine,'trailing') /*show a line of it*/
end /*i*/ /* [↑] show sphere*/
return
/*─────────────────────────────────────subroutines────────────────────────────*/
ceil: procedure; parse arg x; _=trunc(x); return _ + (x>0) * (x\=_)
floor: procedure; parse arg x; _=trunc(x); return _ - (x<0) * (x\=_)
norm: parse arg _1 _2 _3; _=sqrt(_1**2+_2**2+_3**2); return _1/_ _2/_ _3/_
/*─────────────────────────────────────SQRT subroutine────────────────────────*/
sqrt: procedure; parse arg x; if x=0 then return 0; d=digits(); p=d+d%4+2; m.=11
numeric digits m.;numeric form;parse value format(x,2,1,,0) 'E0' with g 'E' _ .
g=g*.5'E'_%2; do j=0 while p>9; m.j=p; p=p%2+1; end
do k=j+5 to 0 by -1; if m.k>11 then numeric digits m.k; g=.5*(g+x/g); end
numeric digits d; return g/1
Output:
when executed on an ASCII machine:
                             eeeeeeeeee@@@@@@@
                       eoooooooooooooooeeeee@@@@@@@░
                   oo°°°!!!!!!!!°°°°°°ooooeeeee@@@@@@@░░
                o°°!!!:::::::::!!!!!°°°°°ooooeeee@@@@@@@░░░
             o°!!::::·········:::::!!!!°°°ooooeeeee@@@@@@@░░░░
           o°!:::················::::!!!°°°°oooeeeee@@@@@@@░░░░░
         o°!::····················::::!!!°°°°oooeeeee@@@@@@@░░░░░░
       o°!::·······················:::!!!!°°°ooooeeee@@@@@@@@░░░░░░░
      o°!::·························:::!!!°°°ooooeeeee@@@@@@@░░░░░░░░
     o°!:···························:::!!!°°°°oooeeeee@@@@@@@@░░░░░░░░
    o°!::··························::::!!!°°°ooooeeeee@@@@@@@@░░░░░░░░░
   o°!::···························:::!!!!°°°ooooeeeee@@@@@@@@░░░░░░░░░░
  o°!!::··························::::!!!°°°°ooooeeeee@@@@@@@@░░░░░░░░░░░
 eo°!!::·························::::!!!°°°°ooooeeeee@@@@@@@@@░░░░░░░░░░░░
 oo°!!::························::::!!!°°°°ooooeeeeee@@@@@@@@░░░░░░░░░░░░░
eoo°!!:::·····················::::!!!!°°°°oooooeeeee@@@@@@@@@░░░░░░░░░░░░░░
eoo°°!!:::·················:::::!!!!!°°°°ooooeeeeee@@@@@@@@@░░░░░░░░░░░░░░░
eoo°°!!!:::::··········:::::::!!!!!°°°°oooooeeeeee@@@@@@@@@@░░░░░░░░░░░░░░░
eeoo°°°!!!:::::::::::::::::!!!!!!°°°°°oooooeeeeee@@@@@@@@@@░░░░░░░░░░░░░░░░
eeooo°°°!!!!!!!:::::::!!!!!!!!°°°°°°oooooeeeeee@@@@@@@@@@@░░░░░░░░░░░░░░░░░
@eeooo°°°°°!!!!!!!!!!!!!!!°°°°°°°ooooooeeeeeee@@@@@@@@@@@░░░░░░░░░░░░░░░░░░
@@eeeoooo°°°°°°°°°°°°°°°°°°°°°oooooooeeeeeee@@@@@@@@@@@@░░░░░░░░░░░░░░░░░░░
@@@eeeoooooo°°°°°°°°°°°°°oooooooooeeeeeeee@@@@@@@@@@@@░░░░░░░░░░░░░░░░░░░░░
 @@@eeeeeooooooooooooooooooooooeeeeeeeee@@@@@@@@@@@@@░░░░░░░░░░░░░░░░░░░░░
 @@@@@eeeeeeeooooooooooooeeeeeeeeeeee@@@@@@@@@@@@@@░░░░░░░░░░░░░░░░░░░░░░░
  @@@@@@eeeeeeeeeeeeeeeeeeeeeeeee@@@@@@@@@@@@@@@@░░░░░░░░░░░░░░░░░░░░░░░░
   @@@@@@@@@eeeeeeeeeeeeeeeee@@@@@@@@@@@@@@@@@@░░░░░░░░░░░░░░░░░░░░░░░░░
    ░@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@░░░░░░░░░░░░░░░░░░░░░░░░░░░
     ░░@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
      ░░░░@@@@@@@@@@@@@@@@@@@@@@@@@@@░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
       ░░░░░░░@@@@@@@@@@@@@@@@@@░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
         ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
           ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
             ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
                ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
                   ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
                       ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
                             ░░░░░░░░░░░░░░░░░

             ::···:::!!!°o
         ··············::!!°oo
      ··················::!!°°ooe
    ·····················::!!°°ooee
   ·······················::!!°°ooee
  ························::!!°°oooee
 ·························::!!°°oooeee
:························::!!!°°oooeeee
························::!!!°°ooooeeee
:······················::!!!°°°oooeeeee
:····················:::!!!°°°oooeeeeee
!:·················:::!!!°°°°oooeeeeeee
°!:::···········::::!!!!°°°ooooeeeeeeee
 °!!!:::::::::::!!!!!°°°°oooooeeeeeeee
  o°°!!!!!!!!!!!!!°°°°°oooooeeeeeeeee
   oo°°°°°°°°°°°°°°ooooooeeeeeeeeeee
    eoooooooooooooooooeeeeeeeeeeeee
      eeeooooooooeeeeeeeeeeeeeeee
         eeeeeeeeeeeeeeeeeeeee
             eeeeeeeeeeeee

[edit] Ruby

Library: Shoes

Shoes comes with this sample program.

Sphere.shoes.png
Shoes.app :width => 500, :height => 500, :resizable => false do
image 400, 470, :top => 30, :left => 50 do
nostroke
fill "#127"
image :top => 230, :left => 0 do
oval 70, 130, 260, 40
blur 30
end
oval 10, 10, 380, 380
image :top => 0, :left => 0 do
fill "#46D"
oval 30, 30, 338, 338
blur 10
end
fill gradient(rgb(1.0, 1.0, 1.0, 0.7), rgb(1.0, 1.0, 1.0, 0.0))
oval 80, 14, 240, 176
image :top => 0, :left => 0 do
fill "#79F"
oval 134, 134, 130, 130
blur 40
end
image :top => 150, :left => 40, :width => 320, :height => 260 do
fill gradient(rgb(0.7, 0.9, 1.0, 0.0), rgb(0.7, 0.9, 1.0, 0.6))
oval 60, 60, 200, 136
blur 20
end
end
end

[edit] Run BASIC

graphic #g, 300, 300 	'create a graphic object
#g place(100,100) 'place the drawing pen at 100,100
#g circle(75) 'make a circle with radius 75
render #g 'show it

[edit] Smalltalk

there are various OpenGL bindings available; here is a translation of the bare-bones code from C/Go:

Works with: Smalltalk/X

although there is a Point3 class in some loadable library, here is some self contained code, defining a local anon Point3D class.

 
Point3D :=
Point subclass:#Point3D
instanceVariableNames:'z'
classVariableNames:''
poolDictionaries:''
category:''
inEnvironment:nil.
 
Point3D compile:'z ^ z'.
Point3D compile:'z:v z := v'.
 
normalize := [:v | |invLen|
invLen := 1 / (dot value:v value:v) sqrt.
v x: v x * invLen.
v y: v y * invLen.
v z: v z * invLen.
].
 
dot := [:a :b |
(a x * b x) + (a y * b y) + (a z * b z)
].
 
drawSphere := [:r :k :amb :dir |
|w h imh vec img|
 
w := r*4. h := r*3.
img := Image width:w height:h depth:8.
img photometric:#blackIs0; createPixelStore.
vec := Point3D new.
0-r to:r do:[:x |
0-r to:r do:[:y |
|z s lum|
(z := (r*r) - (x*x) - (y*y)) >= 0 ifTrue:[
vec x: x.
vec y: y.
vec z: z sqrt.
normalize value:vec.
s := dot value:dir value:vec.
s < 0 ifTrue:[ s := 0 ].
lum := 255 * ((s raisedTo: k) + amb) / (1 + amb).
lum < 0 ifTrue:[
lum := 0
] ifFalse:[ lum > 255 ifTrue:[
lum := 255
]].
img atX:(x+(w//2)) y:(y+(h//2)) put:(Color greyByte:lum).
]
]
].
img
].
 
main := [
|dir img|
 
dir := Point3D new x:-30; y:-30; z:50; yourself.
normalize value:dir.
img := drawSphere value: 100 value: 1.5 value: 0.2 value: dir.
img displayOn:(View new extent:400@400; openAndWait).
img saveOn:'sphere.png'.
].
 
main value.
 

Sphere-smalltalk.png

[edit] SVG

Not quite a sphere. Sphere-ish.svg

[edit] Tcl

Library: Tk

Assuming the task is to draw a likeness of a sphere, this would usually do:

proc grey {n} {format "#%2.2x%2.2x%2.2x" $n $n $n}
 
pack [canvas .c -height 400 -width 640 -background white]
 
for {set i 0} {$i < 255} {incr i} {
set h [grey $i]
.c create arc [expr {100+$i/5}] [expr {50+$i/5}] [expr {400-$i/1.5}] [expr {350-$i/1.5}] \
-start 0 -extent 359 -fill $h -outline $h}
}

Results in this image:

Tcl-spheroid.gif

[edit] XPL0

SphereXPL0.png
include c:\cxpl\codes;          \intrinsic 'code' declarations
def R=100, R2=R*R; \radius, in pixels; radius squared
def X0=640/2, Y0=480/2; \coordinates of center of screen
int X, Y, Z, C, D2; \coords, color, distance from center squared
[SetVid($112); \set 640x480x24 graphics mode
for Y:= -R to +R do \for all the coordinates near the circle
for X:= -R to +R do \ which is under the sphere
[D2:= X*X + Y*Y;
C:= 0; \default color is black
if D2 <= R2 then \coordinate is inside circle under sphere
[Z:= sqrt(R2-D2); \height of point on surface of sphere above X,Y
C:= Z-(X+Y)/2+130; \color is proportional; offset X and Y, and
]; \ shift color to upper limit of its range
Point(X+X0, Y+Y0, C<<8+C); \green + blue = cyan
];
repeat until KeyHit; \wait for keystroke
SetVid($03); \restore normal text mode
]

[edit] zkl

Uses the PPM class from http://rosettacode.org/wiki/Bitmap/Bresenham%27s_line_algorithm#zkl

Translation of: XPL0
img:=PPM(640,480);
R:=100; R2:=R*R; //radius, in pixels; radius squared
X0:=640/2; Y0:=480/2; //coordinates of center of screen
foreach Y in ([-R..R]){ //for all the coordinates near the circle
foreach X in ([-R..R]){ // which is under the sphere
D2:=X*X + Y*Y;
C:=0; //default color is black
if(D2<=R2){ //coordinate is inside circle under sphere
Z:=(R2-D2).toFloat().sqrt();//height of point on surface of sphere above X,Y
C=0x82+Z-(X+Y)/2; //color is proportional; offset X and Y, and
} // shift color to upper limit of its range
img[X+X0,Y+Y0]=C.shiftLeft(8)+C; //green + blue = cyan
}
}
img.write(File("foo.ppm","wb"));
Output:
See the XPL0 image.

The radius of 100 is the max before the color calculation overflows 24 bits so for a radius (R) of, say 200, use

img[X+X0,Y+Y0]=C*140+C;
Personal tools
Namespaces

Variants
Actions
Community
Explore
Misc
Toolbox