Movatterモバイル変換


[0]ホーム

URL:


Jump to content
Rosetta Code
Search

Draw a rotating cube

From Rosetta Code
Task
Draw a rotating cube
You are encouraged tosolve this task according to the task description, using any language you may know.
Task

Draw a rotating cube.

It should be oriented with one vertex pointing straight up, and its opposite vertex on the main diagonal (the one farthest away) straight down. It can be solid or wire-frame, and you can use ASCII art if your language doesn't have graphical capabilities. Perspective is optional.

Related tasks



Ada

Library:SDLAda
Translation of:Go
withAda.Numerics.Elementary_Functions;withSDL.Video.Windows.Makers;withSDL.Video.Renderers.Makers;withSDL.Events.Events;procedureRotating_CubeisWidth:constant:=500;Height:constant:=500;Offset:constant:=500.0/2.0;Window:SDL.Video.Windows.Window;Renderer:SDL.Video.Renderers.Renderer;Event:SDL.Events.Events.Events;Quit:Boolean:=False;typeNode_IdisnewNatural;typePoint_3DisrecordX,Y,Z:Float;end record;typeEdge_TypeisrecordA,B:Node_Id;end record;Nodes:array(Node_Idrange<>)ofPoint_3D:=((-100.0,-100.0,-100.0),(-100.0,-100.0,100.0),(-100.0,100.0,-100.0),(-100.0,100.0,100.0),(100.0,-100.0,-100.0),(100.0,-100.0,100.0),(100.0,100.0,-100.0),(100.0,100.0,100.0));Edges:constantarray(Positiverange<>)ofEdge_Type:=((0,1),(1,3),(3,2),(2,0),(4,5),(5,7),(7,6),(6,4),(0,4),(1,5),(2,6),(3,7));useAda.Numerics.Elementary_Functions;procedureRotate_Cube(AngleX,AngleY:inFloat)isSinX:constantFloat:=Sin(AngleX);CosX:constantFloat:=Cos(AngleX);SinY:constantFloat:=Sin(AngleY);CosY:constantFloat:=Cos(AngleY);X,Y,Z:Float;beginforNodeofNodesloopX:=Node.X;Y:=Node.Y;Z:=Node.Z;Node.X:=X*CosX-Z*SinX;Node.Z:=Z*CosX+X*SinX;Z:=Node.Z;Node.Y:=Y*CosY-Z*SinY;Node.Z:=Z*CosY+Y*SinY;endloop;endRotate_Cube;functionPoll_QuitreturnBooleanisusetypeSDL.Events.Event_Types;beginwhileSDL.Events.Events.Poll(Event)loopifEvent.Common.Event_Type=SDL.Events.QuitthenreturnTrue;endif;endloop;returnFalse;endPoll_Quit;procedureDraw_Cube(Quit:outBoolean)isuseSDL.C;Pi:constant:=Ada.Numerics.Pi;Xy1,Xy2:Point_3D;beginRotate_Cube(Pi/4.0,Arctan(Sqrt(2.0)));forFramein0..359loopRenderer.Set_Draw_Colour((0,0,0,255));Renderer.Fill(Rectangle=>(0,0,Width,Height));Renderer.Set_Draw_Colour((0,220,0,255));forEdgeofEdgesloopXy1:=Nodes(Edge.A);Xy2:=Nodes(Edge.B);Renderer.Draw(Line=>((int(Xy1.X+Offset),int(Xy1.Y+Offset)),(int(Xy2.X+Offset),int(Xy2.Y+Offset))));endloop;Rotate_Cube(Pi/180.0,0.0);Window.Update_Surface;Quit:=Poll_Quit;exitwhenQuit;delay0.020;endloop;endDraw_Cube;beginifnotSDL.Initialise(Flags=>SDL.Enable_Screen)thenreturn;endif;SDL.Video.Windows.Makers.Create(Win=>Window,Title=>"Rotating cube",Position=>SDL.Natural_Coordinates'(X=>10,Y=>10),Size=>SDL.Positive_Sizes'(Width,Height),Flags=>0);SDL.Video.Renderers.Makers.Create(Renderer,Window.Get_Surface);whilenotQuitloopDraw_Cube(Quit);endloop;Window.Finalize;SDL.Finalise;endRotating_Cube;

Amazing Hopper

Translation of:BASIC256
Translation of:FreeBASIC

El programa requiere de la ejecución con "rxvt" de Linux:rxvt -g 500x250 -fn "xft:FantasqueSansMono-Regular:pixelsize=1" -e ./bin/cubo

Caption
#context-free Draw a cube   Loop for (i=1, #(i<=3), ++i)      Draw a line (size_2, {size_2} Minus(scale_zoff), [i] Get 'x',\                   {size_2} Minus(scale x zoff) )      Draw a line (size_2, {size_2} Plus(scale_zoff), [{7}Minus(i)] Get 'x' ,\                   {size_2} Plus(scale x zoff) )      Draw a line ([i] Get 'x', {size_2} Minus(scale x zoff),\                   [Minusone(i) Module(3) Plus(4)] Get 'x', {size_2} Plus(scale x zoff) )      Draw a line ([i] Get 'x', {size_2} Minus(scale x zoff), \                   [{i} Module(3) Plus(4)] Get 'x', {size_2} Plus(scale x zoff) )   NextReturn\\#context-free Delete old cube   Color back '0', Draw a cubeReturn\\#context-free Setting values of program   Set( Div(M_PI,6), Mul(5,Div(M_PI,6)), Mul(3,M_PI_2), Mul(11,Div(M_PI,6)),\        M_PI_2, Mul(7,Div(M_PI,6)) )   Append to list 'cylphi'      /* pre-cálculos */   Let ( dt := Div(1,30 ))   Let (size_2 := Div( SIZE, 2))   Let (scale_zoff := Div( SCALE,zoff))   Let (scale x zoff := Mul (SCALE, zoff))Return \\#include <jambo.h>/*Execute with:  $ rxvt -g 250x250 -fn "xft:FantasqueSansMono-Regular:pixelsize=1" -e hopper jm/cubo.jambo*/#define SCALE 50#define SIZE 200#define zoff 0.5773502691896257645091487805019574556#define cylr 1.6329931618554520654648560498039275946Main   Set break   theta=0, dtheta=1.5, lasttime=0, dt=0 , timer=0   size_2=0, scale_zoff=0, scale x zoff=0, cylphi = {}   Dim (6) as zeros (x)      Setting values of program          Cls   /* Draw a cube */   Loop while ( Not (Keypressed))       Tic(lasttime)       Loop for( i=1, #(i<=6), ++i )           Add( size_2, Mul( Mul(SCALE,cylr), Cos( [i] Get 'cylphi' Plus 'theta')) )           Put 'x'       Next       Color back '15', Draw a cube              Loop            Timecpu(timer)       While ( This 'timer' Compared to 'Add(lasttime, dt)' Is less )              Let ( theta := Add( theta, Mul( dtheta, Sub(timer, lasttime))))        Sleep (0.01)       Delete old cube   BackEndSubrutines

AutoHotkey

RequiresGdip Library

; ---------------------------------------------------------------cubeSize:=200deltaX:=A_ScreenWidth/2deltaY:=A_ScreenHeight/2keyStep:=1mouseStep:=0.2zoomStep:=1.1playSpeed:=1playTimer:=10penSize:=5/*HotKeys:!p::Play/Stop!x::change play to x-axis!y::change play to y-axis!z::change play to z-axis!NumpadAdd::Zoom in!WheelUp::Zoom in!NumpadSub::Zoom out!WheelDown::Zoom out!LButton::Rotate X-axis, follow mouse!Up::Rotate X-axis, CCW!Down::Rotate X-axis, CW!LButton::Rotate Y-axis, follow mouse!Right::Rotate Y-axis, CCW!Left::Rotate Y-axis, CW!RButton::Rotate Z-axis, follow mouse!PGUP::Rotate Z-axis, CW!PGDN::Rotate Z-axis, CCW+LButton::Move, follow mouse^esc::Exitapp*/visualCube=(1+--------+5 |\         \ | 2+--------+6 |  |        |3+  |   7+   |  \ |        |   4+--------+8)SetBatchLines,-1coord:=cubeSize/2nodes:=[[-coord,-coord,-coord],[-coord,-coord,coord],[-coord,coord,-coord],[-coord,coord,coord],[coord,-coord,-coord],[coord,-coord,coord],[coord,coord,-coord],[coord,coord,coord]]edges:=[[1,2],[2,4],[4,3],[3,1],[5,6],[6,8],[8,7],[7,5],[1,5],[2,6],[3,7],[4,8]]faces:=[[1,2,4,3],[2,4,8,6],[1,2,6,5],[1,3,7,5],[5,7,8,6],[3,4,8,7]]CP:=[(nodes[8,1]+nodes[1,1])/2,(nodes[8,2]+nodes[1,2])/2]rotateX3D(-30)rotateY3D(30)Gdip1()draw()return; --------------------------------------------------------------draw(){globalD:=""fori,ninnodesD.=Sqrt((n.1-CP.1)**2+(n.2-CP.2)**2)"`t:"i":`t"n.3"`n"Sort,D,Np1:=StrSplit(StrSplit(D,"`n","`r").1,":").2p2:=StrSplit(StrSplit(D,"`n","`r").2,":").2hiddenNode:=nodes[p1,3]<nodes[p2,3]?p1:p2; Draw Facesloop%faces.count(){n1:=faces[A_Index,1]n2:=faces[A_Index,2]n3:=faces[A_Index,3]n4:=faces[A_Index,4]if(n1=hiddenNode)||(n2=hiddenNode)||(n3=hiddenNode)||(n4=hiddenNode)continuepoints:=nodes[n1,1]+deltaX","nodes[n1,2]+deltaY."|"nodes[n2,1]+deltaX","nodes[n2,2]+deltaY."|"nodes[n3,1]+deltaX","nodes[n3,2]+deltaY."|"nodes[n4,1]+deltaX","nodes[n4,2]+deltaYGdip_FillPolygon(G,FaceBrush%A_Index%,Points)}; Draw Node-Numbers;~ loop % nodes.count() {;~ Gdip_FillEllipse(G, pBrush, nodes[A_Index, 1]+deltaX, nodes[A_Index, 2]+deltaY, 4, 4);~ Options := "x" nodes[A_Index, 1]+deltaX " y" nodes[A_Index, 2]+deltaY "c" TextColor " Bold s" size;~ Gdip_TextToGraphics(G, A_Index, Options, Font);~ }; Draw Edgesloop%edges.count(){n1:=edges[A_Index,1]n2:=edges[A_Index,2]if(n1=hiddenNode)||(n2=hiddenNode)continueGdip_DrawLine(G,pPen,nodes[n1,1]+deltaX,nodes[n1,2]+deltaY,nodes[n2,1]+deltaX,nodes[n2,2]+deltaY)}UpdateLayeredWindow(hwnd1,hdc,0,0,Width,Height)}; ---------------------------------------------------------------rotateZ3D(theta){ ; Rotate shape around the z-axisglobaltheta*=3.141592653589793/180sinTheta:=sin(theta)cosTheta:=cos(theta)loop%nodes.count(){x:=nodes[A_Index,1]y:=nodes[A_Index,2]nodes[A_Index,1]:=x*cosTheta-y*sinThetanodes[A_Index,2]:=y*cosTheta+x*sinTheta}Redraw()}; ---------------------------------------------------------------rotateX3D(theta){ ; Rotate shape around the x-axisglobaltheta*=3.141592653589793/180sinTheta:=sin(theta)cosTheta:=cos(theta)loop%nodes.count(){y:=nodes[A_Index,2]z:=nodes[A_Index,3]nodes[A_Index,2]:=y*cosTheta-z*sinThetanodes[A_Index,3]:=z*cosTheta+y*sinTheta}Redraw()}; ---------------------------------------------------------------rotateY3D(theta){ ; Rotate shape around the y-axisglobaltheta*=3.141592653589793/180sinTheta:=sin(theta)cosTheta:=cos(theta)loop%nodes.count(){x:=nodes[A_Index,1]z:=nodes[A_Index,3]nodes[A_Index,1]:=x*cosTheta+z*sinThetanodes[A_Index,3]:=z*cosTheta-x*sinTheta}Redraw()}; ---------------------------------------------------------------Redraw(){globalgdip2()gdip1()draw()}; ---------------------------------------------------------------gdip1(){globalIf!pToken:=Gdip_Startup(){MsgBox,48,gdipluserror!,Gdiplusfailedtostart.PleaseensureyouhavegdiplusonyoursystemExitApp}OnExit,ExitWidth:=A_ScreenWidth,Height:=A_ScreenHeightGui,1:-Caption+E0x80000+LastFound+OwnDialogs+Owner+AlwaysOnTopGui,1:Show,NAhwnd1:=WinExist()hbm:=CreateDIBSection(Width,Height)hdc:=CreateCompatibleDC()obm:=SelectObject(hdc,hbm)G:=Gdip_GraphicsFromHDC(hdc)Gdip_SetSmoothingMode(G,4)TextColor:="FFFFFF00",size:=18Font:="Arial"Gdip_FontFamilyCreate(Font)pBrush:=Gdip_BrushCreateSolid(0xFFFF00FF)FaceBrush1:=Gdip_BrushCreateSolid(0xFF0000FF); blueFaceBrush2:=Gdip_BrushCreateSolid(0xFFFF0000) ; redFaceBrush3:=Gdip_BrushCreateSolid(0xFFFFFF00) ; yellowFaceBrush4:=Gdip_BrushCreateSolid(0xFFFF7518) ; orangeFaceBrush5:=Gdip_BrushCreateSolid(0xFF00FF00) ; limeFaceBrush6:=Gdip_BrushCreateSolid(0xFFFFFFFF) ; whitepPen:=Gdip_CreatePen(0xFF000000,penSize)}; ---------------------------------------------------------------gdip2(){globalGdip_DeleteBrush(pBrush)Gdip_DeletePen(pPen)SelectObject(hdc,obm)DeleteObject(hbm)DeleteDC(hdc)Gdip_DeleteGraphics(G)}; Viewing Hotkeys ----------------------------------------------; HotKey Play/Stop ---------------------------------------------!p::SetTimer,rotateTimer,%(toggle:=!toggle)?playTimer:"off"returnrotateTimer:axis:=!axis?"Y":axisrotate%axis%3D(playSpeed)return!x::!y::!z::axis:=SubStr(A_ThisHotkey,2,1)return; HotKey Zoom in/out -------------------------------------------!NumpadAdd::!NumpadSub::!WheelUp::!WheelDown::loop%nodes.count(){nodes[A_Index,1]:=nodes[A_Index,1]*(InStr(A_ThisHotkey,"Add")||InStr(A_ThisHotkey,"Up")?zoomStep:1/zoomStep)nodes[A_Index,2]:=nodes[A_Index,2]*(InStr(A_ThisHotkey,"Add")||InStr(A_ThisHotkey,"Up")?zoomStep:1/zoomStep)nodes[A_Index,3]:=nodes[A_Index,3]*(InStr(A_ThisHotkey,"Add")||InStr(A_ThisHotkey,"Up")?zoomStep:1/zoomStep)}Redraw()return; HotKey Rotate around Y-Axis ----------------------------------!Right::!Left::rotateY3D(keyStep*(InStr(A_ThisHotkey,"right")?1:-1))return; HotKey Rotate around X-Axis ----------------------------------!Up::!Down::rotateX3D(keyStep*(InStr(A_ThisHotkey,"Up")?1:-1))return; HotKey Rotate around Z-Axis ----------------------------------!PGUP::!PGDN::rotateZ3D(keyStep*(InStr(A_ThisHotkey,"UP")?1:-1))return; HotKey, Rotate around X/Y-Axis -------------------------------!LButton::MouseGetPos,pmouseX,pmouseYwhileGetKeyState("Lbutton","P"){MouseGetPos,mouseX,mouseYDeltaMX:=mouseX-pmouseXDeltaMY:=pmouseY-mouseYif(DeltaMX||DeltaMY){MouseGetPos,pmouseX,pmouseYrotateY3D(DeltaMX)rotateX3D(DeltaMY)}}return; HotKey Rotate around Z-Axis ----------------------------------!RButton::MouseGetPos,pmouseX,pmouseYwhileGetKeyState("Rbutton","P"){MouseGetPos,mouseX,mouseYDeltaMX:=mouseX-pmouseXDeltaMY:=mouseY-pmouseYDeltaMX*=mouseY<deltaY?mouseStep:-mouseStepDeltaMY*=mouseX>deltaX?mouseStep:-mouseStepif(DeltaMX||DeltaMY){MouseGetPos,pmouseX,pmouseYrotateZ3D(DeltaMX)rotateZ3D(DeltaMY)}}return; HotKey, Move -------------------------------------------------+LButton::MouseGetPos,pmouseX,pmouseYwhileGetKeyState("Lbutton","P"){MouseGetPos,mouseX,mouseYdeltaX+=mouseX-pmouseXdeltaY+=mouseY-pmouseYpmouseX:=mouseXpmouseY:=mouseYRedraw()}return; ---------------------------------------------------------------^esc::Exit:gdip2()Gdip_Shutdown(pToken)ExitAppReturn; ---------------------------------------------------------------


BASIC

BASIC256

global escalaglobal tamglobal zoffglobal cylrescala = 50tam = 320zoff = 0.5773502691896257645091487805019574556cylr = 1.6329931618554520654648560498039275946clggraphsize tam, tamdim x(6)theta = 0.0dtheta = 1.5dt = 1.0 / 30dim cylphi = {PI/6, 5*PI/6, 3*PI/2, 11*PI/6, PI/2, 7*PI/6}while key = ""    lasttime = msec    for i = 0 to 5        x[i] = tam/2 + escala *cylr * cos(cylphi[i] + theta)    next i    clg    call drawcube(x)    while msec < lasttime + dt    end while    theta += dtheta*(msec-lasttime)    pause .4    call drawcube(x)end whilesubroutine drawcube(x)    for i = 0 to 2        color rgb(0,0,0)  #black        line tam/2, tam/2 - escala / zoff, x[i], tam/2 - escala * zoff        line tam/2, tam/2 + escala / zoff, x[5-i], tam/2 + escala * zoff        line  x[i], tam/2 - escala * zoff, x[(i % 3) + 3], tam/2 + escala * zoff        line  x[i], tam/2 - escala * zoff, x[((i+1)%3) + 3], tam/2 + escala * zoff    next iend subroutine

Chipmunk Basic

Works with:Chipmunk Basic version 3.6.4
100cls110graphics0120graphicscolor0,0,0130whiletrue140graphicscls150x=cos(t)*20160y=sin(t)*18170r=sin(t+t)180moveto(x+40),(y+40-r)190lineto(-y+40),(x+40-r)200moveto(-y+40),(x+40-r)210lineto(-x+40),(-y+40-r)220moveto(-x+40),(-y+40-r)230lineto(y+40),(-x+40-r)240moveto(y+40),(-x+40-r)250lineto(x+40),(y+40-r)260moveto(x+40),(y+20+r)270lineto(-y+40),(x+20+r)280moveto(-y+40),(x+20+r)290lineto(-x+40),(-y+20+r)300moveto(-x+40),(-y+20+r)310lineto(y+40),(-x+20+r)320moveto(y+40),(-x+20+r)330lineto(x+40),(y+20+r)340moveto(x+40),(y+40-r)350lineto(x+40),(y+20+r)360moveto(-y+40),(x+40-r)370lineto(-y+40),(x+20+r)380moveto(-x+40),(-y+40-r)390lineto(-x+40),(-y+20+r)400moveto(y+40),(-x+40-r)410lineto(y+40),(-x+20+r)420fori=1to1000:nexti430t=t+0.15440wend

GW-BASIC

Works with:PC-BASIC version any
100SCREEN2110WHILE1120CLS130X=COS(T)*20140Y=SIN(T)*18150R=SIN(T+T)160LINE((X+40),(Y+40-R))-((-Y+40),(X+40-R))170LINE((-Y+40),(X+40-R))-((-X+40),(-Y+40-R))180LINE((-X+40),(-Y+40-R))-((Y+40),(-X+40-R))190LINE((Y+40),(-X+40-R))-((X+40),(Y+40-R))200LINE((X+40),(Y+20+R))-((-Y+40),(X+20+R))210LINE((-Y+40),(X+20+R))-((-X+40),(-Y+20+R))220LINE((-X+40),(-Y+20+R))-((Y+40),(-X+20+R))230LINE((Y+40),(-X+20+R))-((X+40),(Y+20+R))240LINE((X+40),(Y+40-R))-((X+40),(Y+20+R))250LINE((-Y+40),(X+40-R))-((-Y+40),(X+20+R))260LINE((-X+40),(-Y+40-R))-((-X+40),(-Y+20+R))270LINE((Y+40),(-X+40-R))-((Y+40),(-X+20+R))280T=T+.15290WEND

MSX Basic

Works with:MSX BASIC version any
100SCREEN2110COLOR15120CLS130X=COS(T)*20140Y=SIN(T)*18150R=SIN(T+T)160LINE((X+40),(Y+40-R))-((-Y+40),(X+40-R))170LINE((-Y+40),(X+40-R))-((-X+40),(-Y+40-R))180LINE((-X+40),(-Y+40-R))-((Y+40),(-X+40-R))190LINE((Y+40),(-X+40-R))-((X+40),(Y+40-R))200LINE((X+40),(Y+20+R))-((-Y+40),(X+20+R))210LINE((-Y+40),(X+20+R))-((-X+40),(-Y+20+R))220LINE((-X+40),(-Y+20+R))-((Y+40),(-X+20+R))230LINE((Y+40),(-X+20+R))-((X+40),(Y+20+R))240LINE((X+40),(Y+40-R))-((X+40),(Y+20+R))250LINE((-Y+40),(X+40-R))-((-Y+40),(X+20+R))260LINE((-X+40),(-Y+40-R))-((-X+40),(-Y+20+R))270LINE((Y+40),(-X+40-R))-((Y+40),(-X+20+R))280FORI=1TO40:NEXTI290T=T+0.15300GOTO120

C

Rotating wireframe cube inOpenGL, windowing implementation viafreeglut

#include<gl/freeglut.h>doublerot=0;floatmatCol[]={1,0,0,0};voiddisplay(){glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);glPushMatrix();glRotatef(30,1,1,0);glRotatef(rot,0,1,1);glMaterialfv(GL_FRONT,GL_DIFFUSE,matCol);glutWireCube(1);glPopMatrix();glFlush();}voidonIdle(){rot+=0.1;glutPostRedisplay();}voidreshape(intw,inth){floatar=(float)w/(float)h;glViewport(0,0,(GLsizei)w,(GLsizei)h);glTranslatef(0,0,-10);glMatrixMode(GL_PROJECTION);gluPerspective(70,(GLfloat)w/(GLfloat)h,1,12);glLoadIdentity();glFrustum(-1.0,1.0,-1.0,1.0,10.0,100.0);glMatrixMode(GL_MODELVIEW);glLoadIdentity();}voidinit(){floatpos[]={1,1,1,0};floatwhite[]={1,1,1,0};floatshini[]={70};glClearColor(.5,.5,.5,0);glShadeModel(GL_SMOOTH);glLightfv(GL_LIGHT0,GL_AMBIENT,white);glLightfv(GL_LIGHT0,GL_DIFFUSE,white);glMaterialfv(GL_FRONT,GL_SHININESS,shini);glEnable(GL_LIGHTING);glEnable(GL_LIGHT0);glEnable(GL_DEPTH_TEST);}intmain(intargC,char*argV[]){glutInit(&argC,argV);glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB|GLUT_DEPTH);glutInitWindowSize(600,500);glutCreateWindow("Rossetta's Rotating Cube");init();glutDisplayFunc(display);glutReshapeFunc(reshape);glutIdleFunc(onIdle);glutMainLoop();return0;}

C#

Translation of:Java
usingSystem;usingSystem.Drawing;usingSystem.Drawing.Drawing2D;usingSystem.Windows.Forms;usingSystem.Windows.Threading;namespaceRotatingCube{publicpartialclassForm1:Form{double[][]nodes={newdouble[]{-1,-1,-1},newdouble[]{-1,-1,1},newdouble[]{-1,1,-1},newdouble[]{-1,1,1},newdouble[]{1,-1,-1},newdouble[]{1,-1,1},newdouble[]{1,1,-1},newdouble[]{1,1,1}};int[][]edges={newint[]{0,1},newint[]{1,3},newint[]{3,2},newint[]{2,0},newint[]{4,5},newint[]{5,7},newint[]{7,6},newint[]{6,4},newint[]{0,4},newint[]{1,5},newint[]{2,6},newint[]{3,7}};publicForm1(){Width=Height=640;StartPosition=FormStartPosition.CenterScreen;SetStyle(ControlStyles.AllPaintingInWmPaint|ControlStyles.UserPaint|ControlStyles.DoubleBuffer,true);Scale(100,100,100);RotateCuboid(Math.PI/4,Math.Atan(Math.Sqrt(2)));vartimer=newDispatcherTimer();timer.Tick+=(s,e)=>{RotateCuboid(Math.PI/180,0);Refresh();};timer.Interval=newTimeSpan(0,0,0,0,17);timer.Start();}privatevoidRotateCuboid(doubleangleX,doubleangleY){doublesinX=Math.Sin(angleX);doublecosX=Math.Cos(angleX);doublesinY=Math.Sin(angleY);doublecosY=Math.Cos(angleY);foreach(varnodeinnodes){doublex=node[0];doubley=node[1];doublez=node[2];node[0]=x*cosX-z*sinX;node[2]=z*cosX+x*sinX;z=node[2];node[1]=y*cosY-z*sinY;node[2]=z*cosY+y*sinY;}}privatevoidScale(intv1,intv2,intv3){foreach(variteminnodes){item[0]*=v1;item[1]*=v2;item[2]*=v3;}}protectedoverridevoidOnPaint(PaintEventArgsargs){varg=args.Graphics;g.SmoothingMode=SmoothingMode.HighQuality;g.Clear(Color.White);g.TranslateTransform(Width/2,Height/2);foreach(varedgeinedges){double[]xy1=nodes[edge[0]];double[]xy2=nodes[edge[1]];g.DrawLine(Pens.Black,(int)Math.Round(xy1[0]),(int)Math.Round(xy1[1]),(int)Math.Round(xy2[0]),(int)Math.Round(xy2[1]));}foreach(varnodeinnodes){g.FillEllipse(Brushes.Black,(int)Math.Round(node[0])-4,(int)Math.Round(node[1])-4,8,8);}}}}

Delphi

Library: Winapi.Windows
Library: Vcl.Graphics
Library: Vcl.Controls
Library: Vcl.Forms
Library: Vcl.ExtCtrls
Library: System.Math
Library: System.Classes
Translation of:Javascript
unitmain;interfaceusesWinapi.Windows,Vcl.Graphics,Vcl.Controls,Vcl.Forms,Vcl.ExtCtrls,System.Math,System.Classes;typeTForm1=class(TForm)tmr1:TTimer;procedureFormCreate(Sender:TObject);proceduretmr1Timer(Sender:TObject);private{ Private declarations }public{ Public declarations }end;varForm1:TForm1;nodes:TArray<TArray<double>>=[[-1,-1,-1],[-1,-1,1],[-1,1,-1],[-1,1,1],[1,-1,-1],[1,-1,1],[1,1,-1],[1,1,1]];edges:TArray<TArray<Integer>>=[[0,1],[1,3],[3,2],[2,0],[4,5],[5,7],[7,6],[6,4],[0,4],[1,5],[2,6],[3,7]];implementation{$R *.dfm}procedureScale(factor:TArray<double>);beginifLength(factor)<>3thenexit;forvari:=0toHigh(nodes)doforvarf:=0toHigh(factor)donodes[i][f]:=nodes[i][f]*factor[f];end;procedureRotateCuboid(angleX,angleY:double);beginvarsinX:=sin(angleX);varcosX:=cos(angleX);varsinY:=sin(angleY);varcosY:=cos(angleY);forvari:=0toHigh(nodes)dobeginvarx:=nodes[i][0];vary:=nodes[i][1];varz:=nodes[i][2];nodes[i][0]:=x*cosX-z*sinX;nodes[i][2]:=z*cosX+x*sinX;z:=nodes[i][2];nodes[i][1]:=y*cosY-z*sinY;nodes[i][2]:=z*cosY+y*sinY;end;end;functionDrawCuboid(x,y,w,h:Integer):TBitmap;varoffset:TPoint;beginResult:=TBitmap.Create;Result.SetSize(w,h);rotateCuboid(PI/180,0);offset:=TPoint.Create(x,y);withResult.canvasdobeginBrush.Color:=clBlack;Pen.Color:=clWhite;Lock;FillRect(ClipRect);forvaredgeinedgesdobeginvarp1:=(nodes[edge[0]]);varp2:=(nodes[edge[1]]);moveTo(trunc(p1[0])+offset.x,trunc(p1[1])+offset.y);lineTo(trunc(p2[0])+offset.x,trunc(p2[1])+offset.y);end;Unlock;end;end;procedureTForm1.FormCreate(Sender:TObject);beginClientHeight:=360;ClientWidth:=640;DoubleBuffered:=true;scale([100,100,100]);rotateCuboid(PI/4,ArcTan(sqrt(2)));end;procedureTForm1.tmr1Timer(Sender:TObject);varbuffer:TBitmap;beginbuffer:=DrawCuboid(ClientWidthdiv2,ClientHeightdiv2,ClientWidth,ClientHeight);Canvas.Draw(0,0,buffer);buffer.Free;end;end.

Resource Form

objectForm1:TForm1OnCreate=FormCreateobjecttmr1:TTimerInterval=17OnTimer=tmr1Timerendend


EasyLang

Draws only the visible edges

Run it

node[][] = [ [ -1 -1 -1 ] [ -1 -1 1 ] [ -1 1 -1 ] [ -1 1 1 ] [ 1 -1 -1 ] [ 1 -1 1 ] [ 1 1 -1 ] [ 1 1 1 ] ]edge[][] = [ [ 1 2 ] [ 2 4 ] [ 4 3 ] [ 3 1 ] [ 5 6 ] [ 6 8 ] [ 8 7 ] [ 7 5 ] [ 1 5 ] [ 2 6 ] [ 3 7 ] [ 4 8 ] ]# proc scale f .   for i = 1 to len node[][] : for d = 1 to 3      node[i][d] *= f   ..proc rotate angx angy .   sinx = sin angx   cosx = cos angx   siny = sin angy   cosy = cos angy   for i = 1 to len node[][]      x = node[i][1]      z = node[i][3]      node[i][1] = x * cosx - z * sinx      y = node[i][2]      z = z * cosx + x * sinx      node[i][2] = y * cosy - z * siny      node[i][3] = z * cosy + y * siny   ..len nd[] 3proc draw .   gclear   m = 999   mi = -1   for i = 1 to len node[][]      if node[i][3] < m         m = node[i][3]         mi = i      .   .   ix = 1   for i = 1 to len edge[][]      if edge[i][1] = mi         nd[ix] = edge[i][2]         ix += 1      elif edge[i][2] = mi         nd[ix] = edge[i][1]         ix += 1      .   .   for ni = 1 to len nd[] : for i = 1 to len edge[][]      if edge[i][1] = nd[ni] or edge[i][2] = nd[ni]         x1 = node[edge[i][1]][1]         y1 = node[edge[i][1]][2]         x2 = node[edge[i][2]][1]         y2 = node[edge[i][2]][2]         gline x1 + 50 y1 + 50 x2 + 50 y2 + 50      .   ..scale 25rotate 45 atan sqrt 2drawon animate   rotate 1 0   draw.

Evaldraw

Based on the solution in draw cuboid.Draws a filled cube with a texture on each face.

Rotating 3D cube
Rotating cube with texture. Makes use of rudimentary glBegin(GL_QUADS) function
// We can define our own vec3 structstructvec3{x,y,z;}staticmodelMatrix[9];(){cls(0x828282);// clear screenclz(1e32);// clear depth buffersetcam(0,0,-3,0,0);// set camera some units back// create two local arrays to hold rotation matricesdoubleroty[9],rotz[9];staticotim;tim=klock(0);dt=tim-otim;otim=tim;staticdegrees=0;degrees+=200*dt;rads=degrees/180*pi;rotateZ(rotz,rads);rotateY(roty,rads);// evaldraw does support some GL-like drawing// modes, but any transformations must be done by hand// Here we use a global model matrix that// transforms vertices created by the myVertex functionmult(modelMatrix,roty,rotz);glSetTex("cloud.png");drawcuboid(0,0,0,1,1,1);}drawcuboid(x,y,z,sx,sy,sz){glBegin(GL_QUADS);setcol(192,32,32);glTexCoord(0,0);myVertex(x-sx,y-sy,z-sz);glTexCoord(1,0);myVertex(x+sx,y-sy,z-sz);glTexCoord(1,1);myVertex(x+sx,y+sy,z-sz);glTexCoord(0,1);myVertex(x-sx,y+sy,z-sz);setcol(32,192,32);glTexCoord(0,0);myVertex(x-sx,y-sy,z+sz);glTexCoord(1,0);myVertex(x-sx,y-sy,z-sz);glTexCoord(1,1);myVertex(x-sx,y+sy,z-sz);glTexCoord(0,1);myVertex(x-sx,y+sy,z+sz);setcol(32,32,192);glTexCoord(0,0);myVertex(x+sx,y-sy,z+sz);glTexCoord(1,0);myVertex(x-sx,y-sy,z+sz);glTexCoord(1,1);myVertex(x-sx,y+sy,z+sz);glTexCoord(0,1);myVertex(x+sx,y+sy,z+sz);setcol(192,192,32);glTexCoord(0,0);myVertex(x+sx,y-sy,z-sz);glTexCoord(1,0);myVertex(x+sx,y-sy,z+sz);glTexCoord(1,1);myVertex(x+sx,y+sy,z+sz);glTexCoord(0,1);myVertex(x+sx,y+sy,z-sz);setcol(192,32,192);glTexCoord(0,0);myVertex(x-sx,y-sy,z+sz);glTexCoord(1,0);myVertex(x+sx,y-sy,z+sz);glTexCoord(1,1);myVertex(x+sx,y-sy,z-sz);glTexCoord(0,1);myVertex(x-sx,y-sy,z-sz);setcol(32,192,192);glTexCoord(0,0);myVertex(x-sx,y+sy,z-sz);glTexCoord(1,0);myVertex(x+sx,y+sy,z-sz);glTexCoord(1,1);myVertex(x+sx,y+sy,z+sz);glTexCoord(0,1);myVertex(x-sx,y+sy,z+sz);glEnd();}myVertex(x,y,z){// Initialize a struct valuevec3v={x,y,z};// Apply global model matrix transformationtransformPoint(v,modelMatrix);// Submit the vertex to draw listglVertex(v.x,v.y,v.z);}rotateY(m[9],r){c=cos(r);s=sin(r);m[0]=c;m[1]=0;m[2]=s;m[3]=0;m[4]=1;m[5]=0;m[6]=-s;m[7]=0;m[8]=c;}rotateZ(m[9],r){c=cos(r);s=sin(r);m[0]=c;m[1]=-s;m[2]=0;m[3]=s;m[4]=c;m[5]=0;m[6]=0;m[7]=0;m[8]=1;}transformPoint(vec3v,m[9]){x2=v.x*m[0]+v.y*m[1]+v.z*m[2];y2=v.x*m[3]+v.y*m[4]+v.z*m[5];z2=v.x*m[6]+v.y*m[7]+v.z*m[8];// Mutate the struct v with new valuesv.x=x2;v.y=y2;v.z=z2;}mult(c[9],a[9],b[9]){// C = AB// multiply a row in A with a column in Bfor(i=0;i<3;i++)for(j=0;j<3;j++){sum=0.0;for(k=0;k<3;k++){sum+=A[k*3+i]*B[k*3+j];}C[i*3+j]=sum;}}

FreeBASIC

#definePI3.14159265358979323#defineSCALE50#defineSIZE320#definezoff0.5773502691896257645091487805019574556#definecylr1.6329931618554520654648560498039275946screenresSIZE,SIZE,4dimasdoubletheta=0.0,dtheta=1.5,x(0to5),lasttime,dt=1./30dimasdoublecylphi(0to5)={PI/6,5*PI/6,3*PI/2,11*PI/6,PI/2,7*PI/6}subdrawcube(x()asdouble,colourasuinteger)foriasuinteger=0to2line(SIZE/2,SIZE/2-SCALE/zoff)-(x(i),SIZE/2-SCALE*zoff),colourline(SIZE/2,SIZE/2+SCALE/zoff)-(x(5-i),SIZE/2+SCALE*zoff),colourline(x(i),SIZE/2-SCALE*zoff)-(x(imod3+3),SIZE/2+SCALE*zoff),colourline(x(i),SIZE/2-SCALE*zoff)-(x((i+1)mod3+3),SIZE/2+SCALE*zoff),colournextiendsubwhileinkey=""lasttime=timerforiasuinteger=0to5x(i)=SIZE/2+SCALE*cylr*cos(cylphi(i)+theta)nextidrawcubex(),15whiletimer<lasttime+dtwendtheta+=dtheta*(timer-lasttime)drawcubex(),0wendend

FutureBasic

FB 7.0.35 macOS 14.7.2 Sonoma

include "Tlbx SceneKit.incl"_window = 1begin enum output 1  _sceneViewend enumlocal fn RotatingCubeScene as SCNSceneRef  SCNSceneRef   scene = fn SCNSceneInit  SCNNodeRef rootNode = fn SCNSceneRootNode( scene )    SCNCameraRef camera = fn SCNCameraInit  SCNNodeRef cameraNode = fn SCNNodeInit  SCNNodeSetCamera( cameraNode, camera )  SCNNodeAddChildNode( rootNode, cameraNode )    SCNVector3 cameraPos = {0.0, 0.0, 10.0}  SCNNodeSetPosition( cameraNode, cameraPos )    SCNNodeRef lightNode = fn SCNNodeInit  SCNLightRef    light = fn SCNLightInit  SCNLightSetType( light, SCNLightTypeOmni )  SCNNodeSetPosition( lightNode, fn SCNVector3Make( 0.0, 10.0, 10.0 ) )  SCNNodeAddChildNode( rootNode, lightNode )    SCNNodeRef    ambientLightNode = fn SCNNodeInit  SCNLightRef       ambientLight = fn SCNLightInit  SCNLightSetType(  ambientLight, SCNLightTypeAmbient )  SCNLightSetColor( ambientLight, fn ColorGray )  SCNNodeSetLight( ambientLightNode, ambientLight )  SCNNodeAddChildNode( rootNode, ambientLightNode )    SCNBoxRef  boxGeometry = fn SCNBoxInit( 4.0, 4.0, 4.0, 0.0 )  SCNNodeRef boxNode = fn SCNNodeWithGeometry( boxGeometry )    SCNMaterialRef side1 = fn SCNMaterialInit  SCNMaterialRef side2 = fn SCNMaterialInit  SCNMaterialRef side3 = fn SCNMaterialInit  SCNMaterialRef side4 = fn SCNMaterialInit  SCNMaterialRef side5 = fn SCNMaterialInit  SCNMaterialRef side6 = fn SCNMaterialInit    SCNMaterialPropertySetContents( fn SCNMaterialMultiply( side1 ), fn ColorBlue   )  SCNMaterialPropertySetContents( fn SCNMaterialMultiply( side2 ), fn ColorOrange )  SCNMaterialPropertySetContents( fn SCNMaterialMultiply( side3 ), fn ColorRed    )  SCNMaterialPropertySetContents( fn SCNMaterialMultiply( side4 ), fn ColorGreen  )  SCNMaterialPropertySetContents( fn SCNMaterialMultiply( side5 ), fn ColorYellow )  SCNMaterialPropertySetContents( fn SCNMaterialMultiply( side6 ), fn ColorCyan   )    SCNGeometrySetMaterials( boxGeometry, @[side1,side2,side3,side4,side5,side6] )  SCNNodeAddChildNode( rootNode, boxNode )  SCNActionableRunAction( boxNode, fn SCNActionRepeatActionForever( fn SCNActionRotateByAngle( M_PI, fn SCNVector3Make( 0.0, 25.0, 5.0 ), 5.0 ) ) )end fn = scenevoid local fn BuildWindow  window _window, @"Rosetta Code Rotating Cube", ( 0, 0, 600, 600 )  scnview _sceneView, fn RotatingCubeScene, ( 0, 0, 600, 600 )  SCNViewSetBackgroundColor( _sceneView, fn ColorBlack )  SCNViewSetAllowsCameraControl( _sceneView, YES )end fnvoid local fn DoDialog( ev as long, tag as long, wnd as long )  select (ev)    case _windowWillClose : end  end selectend fnon dialog fn DoDialogfn BuildWindowHandleEvents
Output:

Go

As of Go 1.9, it looks as if the only standard library supporting animated graphics is image/gif - so we create an animated GIF...

packagemainimport("image""image/color""image/gif""log""math""os")const(width,height=640,640offset=height/2fileName="rotatingCube.gif")varnodes=[][]float64{{-100,-100,-100},{-100,-100,100},{-100,100,-100},{-100,100,100},{100,-100,-100},{100,-100,100},{100,100,-100},{100,100,100}}varedges=[][]int{{0,1},{1,3},{3,2},{2,0},{4,5},{5,7},{7,6},{6,4},{0,4},{1,5},{2,6},{3,7}}funcmain(){varimages[]*image.PalettedfgCol:=color.RGBA{0xff,0x00,0xff,0xff}varpalette=[]color.Color{color.RGBA{0x00,0x00,0x00,0xff},fgCol}vardelays[]intimgFile,err:=os.Create(fileName)iferr!=nil{log.Fatal(err)}deferimgFile.Close()rotateCube(math.Pi/4,math.Atan(math.Sqrt(2)))varframefloat64forframe=0;frame<360;frame++{img:=image.NewPaletted(image.Rect(0,0,width,height),palette)images=append(images,img)delays=append(delays,5)for_,edge:=rangeedges{xy1:=nodes[edge[0]]xy2:=nodes[edge[1]]drawLine(int(xy1[0])+offset,int(xy1[1])+offset,int(xy2[0])+offset,int(xy2[1])+offset,img,fgCol)}rotateCube(math.Pi/180,0)}iferr:=gif.EncodeAll(imgFile,&gif.GIF{Image:images,Delay:delays});err!=nil{imgFile.Close()log.Fatal(err)}}funcrotateCube(angleX,angleYfloat64){sinX:=math.Sin(angleX)cosX:=math.Cos(angleX)sinY:=math.Sin(angleY)cosY:=math.Cos(angleY)for_,node:=rangenodes{x:=node[0]y:=node[1]z:=node[2]node[0]=x*cosX-z*sinXnode[2]=z*cosX+x*sinXz=node[2]node[1]=y*cosY-z*sinYnode[2]=z*cosY+y*sinY}}funcdrawLine(x0,y0,x1,y1int,img*image.Paletted,colcolor.RGBA){dx:=abs(x1-x0)dy:=abs(y1-y0)varsx,syint=-1,-1ifx0<x1{sx=1}ify0<y1{sy=1}err:=dx-dyfor{img.Set(x0,y0,col)ifx0==x1&&y0==y1{break}e2:=2*errife2>-dy{err-=dyx0+=sx}ife2<dx{err+=dxy0+=sy}}}funcabs(xint)int{ifx<0{return-x}returnx}

Haskell

This implementation compiles to JavaScript that runs in a browser using theghcjs compiler . Thereflex-dom library is used to help with svg rendering and animation.

{-# LANGUAGE RecursiveDo #-}importReflex.DomimportData.MapasDM(Map,lookup,insert,empty,fromList)importData.MatriximportData.Time.ClockimportControl.Monad.Transsize=500updateFrequency=0.2rotationStep=pi/10dataColor=Red|Green|Blue|Yellow|Orange|Purple|Blackderiving(Show,Eq,Ord,Enum)zRot::Float->MatrixFloatzRotrotation=letc=cosrotations=sinrotationinfromLists[[c,s,0,0],[-s,c,0,0],[0,0,1,0],[0,0,0,1]]xRot::Float->MatrixFloatxRotrotation=letc=cosrotations=sinrotationinfromLists[[1,0,0,0],[0,c,s,0],[0,-s,c,0],[0,0,0,1]]yRot::Float->MatrixFloatyRotrotation=letc=cosrotations=sinrotationinfromLists[[c,0,-s,0],[0,1,0,0],[s,0,c,0],[0,0,0,1]]translation::(Float,Float,Float)->MatrixFloattranslation(x,y,z)=fromLists[[1,0,0,0],[0,1,0,0],[0,0,1,0],[x,y,z,1]]scale::Float->MatrixFloatscales=fromLists[[s,0,0,0],[0,s,0,0],[0,0,s,0],[0,0,0,1]]-- perspective transformation;perspective::MatrixFloatperspective=fromLists[[1,0,0,0],[0,1,0,0],[0,0,1,1],[0,0,1,1]]transformPoints::MatrixFloat->MatrixFloat->[(Float,Float)]transformPointstransformpoints=letresult4d=points`multStd2`transformresult2d=(\[x,y,z,w]->(x/w,y/w))<$>toListsresult4dinresult2dshowRectangle::MonadWidgettm=>Float->Float->Float->Float->Color->Dynamict(MatrixFloat)->m()showRectanglex0y0x1y1faceColordFaceView=doletpoints=fromLists[[x0,y0,0,1],[x0,y1,0,1],[x1,y1,0,1],[x1,y0,0,1]]pointsToString=concatMap(\(x,y)->showx++", "++showy++" ")dAttrs<-mapDyn(\fvk->DM.fromList[("fill",showfaceColor),("points",pointsToString(transformPointsfvkpoints))])dFaceViewelDynAttrSVG"polygon"dAttrs$return()showUnitSquare::MonadWidgettm=>Color->Float->Dynamict(MatrixFloat)->m()showUnitSquarefaceColormargindFaceView=showRectanglemarginmargin(1.0-margin)(1.0-margin)faceColordFaceView-- show colored square on top of black square for outline effectshowFace::MonadWidgettm=>Color->Dynamict(MatrixFloat)->m()showFacefaceColordFaceView=doshowUnitSquareBlack0dFaceViewshowUnitSquarefaceColor0.03dFaceViewfacingCamera::[Float]->MatrixFloat->BoolfacingCameraviewPointmodelTransform=letcross[x0,y0,z0][x1,y1,z1]=[y0*z1-z0*y1,z0*x1-x0*z1,x0*y1-y0*x1]dotv0v1=sum$zipWith(*)v0v1vMinus=zipWith(-)untransformedPoints=fromLists[[0,0,0,1]-- lower left,[1,0,0,1]-- lower right,[0,1,0,1]]-- upper lefttransformedPoints=toLists$untransformedPoints`multStd2`modelTransformpt00=take3$headtransformedPoints-- transformed lower leftpt10=take3$transformedPoints!!1-- transformed upper rightpt01=take3$transformedPoints!!2-- transformed upper lefttVec_10_00=pt10`vMinus`pt00-- lower right to lower lefttVec_01_00=pt01`vMinus`pt00-- upper left to lower leftperpendicular=tVec_10_00`cross`tVec_01_00-- perpendicular to facecameraToPlane=pt00`vMinus`viewPoint-- line of sight to face-- Perpendicular points away from surface;-- Camera vector points towards surface-- Opposed vectors means that face will be visible.incameraToPlane`dot`perpendicular<0faceView::MatrixFloat->MatrixFloat->(Bool,MatrixFloat)faceViewmodelOrientationfaceOrientation=letmodelTransform=translation(-1/2,-1/2,1/2)-- unit square to origin + z offset`multStd2`faceOrientation-- orientation specific to each face`multStd2`scale(1/2)-- shrink cube to fit in view.`multStd2`modelOrientation-- position the entire cubeisFacingCamera=facingCamera[0,0,-1]modelTransform-- backface elimination-- combine to get single transform from 2d face to 2d displayviewTransform=modelTransform`multStd2`perspective`multStd2`scalesize-- scale up to svg box scale`multStd2`translation(size/2,size/2,0)-- move to center of svg boxin(isFacingCamera,viewTransform)updateFaceViews::MatrixFloat->MapColor(MatrixFloat)->(Color,MatrixFloat)->MapColor(MatrixFloat)updateFaceViewsmodelOrientationprevCollection(faceColor,faceOrientation)=let(isVisible,newFaceView)=faceViewmodelOrientationfaceOrientationinifisVisibletheninsertfaceColornewFaceViewprevCollectionelseprevCollectionfaceViews::MatrixFloat->MapColor(MatrixFloat)faceViewsmodelOrientation=foldl(updateFaceViewsmodelOrientation)empty[(Purple,xRot(0.0)),(Yellow,xRot(pi/2)),(Red,yRot(pi/2)),(Green,xRot(-pi/2)),(Blue,yRot(-pi/2)),(Orange,xRot(pi))]viewModel::MonadWidgettm=>Dynamict(MatrixFloat)->m()viewModelmodelOrientation=dofaceMap<-mapDynfaceViewsmodelOrientationlistWithKeyfaceMapshowFacereturn()view::MonadWidgettm=>Dynamict(MatrixFloat)->m()viewmodelOrientation=doel"h1"$text"Rotating Cube"elDynAttrSVG"svg"(constDyn$DM.fromList[("width",showsize),("height",showsize)])$viewModelmodelOrientationmain=mainWidget$doletinitialOrientation=xRot(pi/4)`multStd2`zRot(atan(1/sqrt(2)))update_modelOrientation=modelOrientation`multStd2`(yRot(rotationStep))tick<-tickLossyupdateFrequency=<<liftIOgetCurrentTimerecviewmodelOrientationmodelOrientation<-foldDynupdateinitialOrientationtickreturn()-- At end because of Rosetta Code handling of unmatched quotes.elDynAttrSVGa2a3a4=doelDynAttrNS'(Just"http://www.w3.org/2000/svg")a2a3a4return()

Link to live demo:https://dc25.github.io/drawRotatingCubeHaskell/

J

Derived from J'sqt shader demo:

require'gl2 gles ide/qt/opengl'coinsert'jgl2 jgles qtopengl'rotcube=:{{if.0=nc<'sprog'do.return.end.fixosx=.'opengl';'opengl',('DARWIN'-:UNAME)#' version 4.1'wd'pc rot; minwh 300 300; cc cube opengl flush'rplcfixosxHD=:".wd'qhwndc cube'wd'ptimer 17; pshow'}}rot_close=:{{wd'ptimer 0'glDeleteBuffers::0:2;vboglDeleteProgram::0:sprogerase'sprog'wd'pclose'}}cstr=:{{if.ydo.memry,0_12else.EMPTYend.}}gstr=:{{cstr>{.glGetStringy}}diag=:{{p[echoy,': ',p=.gstr".y}}blitf=:{{dat=.1fc,yNB. short floatsglBindBufferGL_ARRAY_BUFFER;x{vboglBufferDataGL_ARRAY_BUFFER;(#dat);(symdat<'dat');GL_STATIC_DRAW}}rot_cube_initialize=:{{erase'sprog'if.0=#diag'GL_VERSION'do.echo'cannot retrieve GL_VERSION'return.end.diageach;:'GL_VENDOR GL_RENDERER GL_SHADING_LANGUAGE_VERSION'GLSL=:wglGLSL''wglPROC'''err program'=.gl_makeprogramVSRC;&fixversionFSRCif.#errdo.echo'err: ',errreturn.end.if.GLSL>120do.vao=:>{:glGenVertexArrays1;,_1end.assert_1~:vertexAttr=:>{.glGetAttribLocationprogram;'vertex'assert_1~:colorAttr=:>{.glGetAttribLocationprogram;'color'assert_1~:mvpUni=:>{.glGetUniformLocationprogram;'mvp'vbo=:>{:glGenBuffers2;2#_10blitfvertexData1blitfcolorDatasprog=:program}}VSRC=:{{)n#version$version$v_in$highpvec3vertex;$v_in$lowpvec3color;$v_out$lowpvec4v_color;uniformmat4mvp;voidmain(void){gl_Position=mvp*vec4(vertex,1.0);v_color=vec4(color,1.0);}}}FSRC=:{{)n#version$version$f_in$lowpvec4v_color;$fragColorvoidmain(void){$gl_fragColor=v_color;}}}fixversion=:{{NB. cope with host shader language versionr=.'$version';GLSL,&":;(GLSL>:300)#(*GLES_VERSION){' core';' es'f1=.GLSL<:120r=.r,'$v_in';f1{'in';'attribute'r=.r,'$v_out';f1{'out';'varying'r=.r,'$f_in';f1{'in';'varying'r=.r,'$highp ';f1#(*GLES_VERSION)#'highp'r=.r,'$lowp ';f1#(*GLES_VERSION)#'lowp'f2=.(330<:GLSL)+.(300<:GLSL)**GLES_VERSIONr=.r,'$gl_fragColor';f2{'gl_FragColor';'fragColor'r=.r,'$fragColor';f2#'out vec4 fragColor;'yrplcr}}rot_timer=:{{try.gl_selHDgl_paint''catch.echo'error in rot_timer',LF,13!:12''wd'ptimer 0'end.}}zeroVAttr=:{{glEnableVertexAttribArrayyglBindBufferGL_ARRAY_BUFFER;x{vboglVertexAttribPointery;3;GL_FLOAT;0;0;0}}mp=:+/.*ref=:(gl_Translate00_10)mpglu_LookAt001,000,100rot_cube_paint=:{{try.if.nc<'sprog'do.return.end.wh=.gl_qwh''glClearGL_COLOR_BUFFER_BIT+GL_DEPTH_BUFFER_BIT[glClearColor0000+%3glUseProgramsprogglEnableeachGL_DEPTH_TEST,GL_CULL_FACE,GL_BLENDglBlendFuncGL_SRC_ALPHA;GL_ONE_MINUS_SRC_ALPHAmvp=.(gl_Rotate(360|60*6!:1''),100)mprefmpgl_Perspective30,(%/wh),120glUniformMatrix4fvmvpUni;1;GL_FALSE;mvpif.GLSL>120do.glBindVertexArray{.vaoend.0zeroVAttrvertexAttr1zeroVAttrcolorAttrglDrawArraysGL_TRIANGLES;0;36glUseProgram0catch.echo'error in rot_cube_paint',LF,13!:12''wd'ptimer 0'end.}}NB. oriented triangle representation of unit cubeunitCube=:#:(012,213)&{@".;._2{{)n2301NB. unit cube corner indices3715NB. 0: origin4051NB. 1, 2, 4: unit distance along each axis6240NB. 3, 5, 6, 7:  combinations of axes76547362}}NB. orient cube so diagonal is along first axisdaxis=:(_1^56e.~i.33)*%:6%~204,231,:231vertexData=:(_1^unitCube)mpdaxisNB. cube with center at origincolorData=:unitCubeNB. corresponding colorsrotcube''

A variation which did not use opengl would probably be much more concise.

Java

importjava.awt.*;importjava.awt.event.ActionEvent;import staticjava.lang.Math.*;importjavax.swing.*;publicclassRotatingCubeextendsJPanel{double[][]nodes={{-1,-1,-1},{-1,-1,1},{-1,1,-1},{-1,1,1},{1,-1,-1},{1,-1,1},{1,1,-1},{1,1,1}};int[][]edges={{0,1},{1,3},{3,2},{2,0},{4,5},{5,7},{7,6},{6,4},{0,4},{1,5},{2,6},{3,7}};publicRotatingCube(){setPreferredSize(newDimension(640,640));setBackground(Color.white);scale(100);rotateCube(PI/4,atan(sqrt(2)));newTimer(17,(ActionEvente)->{rotateCube(PI/180,0);repaint();}).start();}finalvoidscale(doubles){for(double[]node:nodes){node[0]*=s;node[1]*=s;node[2]*=s;}}finalvoidrotateCube(doubleangleX,doubleangleY){doublesinX=sin(angleX);doublecosX=cos(angleX);doublesinY=sin(angleY);doublecosY=cos(angleY);for(double[]node:nodes){doublex=node[0];doubley=node[1];doublez=node[2];node[0]=x*cosX-z*sinX;node[2]=z*cosX+x*sinX;z=node[2];node[1]=y*cosY-z*sinY;node[2]=z*cosY+y*sinY;}}voiddrawCube(Graphics2Dg){g.translate(getWidth()/2,getHeight()/2);for(int[]edge:edges){double[]xy1=nodes[edge[0]];double[]xy2=nodes[edge[1]];g.drawLine((int)round(xy1[0]),(int)round(xy1[1]),(int)round(xy2[0]),(int)round(xy2[1]));}for(double[]node:nodes)g.fillOval((int)round(node[0])-4,(int)round(node[1])-4,8,8);}@OverridepublicvoidpaintComponent(Graphicsgg){super.paintComponent(gg);Graphics2Dg=(Graphics2D)gg;g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);drawCube(g);}publicstaticvoidmain(String[]args){SwingUtilities.invokeLater(()->{JFramef=newJFrame();f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);f.setTitle("Rotating Cube");f.setResizable(false);f.add(newRotatingCube(),BorderLayout.CENTER);f.pack();f.setLocationRelativeTo(null);f.setVisible(true);});}}

JavaScript

Translation of:Java
<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><style>canvas{background-color:black;}</style></head><body><canvas></canvas><script>varcanvas=document.querySelector("canvas");canvas.width=window.innerWidth;canvas.height=window.innerHeight;varg=canvas.getContext("2d");varnodes=[[-1,-1,-1],[-1,-1,1],[-1,1,-1],[-1,1,1],[1,-1,-1],[1,-1,1],[1,1,-1],[1,1,1]];varedges=[[0,1],[1,3],[3,2],[2,0],[4,5],[5,7],[7,6],[6,4],[0,4],[1,5],[2,6],[3,7]];functionscale(factor0,factor1,factor2){nodes.forEach(function(node){node[0]*=factor0;node[1]*=factor1;node[2]*=factor2;});}functionrotateCuboid(angleX,angleY){varsinX=Math.sin(angleX);varcosX=Math.cos(angleX);varsinY=Math.sin(angleY);varcosY=Math.cos(angleY);nodes.forEach(function(node){varx=node[0];vary=node[1];varz=node[2];node[0]=x*cosX-z*sinX;node[2]=z*cosX+x*sinX;z=node[2];node[1]=y*cosY-z*sinY;node[2]=z*cosY+y*sinY;});}functiondrawCuboid(){g.save();g.clearRect(0,0,canvas.width,canvas.height);g.translate(canvas.width/2,canvas.height/2);g.strokeStyle="#FFFFFF";g.beginPath();edges.forEach(function(edge){varp1=nodes[edge[0]];varp2=nodes[edge[1]];g.moveTo(p1[0],p1[1]);g.lineTo(p2[0],p2[1]);});g.closePath();g.stroke();g.restore();}scale(200,200,200);rotateCuboid(Math.PI/4,Math.atan(Math.sqrt(2)));setInterval(function(){rotateCuboid(Math.PI/180,0);drawCuboid();},17);</script></body></html>

Julia

Run at the Julia REPL command line.

usingMakie,LinearAlgebraN=40interval=0.10scene=mesh(FRect3D(Vec3f0(-0.5),Vec3f0(1)),color=:skyblue2)rect=scene[end]forradin0.5:1/N:8.5arr=normalize([cospi(rad/2),0,sinpi(rad/2),-sinpi(rad/2)])Makie.rotate!(rect,Quaternionf0(arr[1],arr[2],arr[3],arr[4]))sleep(interval)end

Kotlin

Translation of:Java
// version 1.1importjava.awt.*importjavax.swing.*classRotatingCube:JPanel(){privatevalnodes=arrayOf(doubleArrayOf(-1.0,-1.0,-1.0),doubleArrayOf(-1.0,-1.0,1.0),doubleArrayOf(-1.0,1.0,-1.0),doubleArrayOf(-1.0,1.0,1.0),doubleArrayOf(1.0,-1.0,-1.0),doubleArrayOf(1.0,-1.0,1.0),doubleArrayOf(1.0,1.0,-1.0),doubleArrayOf(1.0,1.0,1.0))privatevaledges=arrayOf(intArrayOf(0,1),intArrayOf(1,3),intArrayOf(3,2),intArrayOf(2,0),intArrayOf(4,5),intArrayOf(5,7),intArrayOf(7,6),intArrayOf(6,4),intArrayOf(0,4),intArrayOf(1,5),intArrayOf(2,6),intArrayOf(3,7))init{preferredSize=Dimension(640,640)background=Color.whitescale(100.0)rotateCube(Math.PI/4.0,Math.atan(Math.sqrt(2.0)))Timer(17){rotateCube(Math.PI/180.0,0.0)repaint()}.start()}privatefunscale(s:Double){for(nodeinnodes){node[0]*=snode[1]*=snode[2]*=s}}privatefunrotateCube(angleX:Double,angleY:Double){valsinX=Math.sin(angleX)valcosX=Math.cos(angleX)valsinY=Math.sin(angleY)valcosY=Math.cos(angleY)for(nodeinnodes){valx=node[0]valy=node[1]varz=node[2]node[0]=x*cosX-z*sinXnode[2]=z*cosX+x*sinXz=node[2]node[1]=y*cosY-z*sinYnode[2]=z*cosY+y*sinY}}privatefundrawCube(g:Graphics2D){g.translate(width/2,height/2)for(edgeinedges){valxy1=nodes[edge[0]]valxy2=nodes[edge[1]]g.drawLine(Math.round(xy1[0]).toInt(),Math.round(xy1[1]).toInt(),Math.round(xy2[0]).toInt(),Math.round(xy2[1]).toInt())}for(nodeinnodes){g.fillOval(Math.round(node[0]).toInt()-4,Math.round(node[1]).toInt()-4,8,8)}}overridepublicfunpaintComponent(gg:Graphics){super.paintComponent(gg)valg=ggasGraphics2Dg.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON)g.color=Color.bluedrawCube(g)}}funmain(args:Array<String>){SwingUtilities.invokeLater{valf=JFrame()f.defaultCloseOperation=JFrame.EXIT_ON_CLOSEf.title="Rotating cube"f.isResizable=falsef.add(RotatingCube(),BorderLayout.CENTER)f.pack()f.setLocationRelativeTo(null)f.isVisible=true}}

Lua

localabs,atan,cos,floor,pi,sin,sqrt=math.abs,math.atan,math.cos,math.floor,math.pi,math.sin,math.sqrtlocalbitmap={init=function(self,w,h,value)self.w,self.h,self.pixels=w,h,{}fory=1,hdoself.pixels[y]={}endself:clear(value)end,clear=function(self,value)fory=1,self.hdoforx=1,self.wdoself.pixels[y][x]=valueor"  "endendend,set=function(self,x,y,value)x,y=floor(x),floor(y)ifx>0andy>0andx<=self.wandy<=self.hthenself.pixels[y][x]=valueor"#"endend,line=function(self,x1,y1,x2,y2,c)x1,y1,x2,y2=floor(x1),floor(y1),floor(x2),floor(y2)localdx,sx=abs(x2-x1),x1<x2and1or-1localdy,sy=abs(y2-y1),y1<y2and1or-1localerr=floor((dx>dyanddxor-dy)/2)while(true)doself:set(x1,y1,c)if(x1==x2andy1==y2)thenbreakendif(err>-dx)thenerr,x1=err-dy,x1+sxif(x1==x2andy1==y2)thenself:set(x1,y1,c)breakendendif(err<dy)thenerr,y1=err+dx,y1+syendendend,render=function(self)fory=1,self.hdoprint(table.concat(self.pixels[y]))endend,}screen={clear=function()os.execute("cls")-- or? os.execute("clear"), or? io.write("\027[2J\027[H"), or etc?end,}localcamera={fl=2.5}localL=0.5localcube={verts={{L,L,L},{L,-L,L},{-L,-L,L},{-L,L,L},{L,L,-L},{L,-L,-L},{-L,-L,-L},{-L,L,-L}},edges={{1,2},{2,3},{3,4},{4,1},{5,6},{6,7},{7,8},{8,5},{1,5},{2,6},{3,7},{4,8}},rotate=function(self,rx,ry)localcx,sx=cos(rx),sin(rx)localcy,sy=cos(ry),sin(ry)fori,vinipairs(self.verts)dolocalx,y,z=v[1],v[2],v[3]v[1],v[2],v[3]=x*cx-z*sx,y*cy-x*sx*sy-z*cx*sy,x*sx*cy+y*sy+z*cx*cyendend,}localrenderer={render=function(self,shape,camera,bitmap)localfl=camera.fllocalox,oy=bitmap.w/2,bitmap.h/2localmx,my=bitmap.w/2,bitmap.h/2localrpverts={}fori,vinipairs(shape.verts)dolocalx,y,z=v[1],v[2],v[3]localpx=ox+mx*(fl*x)/(fl-z)localpy=oy+my*(fl*y)/(fl-z)rpverts[i]={px,py}endfori,einipairs(shape.edges)dolocalv1,v2=rpverts[e[1]],rpverts[e[2]]bitmap:line(v1[1],v1[2],v2[1],v2[2],"██")endend}--bitmap:init(40,40)cube:rotate(pi/4,atan(sqrt(2)))fori=1,60docube:rotate(pi/60,0)bitmap:clear("··")renderer:render(cube,camera,bitmap)screen:clear()bitmap:render()end
Output:
Frame 1:······················································································································██············································································██████········································································████····██····································································██··██······██································································██····██········██····························································██······██··········██··························································██······██············██······················································██······██················██··················································██········██··················██··············································██········████····················██··········································██········██····██····················██······································██········██········██····················██··································██········██············██····················██······························██········██················██················████······························████····██····················██············██····██··························██····████························██········██······██························██······████··························██····██········██························██····██····████························████············██····················██····██··········██······················████············██····················██··██··············██················████····██··········██··················██··██··················████··········██··········██··········██················████························██······██··············████······██··············████····························██████····················██····██··············██································██························██··██············██··································██··························██··██············██································██····························████··············████····························██························████······················██··························██······················██····························████······················██··················████··································████··················██··············████··········································██················██············██················································████············██········████······················································██··········██······██····························································████······██··████··································································████··████··········································································████························································································································································································································································································Frame 60:······················································································································██············································································██████········································································██··██··██··································································████····██····████····························································██········██········██······················································████··········██··········████··············································████··············██··············██··········································██··················██················██····································████····················██··················████······························██························██······················██························████··························██························████················████······························██····························████············████······························██····························████··············████····························████························████················██··██························██····██····················██··██··················██··██····················██········████··············██····██··················██····██··············████··············██··········██····██····················██······██··········██····················██······██······██······················██······██······██························██████········██······················██········██████····························████······██························██········████····························██····██····██··························██··████····██························██········████····························████··········████··················██············██······························██··············██··············██············██··································██··············██··········██············██······································██··············██······██············██··········································██··············██████············██··············································██··············██············██··················································██············██············██····················································██··········██··········██························································██········██········██····························································██······██······██································································██····██····██····································································██··██··██········································································██████············································································██························································································································································································································································································

M2000 Interpreter

Cube Example

Draw on M2000 console. Using of GDI+ for smooth lines. Using Every {} structure and Refresh 100 to immediate refresh double buffer, and set 100ms for the next auto refresh. So we erase the screen without refresh and draw again after dt time. Cube has 6 more lines for fancy drawing. Also time displayed. We can move the cube (and accelarate the rotation as we press a mouse button).









Module Cube3D {form 80, 32smooth on   // enable GDI+ smooth lineszoff=0.5773502691896257645091487805019574556@cylr=1.6329931618554520654648560498039275946@oX=scale.x div 2 : oY=scale.y div 2SCALE=min.data(oX, oY)/2*.6gradient 0theta = 0.0 : dtheta = 1.5 : dt = 1000/60ScZof=SCALE/zoffScZofM=SCALE*zoffdim cylphi(), x()c =(PI/6, 5*PI/6, 3*PI/2, 11*PI/6, PI/2, 7*PI/6) : c*=180/Pi : cylphi()=c // cos() take Degreeevery DT {if mouse then (oX, oY)=(mouse.x,mouse.y) : dtheta*=1.05 else dtheta = 1.5dim x(6)=oX : for i=0 to 5: x(i) += SCALE*cylr*cos(cylphi(i)+theta):nextdrawcube() : refresh 100 : IF keypress(32) then exittheta += dtheta : gradient 0, 5: cursor 0,0Print "Press space to exit",,"Press any mouse button to move cube",,Time$(Now)}sub drawcube()for i= 0 to 2move x(i), oY-ScZofM:draw to oX,oY-ScZof, 11move oX,ScZof+oY:draw to x(i),oY-ScZofM, 9move oX,oY+ ScZof:draw to x(5-i),ScZofM+oYmove x(i),oY-ScZofM:draw to x(i mod 3 + 3),oY+ScZofM, 15move oX,oY-ScZof:draw to x(i mod 3 + 3), oY+ScZofM, 7move x(i),oY-ScZofM:draw to x((i+1) mod 3 + 3),oY+ScZofM, 13nextend sub}Cube3D

Maple

plots:-display(seq(plots:-display(plottools[cuboid]([0,0,0],[1,1,1]),axes=none,scaling=constrained,orientation=[0,45,i]),i=0..360,20),insequence=true);

Mathematica /Wolfram Language

Dynamic[Graphics3D[GeometricTransformation[GeometricTransformation[Cuboid[],RotationTransform[Pi/4,{1,1,0}]],RotationTransform[Clock[2Pi],{0,0,1}]],Boxed->False]]

MiniScript

Works with:Mini Micro
import"mathUtil"scale=250radius=sqrt(scale^2)Face=newSpriteFace.image=file.loadImage("/sys/pics/shapes/SquareThin.png")clear;gfx.clearcolor.graysprites=display(4).sprites// build a sprite for each sideforiinrange(0,3)sp=newFacesp.x=480;sp.y=320yBot=-sin(pi/4)yTop=sin(pi/4)cosAngL=cos(i*pi/2);sinAngL=sin(i*pi/2)cosAngR=cos((i+1)*pi/2);sinAngR=sin((i+1)*pi/2)sp.corners3d=[[cosAngL,yBot,sinAngL],[cosAngR,yBot,sinAngR],[cosAngR,yTop,sinAngR],[cosAngL,yTop,sinAngL]]sp.color=[color.yellow,color.aqua,color.pink,color.lime][i]sprites.pushspendfor// ...and one for the toptop=newFacetop.x=480;top.y=320top.corners3d=[]foriinrange(0,3)top.corners3d.push[cos(i*pi/2),sin(pi/4),sin(i*pi/2)]endforsprites.pushtop// Rotate the given [x,y,z] point by some number of degrees// around the Y axis, then project to the screen.rotateAndProject=function(point3d,rotDegrees)radians=rotDegrees*pi/180cosAng=cos(radians);sinAng=sin(radians)// First, rotate around the Y axis in 3D spacex=point3d[0]*cosAng-point3d[2]*sinAngy=point3d[1]z=point3d[0]*sinAng+point3d[2]*cosAng// Then, project this to the screenresult=[480+x*scale,320+y*scale+z*0]p=(8-z)/8// (perspective factor)returnmathUtil.lerp2d(result,[480,800],1-p)endfunction// Position all the sprites where they should be on screen for the given rotation.positionSprites=function(rotDegrees)forspinspritescorners=[]foriinrange(0,3)corners.pushrotateAndProject(sp.corners3d[i],rotDegrees)endforsp.setCornerscornersifsp==topthencontinueifcorners[1][0]>corners[0][0]thensp.tint=sp.colorelsesp.tint=color.clearendifendforendfunction// Main programrot=0whilenotkey.pressed("escape")andnotkey.pressed("q")yieldpositionSpritesrotrot=rot+1endwhilekey.clear
Output:

MiniScript spinning cube solution

Nim

Translation of:Ada
Library:SDL2
importmathimportsdl2constWidth=500Height=500Offset=500/2varnodes=[(x:-100.0,y:-100.0,z:-100.0),(x:-100.0,y:-100.0,z:100.0),(x:-100.0,y:100.0,z:-100.0),(x:-100.0,y:100.0,z:100.0),(x:100.0,y:-100.0,z:-100.0),(x:100.0,y:-100.0,z:100.0),(x:100.0,y:100.0,z:-100.0),(x:100.0,y:100.0,z:100.0)]constEdges=[(a:0,b:1),(a:1,b:3),(a:3,b:2),(a:2,b:0),(a:4,b:5),(a:5,b:7),(a:7,b:6),(a:6,b:4),(a:0,b:4),(a:1,b:5),(a:2,b:6),(a:3,b:7)]varwindow:WindowPtrrenderer:RendererPtrevent:EventendSimulation=false#---------------------------------------------------------------------------------------------------procrotateCube(angleX,angleY:float)=letsinX=sin(angleX)cosX=cos(angleX)sinY=sin(angleY)cosY=cos(angleY)fornodeinnodes.mitems:var(x,y,z)=nodenode.x=x*cosX-z*sinXnode.z=z*cosX+x*sinXz=node.znode.y=y*cosY-z*sinYnode.z=z*cosY+y*sinY#---------------------------------------------------------------------------------------------------procpollQuit():bool=whilepollEvent(event):ifevent.kind==QuitEvent:returntrue#---------------------------------------------------------------------------------------------------procdrawCube():bool=varrect:Rect=(cint(0),cint(0),cint(Width),cint(Height))rotateCube(PI/4,arctan(sqrt(2.0)))forframein0..359:renderer.setDrawColor((0u8, 0u8, 0u8, 255u8))renderer.fillRect(addr(rect))renderer.setDrawColor((0u8, 220u8, 0u8, 255u8))foredgeinEdges:letxy1=nodes[edge.a]letxy2=nodes[edge.b]renderer.drawLine(cint(xy1.x+Offset),cint(xy1.y+Offset),cint(xy2.x+Offset),cint(xy2.y+Offset))rotateCube(PI/180,0)renderer.present()ifpollQuit():returntruedelay10#———————————————————————————————————————————————————————————————————————————————————————————————————ifsdl2.init(INIT_EVERYTHING)==SdlError:quit(QuitFailure)window=createWindow("Rotating cube",10,10,500,500,0)renderer=createRenderer(window,-1,Renderer_Accelerated)whilenotendSimulation:endSimulation=drawCube()window.destroy()

Objeck

Library:SDL2
Translation of:Ada
#~Rotating Cube~#use Collection.Generic;use Game.SDL2;use Game.Framework;class RotatingCube {  # game framework  @framework : GameFramework;  @initialized : Bool;  @nodes : Float[,];  @edges : Int[,];  New() {    @initialized := true;    @framework := GameFramework->New(GameConsts->SCREEN_WIDTH, GameConsts->SCREEN_HEIGHT, "Rotating Cube");    @nodes := [[-100.0, -100.0, -100.0], [-100.0, -100.0, 100.0], [-100.0, 100.0, -100.0],       [-100.0, 100.0, 100.0],   [100.0, -100.0, -100.0], [100.0, -100.0, 100.0],       [100.0, 100.0, -100.0],   [100.0, 100.0, 100.0]];        @edges := [[0, 1], [1, 3], [3, 2], [2, 0], [4, 5], [5, 7],           [7, 6], [6, 4], [0, 4], [1, 5], [2, 6], [3, 7]];  }  function : Main(args : String[]) ~ Nil {    RotatingCube->New()->Play();  }  method : Play() ~ Nil {    if(@initialized) {      # initialization      @framework->SetClearColor(Color->New(0, 0, 0));      RotateCube(Float->Pi(), 2.0->SquareRoot()->ArcTan());      quit := false;      e := @framework->GetEvent();      while(<>quit) {        @framework->FrameStart();        @framework->Clear();                # process input        while(e->Poll() <> 0) {          if(e->GetType() = EventType->SDL_QUIT) {            quit := true;          };        };        #draw        DrawCube();        @framework->FrameEnd();        # render        @framework->Show();        Timer->Delay(200);        RotateCube (Float->Pi() / 180.0, 0.0);      };    }    else {      "--- Error Initializing Environment ---"->ErrorLine();      return;    };    leaving {      @framework->FreeShapes();    };  }  method : RotateCube(angleX : Float, angleY : Float) ~ Nil {    sinX := angleX->Sin();        cosX := angleX->Cos();         sinY := angleY->Sin();        cosY := angleY->Cos();     node_sizes := @nodes->Size();    size := node_sizes[0];        for(i := 0; i < size; i += 1;) {            x := @nodes[i, 0];            y := @nodes[i, 1];            z := @nodes[i, 2];             @nodes[i, 0] := x * cosX - z * sinX;            @nodes[i, 2] := z * cosX + x * sinX;             z := @nodes[i, 2];             @nodes[i, 1] := y * cosY - z * sinY;            @nodes[i, 2] := z * cosY + y * sinY;        };   }  method : DrawCube() ~ Nil {    edge_sizes := @edges->Size();    size := edge_sizes[0];    @framework->GetRenderer()->SetDrawColor(0, 220, 0, 0);    for(i := 0; i < size; i += 1;) {      x0y0  := @nodes[@edges[i, 0], 0];      x0y1  := @nodes[@edges[i, 0], 1];      x1y0  := @nodes[@edges[i, 1], 0];      x1y1  := @nodes[@edges[i, 1], 1];      @framework->GetRenderer()->DrawLine(x0y0 + GameConsts->DRAW_OFFSET, x0y1 + GameConsts->DRAW_OFFSET, x1y0 + GameConsts->DRAW_OFFSET, x1y1 + GameConsts->DRAW_OFFSET);    };  }}consts GameConsts {  SCREEN_WIDTH := 600,  SCREEN_HEIGHT := 600,  DRAW_OFFSET := 300}

OxygenBasic

Using An OpenGl-based console

  % Title "Rotating Cube"  % Animated  % PlaceCentral  uses ConsoleG  sub main  ========  cls 0.0, 0.5, 0.7  shading  scale 7  pushstate    GoldMaterial.act    static float ang    rotateX ang    rotateY ang    go cube  popstate  ang+=.5 : if ang>=360 then ang-=360  end sub  EndScript

PascalABC.NET

usesGraph3D;beginvarCube:=Box(Origin,Sz3D(3,3,3),Colors.Green);Cube.AnimRotate(OrtZ,180).Forever.Beginend.


Perl

#!/usr/bin/perlusestrict;# http://www.rosettacode.org/wiki/Draw_a_rotating_cubeusewarnings;useTk;useTime::HiResqw( time );my$size=600;my$wait=int1000/30;my($height,$width)=($size,$size*sqrt8/9);my$mid=$width/2;my$rot=atan2(0,-1)/3;# middle corners every 60 degreesmy$mw=MainWindow->new;my$c=$mw->Canvas(-width=>$width,-height=>$height)->pack;$c->Tk::bind('<ButtonRelease>'=>sub{$mw->destroy});# click to exitdraw();MainLoop;subdraw{my$angle=time-$^T;# full rotation every 2*PI secondsmy@points=map{$mid+$mid*cos$angle+$_*$rot,$height*($_%2+1)/3}0..5;$c->delete('all');$c->createLine(@points[-12..1],$mid,0,-width=>5,);$c->createLine(@points[4,5],$mid,0,@points[8,9],-width=>5,);$c->createLine(@points[2,3],$mid,$height,@points[6,7],-width=>5,);$c->createLine($mid,$height,@points[10,11],-width=>5,);$mw->after($wait,\&draw);}

Phix

Library:Phix/pGUI
Library:Phix/online

You can run this onlinehere.

---- demo\rosetta\DrawRotatingCube.exw-- =================================---- credits:http://petercollingridge.appspot.com/3D-tutorial/rotating-objects--https://github.com/ssloy/tinyrenderer/wiki/Lesson-4:-Perspective-projection---- Aside: low CPU usage, at least when using a 30ms timer (33 FPS, which is plenty).--withjavascript_semanticsincludepGUI.econstanttitle="Draw a Rotating Cube"Ihandledlg,canvascdCanvascd_canvas---- First, define 8 corners equidistant from {0,0,0}:----          6-----2--      5-----1   3--      8-----4  ---- ie the right face is 1-2-3-4 clockwise, and the left face--  is 5-6-7-8 counter-clockwise (unless using x-ray vision).-- (since this is not drawing textures, clockwise-ness does --  not matter, as shown by the corrected orange face, but--  it will if you (figure out how to) apply any textures.)-- (a quick (online) study of opengl texture documentation--  should convince you that stuff is best left to opengl.)--enumX,Y,Zconstantl=100constantcorners={{+l,+l,+l},-- 1 (front top right){+l,+l,-l},-- 2 (back top "right"){+l,-l,-l},-- 3 (back btm "right"){+l,-l,+l},-- 4 (front btm right){-l,+l,+l},-- 5 (front top left){-l,+l,-l},-- 6 (back top "left"){-l,-l,-l},-- 7 (back btm "left"){-l,-l,+l}}-- 8 (front btm left)-- I put left/right in quotes for the back face as a reminder-- those match the above diagram, but of course they would be-- swapped were you looking "at" the face/rotated it by 180.constantfaces={{CD_RED,1,2,3,4},-- right{CD_YELLOW,1,5,6,2},-- top{CD_DARK_GREEN,1,4,8,5},-- front{CD_BLUE,2,3,7,6},-- back{CD_WHITE,3,4,8,7},-- bottom--                {CD_ORANGE,       5,6,7,8}}   -- left{CD_ORANGE,8,7,6,5}}-- left-- rotation angles, 0..359, on a timeratomrx=45,-- initially makes cube like a Hry=35,--     "   "    "italic Hrz=0constantnaxes={{Y,Z},-- (rotate about the X-axis){X,Z},-- (rotate about the Y-axis){X,Y}}-- (rotate about the Z-axis)functionrotate(sequencepoints,atomangle,integeraxis)---- rotate points by the specified angle about the given axis--atomradians=angle*CD_DEG2RAD,sin_t=sin(radians),cos_t=cos(radians)integer{nx,ny}=naxes[axis]fori=1tolength(points)doatomx=points[i][nx],y=points[i][ny]points[i][nx]=x*cos_t-y*sin_tpoints[i][ny]=y*cos_t+x*sin_tendforreturnpointsendfunctionfunctionprojection(sequencepoints,atomd)---- project points from {0,0,d} onto the perpendicular plane through {0,0,0}--fori=1tolength(points)doatom{x,y,z}=points[i],denom=(1-z/d)points[i][X]=x/denompoints[i][Y]=y/denomendforreturnpointsendfunctionfunctionnearest(sequencepoints)---- return the index of the nearest point (highest z value)--returnlargest(vslice(points,Z),true)endfunctionproceduredraw_cube(integercx,cy)-- {cx,cy} is the centre point of the canvassequencepoints=deep_copy(corners)points=rotate(points,rx,X)points=rotate(points,ry,Y)points=rotate(points,rz,Z)points=projection(points,1000)integernp=nearest(points)--    -- find the three faces that contain the nearest point,    -- then for each of those faces let diag be the point    -- that is diagonally opposite said nearest point, and    -- order by/draw those faces furthest diag away first.    --  (one or two of them may be completely obscured due     --   to the effects of the perspective projection.)    --  (you could of course draw all six faces, as long as    --   the 3 furthest are draw first/obliterated, which    --   is what that commented-out "else" would achieve.)    --sequencefaceset={}fori=1tolength(faces)dosequencefi=faces[i]integerk=find(np,fi)-- k:=2..5, or 0ifkthenintegerdiag=mod(k,4)+2-- {2,3,4,5} --> {4,5,2,3}                                      -- aka swap 2<=>4 & 3<=>5diag=fi[diag]-- 1..8, diagonally opp. npfaceset=append(faceset,{points[diag][Z],i})--      else--          faceset = append(faceset,{-9999,i})endifendforfaceset=sort(faceset)fori=1tolength(faceset)dosequenceface=faces[faceset[i][2]]cdCanvasSetForeground(cd_canvas,face[1])-- first fill sides (with bresenham edges), then        -- redraw edges, but anti-aliased aka smoothersequencemodes={CD_FILL,CD_CLOSED_LINES}form=1tolength(modes)docdCanvasBegin(cd_canvas,modes[m])forfdx=2to5dosequencept=points[face[fdx]]cdCanvasVertex(cd_canvas,cx+pt[X],cy-pt[Y])endforcdCanvasEnd(cd_canvas)endforendforendprocedurefunctioncanvas_action_cb(Ihandlecanvas)cdCanvasActivate(cd_canvas)cdCanvasClear(cd_canvas)integer{w,h}=IupGetIntInt(canvas,"DRAWSIZE")draw_cube(floor(w/2),floor(h/2))cdCanvasFlush(cd_canvas)returnIUP_DEFAULTendfunctionfunctioncanvas_map_cb(Ihandlecanvas)IupGLMakeCurrent(canvas)ifplatform()=JSthencd_canvas=cdCreateCanvas(CD_IUP,canvas)elseatomres=IupGetDouble(NULL,"SCREENDPI")/25.4cd_canvas=cdCreateCanvas(CD_GL,"10x10 %g",{res})endifcdCanvasSetBackground(cd_canvas,CD_PARCHMENT)returnIUP_DEFAULTendfunctionfunctioncanvas_resize_cb(Ihandle/*canvas*/)integer{canvas_width,canvas_height}=IupGetIntInt(canvas,"DRAWSIZE")atomres=IupGetDouble(NULL,"SCREENDPI")/25.4cdCanvasSetAttribute(cd_canvas,"SIZE","%dx%d %g",{canvas_width,canvas_height,res})returnIUP_DEFAULTendfunctionfunctiontimer_cb(Ihandln/*ih*/)-- (feel free to add a bit more randomness here, maybe)rx=mod(rx+359,360)ry=mod(ry+359,360)rz=mod(rz+359,360)IupRedraw(canvas)returnIUP_IGNOREendfunctionproceduremain()IupOpen()canvas=IupGLCanvas("RASTERSIZE=640x480")IupSetCallbacks(canvas,{"ACTION",Icallback("canvas_action_cb"),"MAP_CB",Icallback("canvas_map_cb"),"RESIZE_CB",Icallback("canvas_resize_cb")})dlg=IupDialog(canvas,`TITLE="%s"`,{title})IupShow(dlg)IupSetAttribute(canvas,"RASTERSIZE",NULL)IhandlehTimer=IupTimer(Icallback("timer_cb"),30)ifplatform()!=JSthenIupMainLoop()IupClose()endifendproceduremain()

PostScript

Don't send this to your printer!

%!PS-Adobe-3.0%%BoundingBox: 0 0 400 400/ed{exchdef}def/roty{dupsin/sedcos/ced[[c0sneg][010][s0c]]}def/rotz{dupsin/sedcos/ced[[csneg0][sc0][001]]}def/dot{/aed/beda0getb0getmula1getb1getmula2getb2getmuladdadd}def/mmul{/ved[exch{vdot}forall]}def/transall{/med[exch{mexchmmul}forall]}def/vt[[111][-111][1-11][-1-11][11-1][-11-1][1-1-1][-1-1-1]]-45rotytransall2sqrt1atanrotztransalldef/xy{exchget{}forallpop}def/page{/aed/vvtarotytransalldef0setlinewidth100100scale22translate/edge{vxymovetovxylinetostroke}def0123456702134657041526371112{popedge}forshowpage}def0{3.2addduppage}loop%%EOF

Processing

Create a cube in Processing with box(), rotate the scene with rotate(), and drive the rotation with either the built-in millis() or frameCount timers.

void setup() {  size(500, 500, P3D);}void draw() {  background(0);  // position  translate(width/2, height/2, -width/2);  // optional fill and lighting colors  noStroke();  strokeWeight(4);  fill(192, 255, 192);  pointLight(255, 255, 255, 0, -500, 500);  // rotation driven by built-in timer  rotateY(millis()/1000.0);  // draw box  box(300, 300, 300);}

Python

Library:VPython

Works with:Python version 2.7.9

See also:Draw_a_cuboid

Short version

fromvisualimport*scene.title="VPython: Draw a rotating cube"scene.range=2scene.autocenter=Trueprint"Drag with right mousebutton to rotate view."print"Drag up+down with middle mousebutton to zoom."deg45=math.radians(45.0)# 0.785398163397cube=box()# using defaults, see http://www.vpython.org/contents/docs/defaults.htmlcube.rotate(angle=deg45,axis=(1,0,0))cube.rotate(angle=deg45,axis=(0,0,1))whileTrue:# Animation-looprate(50)cube.rotate(angle=0.005,axis=(0,1,0))


Racket

#langracket/gui(requiremath/matrixmath/array)(define(Rxθ)(matrix[[1.00.00.0][0.0(cosθ)(-(sinθ))][0.0(sinθ)(cosθ)]]))(define(Ryθ)(matrix[[(cosθ)0.0(sinθ)][0.01.00.0][(-(sinθ))0.0(cosθ)]]))(define(Rzθ)(matrix[[(cosθ)(-(sinθ))0.0][(sinθ)(cosθ)0.0][0.00.01.0]]))(definebase-matrix(matrix*(identity-matrix3100.0)(Rx(-(/pi2)(atan(sqrt2))))(Rz(/pi4.0))))(define(current-matrix)(matrix*(Ry(/(current-inexact-milliseconds)1000.))base-matrix))(definecorners(for*/list([x'(-1.01.0)][y'(-1.01.0)][z'(-1.01.0)])(matrix[[x][y][z]])))(definelines'((01)(02)(04)(13)(15)(23)(26)(37)(45)(46)(57)(67)))(defineox200.)(defineoy200.)(define(draw-linedcab)(senddcdraw-line(+ox(array-refa#(00)))(+oy(array-refa#(10)))(+ox(array-refb#(00)))(+oy(array-refb#(10)))))(define(draw-cubecdc)(define-values(wh)(senddcget-size))(set!ox(/w2))(set!oy(/h2))(definecs(for/vector([c(in-listcorners)])(matrix*(current-matrix)c)))(for([l(in-listlines)])(match-define(listij)l)(draw-linedc(vector-refcsi)(vector-refcsj))))(definef(newframe%[label"cube"]))(definec(newcanvas%[parentf][min-width400][min-height400][paint-callbackdraw-cube]))(sendfshow#t)(send*(sendcget-dc)(set-pen"black"1'solid)(set-smoothing'smoothed))(define(refresh)(sendcrefresh))(definet(newtimer%[notify-callbackrefresh][interval35][just-once?#f]))

Raku

(formerly Perl 6)

Works with:Rakudo version 2018.12

Raku has no native graphics libraries built in, but makes it fairly easy to bind to third party libraries. Here we'll use bindings toLibcaca, theColorASCIIArt library to generate a rotating cube in an ASCII terminal.

useTerminal::Caca;givenmy$canvas =Terminal::Caca.new {    .title('Rosetta Code - Rotating cube - Press any key to exit');subscale-and-translate($x,$y,$z) {$x *5 / (5 +$z ) *15 +40,$y *5 / (5 +$z ) *7 +15,$z;    }subrotate3d-x($x,$y,$z,$angle ) {my ($cosθ,$sinθ) =cis($angle *π /180.0 ).reals;$x,$y *$cosθ -$z *$sinθ,$y *$sinθ +$z *$cosθ;    }subrotate3d-y($x,$y,$z,$angle ) {my ($cosθ,$sinθ) =cis($angle *π /180.0 ).reals;$x *$cosθ -$z *$sinθ,$y,$x *$sinθ +$z *$cosθ;    }subrotate3d-z($x,$y,$z,$angle ) {my ($cosθ,$sinθ) =cis($angle *π /180.0 ).reals;$x *$cosθ -$y *$sinθ,$x *$cosθ +$y *$sinθ,$z;    }# Unit cube from polygon mesh, aligned to axesmy@mesh =      [ [1,1, -1], [-1, -1, -1], [-1,1, -1] ],# far face      [ [1,1, -1], [-1, -1, -1], [1, -1, -1] ],      [ [1,1,1], [-1, -1,1], [-1,1,1] ],# near face      [ [1,1,1], [-1, -1,1], [1, -1,1] ];@mesh.push: [$_».rotate(1)».Array]for@mesh[^4];# positive and@mesh.push: [$_».rotate(-1)».Array]for@mesh[^4];# negative rotations# Rotate to correct orientation for taskfor ^@meshX ^@mesh[0] -> ($i,$j) {        @(@mesh[$i;$j]) =rotate3d-x |@mesh[$i;$j],45;        @(@mesh[$i;$j]) =rotate3d-z |@mesh[$i;$j],40;    }my@colors =red,blue,green,cyan,magenta,yellow;loop {for ^359 ->$angle {            .color(white,white );            .clear;# Flatten 3D into 2D and rotate for all facesmy@faces-z;my$c-index =0;for@mesh ->@triangle {my@points;my$sum-z =0;for@triangle ->@node {my ($px,$py,$z) =scale-and-translate |rotate3d-y |@node,$angle;@points.append:$px.Int,$py.Int;$sum-z +=$z;                }@faces-z.push: %(color  =>@colors[$c-index++div2],points =>@points,avg-z  =>$sum-z / +@points;                );            }# Draw all faces# Sort by z to draw farthest firstfor@faces-z.sort( -*.<avg-z> ) ->%face {# Draw filled triangle                .color(%face<color>,%face<color> );                .fill-triangle( |%face<points> );# And frame                .color(black,black );                .thin-triangle( |%face<points> );            }            .refresh;exitif .wait-for-event(key-press);        }    }# Cleanup on scope exitLEAVE {        .cleanup;    }}

Ring

#===================================================================## Based on Original Sample from RayLib (https://www.raylib.com/)# Ported to RingRayLib by Ring Team#===================================================================#load "raylib.ring"screenWidth = 800screenHeight = 450InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d picking")camera = Camera3D(10, 10, 10,0, 0, 0 ,0, 1, 0 ,45,CAMERA_PERSPECTIVE)cubePosition = Vector3( 0, 1, 0 )cubeSize = Vector3( 2, 2, 2 )ray = Ray(0,0,0,0,0,0)collision = falseSetCameraMode(camera, CAMERA_FREE) SetTargetFPS(60)while !WindowShouldClose()        UpdateCamera(camera)        if IsMouseButtonPressed(MOUSE_LEFT_BUTTON)            if !collision                ray = GetMouseRay(GetMousePosition(), camera)                collision = CheckCollisionRayBox(ray, BoundingBox( cubePosition.x - cubeSize.x/2, cubePosition.y - cubeSize.y/2, cubePosition.z - cubeSize.z/2,    cubePosition.x + cubeSize.x/2, cubePosition.y + cubeSize.y/2, cubePosition.z + cubeSize.z/2 ) )            else collision = false     okok        BeginDrawing()            ClearBackground(RAYWHITE)            BeginMode3D(camera)                if collision                    DrawCube(cubePosition, cubeSize.x, cubeSize.y, cubeSize.z, RED)                    DrawCubeWires(cubePosition, cubeSize.x, cubeSize.y, cubeSize.z, MAROON)                    DrawCubeWires(cubePosition, cubeSize.x + 0.2f, cubeSize.y + 0.2f, cubeSize.z + 0.2f, GREEN)                else                    DrawCube(cubePosition, cubeSize.x, cubeSize.y, cubeSize.z, GRAY)                    DrawCubeWires(cubePosition, cubeSize.x, cubeSize.y, cubeSize.z, DARKGRAY)                ok                DrawRay(ray, MAROON)                DrawGrid(10, 1)            EndMode3D()            DrawText("Try selecting the box with mouse!", 240, 10, 20, DARKGRAY)            if collision  DrawText("BOX SELECTED", (screenWidth - MeasureText("BOX SELECTED", 30)) / 2, screenHeight * 0.1f, 30, GREEN) ok            DrawFPS(10, 10)        EndDrawing()endCloseWindow()

Rotating a Cube

Scala

Java Swing Interoperability

Library:Scala Java Swing interoperability
Library:Scala GUI Animation
Works with:Scala version 2.13
importjava.awt.event.ActionEventimportjava.awt._importjavax.swing.{JFrame,JPanel,Timer}importscala.math.{Pi,atan,cos,sin,sqrt}objectRotatingCubeextendsApp{classRotatingCubeextendsJPanel{privatevalvertices:Vector[Array[Double]]=Vector(Array(-1,-1,-1),Array(-1,-1,1),Array(-1,1,-1),Array(-1,1,1),Array(1,-1,-1),Array(1,-1,1),Array(1,1,-1),Array(1,1,1))privatevaledges:Vector[(Int,Int)]=Vector((0,1),(1,3),(3,2),(2,0),(4,5),(5,7),(7,6),(6,4),(0,4),(1,5),(2,6),(3,7))setPreferredSize(newDimension(640,640))setBackground(Color.white)scale(100)rotateCube(Pi/4,atan(sqrt(2)))newTimer(17,(_:ActionEvent)=>{rotateCube(Pi/180,0)repaint()}).start()overridedefpaintComponent(gg:Graphics):Unit={defdrawCube(g:Graphics2D):Unit={g.translate(getWidth/2,getHeight/2)for{edge<-edgesxy1:Array[Double]=vertices(edge._1)xy2:Array[Double]=vertices(edge._2)}{g.drawLine(xy1(0).toInt,xy1(1).toInt,xy2(0).toInt,xy2(1).toInt)g.fillOval(xy1(0).toInt-4,xy1(1).toInt-4,8,8)g.setColor(Color.black)}}super.paintComponent(gg)valg:Graphics2D=gg.asInstanceOf[Graphics2D]g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON)drawCube(g)}privatedefscale(s:Double):Unit={for{node<-verticesi<-node.indices}node(i)*=s}privatedefrotateCube(angleX:Double,angleY:Double):Unit={defsinCos(x:Double)=(sin(x),cos(x))val((sinX,cosX),(sinY,cosY))=(sinCos(angleX),sinCos(angleY))for{node<-verticesx:Double=node(0)y:Double=node(1)}{deff(p:Double,q:Double)(a:Double,b:Double)=a*p+b*qdeffx(a:Double,b:Double)=f(cosX,sinX)(a,b)deffy(a:Double,b:Double)=f(cosY,sinY)(a,b)node(0)=fx(x,-node(2))valz=fx(node(2),x)node(1)=fy(y,-z)node(2)=fy(z,y)}}}newJFrame("Rotating Cube"){add(newRotatingCube(),BorderLayout.CENTER)pack()setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE)setLocationRelativeTo(null)setResizable(false)setVisible(true)}}

Tcl

See alsoDraw a cuboid. This implementation uses tcllib'sLinear Algebra module for some matrix ops to handle the screen transform and (animated!) rotation. Rendering is in a Tk canvas.

The *Matrix* procedure is something unique to Tcl: it's essentially a control construct that leverages *expr* to make declaring matrices much more convenient than hand-rolling lists.

There is a bit of wander in the top and bottom points, which might just be due to rounding error in the cube's initial "rotation into position".

Seethis wiki page (and others linked from it) for many similar examples.

# matrix operation support:packagerequiremath::linearalgebranamespaceimport::math::linearalgebra::matmulnamespaceimport::math::linearalgebra::crossproductnamespaceimport::math::linearalgebra::dotproductnamespaceimport::math::linearalgebra::sub# returns a cube as a list of faces,# where each face is a list of (3space) pointsprocmake_cube{{radius1}}{setdirs{A{111}B{11-1}C{1-1-1}D{1-11}E{-111}F{-11-1}G{-1-1-1}H{-1-11}}setfaces{{ABCD}{DCGH}{HGFE}{EFBA}{ADHE}{CBFG}}lmapfa$faces{lmapdir$fa{lmapx[dictget$dirs$dir]{expr{1.0*$x*$radius}}}}}# a matrix constructorprocMatrix{m}{tailcalllmaprow$m{lmape$row{expr1.0*($e)}}}procidentity{}{Matrix{{100}{010}{001}}}# some matrices useful for animation:procrotateZ{theta}{Matrix{{cos($theta)-sin($theta)0}{sin($theta)cos($theta)0}{001}}}procrotateY{theta}{Matrix{{sin($theta)0cos($theta)}{010}{cos($theta)0-sin($theta)}}}procrotateX{theta}{Matrix{{100}{0cos($theta)-sin($theta)}{0sin($theta)cos($theta)}}}proccamera{flen}{Matrix{{$flen00}{0$flen0}{000}}}procrender{canvasobject}{setW[winfowidth$canvas]setH[winfoheight$canvas]setfl1.0sett[expr{[clockmicroseconds]/1000000.0}]settransform[identity]settransform[matmul$transform[rotateX[expr{atan(1)}]]]settransform[matmul$transform[rotateZ[expr{atan(1)}]]]settransform[matmul$transform[rotateY$t]]settransform[matmul$transform[camera$fl]]foreachface$object{# do transformations into screen space:setpoints[lmapp$face{matmul$p$transform}]# calculate a normalseto[lindex$points0]setv1[sub[lindex$points1]$o]setv2[sub[lindex$points2]$o]setnormal[crossproduct$v1$v2]setcosi[dotproduct$normal{00-1.0}]if{$cosi<=0}{;# rear-facing!continue}setpoints[lmapp$points{lassign$pxylist[expr{$x+$W/2}][expr{$y+$H/2}]}]setpoints[concat{*}$points]$canvascreatepoly$points-outlineblack-fillred}}packagerequireTkpack[canvas.c]-expandyes-fillbothproctick{}{.cdeleteallrender.c$::worldafter50tick}set::world[make_cube100]tick

TI-83 BASIC

:-1→Xmin:1→Xmax:-1→Ymin:1→Ymax:AxesOff:Degrees:While 1:For(X,0,359,5:sin(X-120→I%:sin(X→PV:sin(X+120→FV:Line(0,1,I%,.3:Line(0,1,PV,.3:Line(0,1,FV,.3:Line(0,-1,-I%,-.3:Line(0,-1,-PV,-.3:Line(0,-1,-FV,-.3:Line(.3,I%,-.3,-PV:Line(.3,I%,-.3,-FV:Line(.3,PV,-.3,-I%:Line(.3,PV,-.3,-FV:Line(.3,FV,-.3,-I%:Line(.3,FV,-.3,-PV:End:End

I%, PV, and FV are all finance variables that can be found in the finance menu (inside the APPS menu on TI-83+ and up).Finance variables are much faster than normal variables.

Wren

Translation of:Kotlin
Library:DOME
import"graphics"forCanvas,Colorimport"dome"forWindowimport"math"forMathvarNodes=[[-1,-1,-1],[-1,-1,1],[-1,1,-1],[-1,1,1],[1,-1,-1],[1,-1,1],[1,1,-1],[1,1,1]]varEdges=[[0,1],[1,3],[3,2],[2,0],[4,5],[5,7],[7,6],[6,4],[0,4],[1,5],[2,6],[3,7]]classRotatingCube{constructnew(width,height){Window.title="Rotating cube"Window.resize(width,height)Canvas.resize(width,height)_width=width_height=height_fore=Color.blue}init(){scale(100)rotateCube(Num.pi/4,Math.atan(2.sqrt))drawCube()}update(){rotateCube(Num.pi/180,0)}draw(alpha){drawCube()}scale(s){for(nodeinNodes){node[0]=node[0]*snode[1]=node[1]*snode[2]=node[2]*s}}drawCube(){Canvas.cls(Color.white)Canvas.offset(_width/2,_height/2)for(edgeinEdges){varxy1=Nodes[edge[0]]varxy2=Nodes[edge[1]]Canvas.line(Math.round(xy1[0]),Math.round(xy1[1]),Math.round(xy2[0]),Math.round(xy2[1]),_fore)}for(nodeinNodes){Canvas.rectfill(Math.round(node[0])-4,Math.round(node[1])-4,8,8,_fore)}}rotateCube(angleX,angleY){varsinX=Math.sin(angleX)varcosX=Math.cos(angleX)varsinY=Math.sin(angleY)varcosY=Math.cos(angleY)for(nodeinNodes){varx=node[0]vary=node[1]varz=node[2]node[0]=x*cosX-z*sinXnode[2]=z*cosX+x*sinXz=node[2]node[1]=y*cosY-z*sinYnode[2]=z*cosY+y*sinY}}}varGame=RotatingCube.new(640,640)

XPL0

The main challenge was figuring out the initial coordinates of the cube.Zometool came to the rescue. The program runs much smoother than the animated gif.

def  Size=100., Speed=0.05;             \drawing size and rotation speedreal X, Y, Z, Farthest;                 \arrays: 3D coordinates of verticesint  I, J, K, ZI, Edge;def  R2=sqrt(2.), R3=sqrt(3.), R13=sqrt(1./3.), R23=sqrt(2./3.), R232=R23*2.;\vertex:0       1       2       3       4       5       6       7[X:= [  0.,     R2,     0.,    -R2,     0.,     R2,     0.,    -R2]; Y:= [ -R3,    -R13,    R13,   -R13,   -R13,    R13,    R3,     R13]; Z:= [  0.,    -R23,   -R232,  -R23,    R232,   R23,    0.,     R23];Edge:= [0,1, 1,2, 2,3, 3,0, 4,5, 5,6, 6,7, 7,4, 0,4, 1,5, 2,6, 3,7];SetVid($101);                           \set 640x480x8 graphicsrepeat  Farthest:= 0.0;                 \find the farthest vertex        for I:= 0 to 8-1 do            if Z(I) > Farthest then [Farthest:= Z(I);  ZI:= I];        Clear;                          \erase screen        for I:= 0 to 2*12-1 do          \for all the vertices...            [J:= Edge(I);  I:= I+1;     \get vertex numbers for edge            Move(Fix(X(J)*Size)+640/2, Fix(Y(J)*Size)+480/2);            K:= Edge(I);            Line(Fix(X(K)*Size)+640/2, Fix(Y(K)*Size)+480/2,                if J=ZI ! K=ZI then $F001 \dashed blue\ else $0C \red\);            ];        DelayUS(55000);        for I:= 0 to 8-1 do            [X(I):= X(I) + Z(I)*Speed;  \rotate vertices about Y axis             Z(I):= Z(I) - X(I)*Speed;  \ (which rotates in X-Z plane)            ];until KeyHit;                           \run until a key is struckSetVid(3);                              \restore normal text mode]
Output:

http://www.xpl0.org/rotcube2.gif

Yabasic

// Rosetta Code problem: http://rosettacode.org/wiki/Draw_a_rotating_cube// adapted to Yabasic by Galileo, 05/2022// GFA Punch (code from tigen.ti-fr.com/)// Carré 3D en rotationopen window 50, 70backcolor 0,0,0clear windowcolor 255,255,255do  clear window  x = COS(T) * 20  y = SIN(T) * 18  r = SIN(T + T)     line (x + 40), (y + 40 - r), (-y + 40), (x + 40 - r)  line (-y + 40), (x + 40 - r), (-x + 40), (-y + 40 - r)  line (-x + 40), (-y + 40 - r), (y + 40), (-x + 40 - r)  line (y + 40), (-x + 40 - r), (x + 40), (y + 40 - r)    line (x + 40), (y + 20 + r), (-y + 40), (x + 20 + r)  line (-y + 40), (x + 20 + r), (-x + 40), (-y + 20 + r)  line (-x + 40), (-y + 20 + r), (y + 40), (-x + 20 + r)  line (y + 40), (-x + 20 + r), (x + 40), (y + 20 + r)  line (x + 40), (y + 40 - r), (x + 40), (y + 20 + r)  line (-y + 40), (x + 40 - r), (-y + 40), (x + 20 + r)  line (-x + 40), (-y + 40 - r), (-x + 40), (-y + 20 + r)  line (y + 40), (-x + 40 - r), (y + 40), (-x + 20 + r)  pause 0.02  T = T + 0.15loop

Zig

Library:Raylib
Works with:Zig version 0.11.0
Works with:Raylib version 4.6
conststd=@import("std");constc=@cImport({@cInclude("raylib.h");@cInclude("rlgl.h");});constdark_mode=true;constshow_grid=false;pubfnmain()!void{constscreen_width=640;constscreen_height=360;constcube_side=1;constsize=c.Vector3{.x=cube_side,.y=cube_side,.z=cube_side};constposition=c.Vector3{.x=0,.y=0,.z=0};constx_rot=45;consty_center:f32=std.math.sqrt(3.0)*cube_side/2.0;constz_rot=std.math.radiansToDegrees(f32,std.math.atan(@as(f32,std.math.sqrt1_2)));c.SetConfigFlags(c.FLAG_WINDOW_RESIZABLE|c.FLAG_VSYNC_HINT);c.InitWindow(screen_width,screen_height,"Draw a Rotating Cube");deferc.CloseWindow();varcamera=c.Camera{.position=.{.x=3,.y=3,.z=3},.target=.{.x=0,.y=y_center,.z=0},// Center of cube.up=.{.x=0,.y=1,.z=0},.fovy=45,// Camera field-of-view Y.projection=c.CAMERA_PERSPECTIVE,};c.SetTargetFPS(60);while(!c.WindowShouldClose())// Detect window close button or ESC key{c.UpdateCamera(&camera,c.CAMERA_ORBITAL);c.BeginDrawing();deferc.EndDrawing();c.ClearBackground(if(dark_mode)c.BLACKelsec.RAYWHITE);{c.BeginMode3D(camera);deferc.EndMode3D();{c.rlPushMatrix();deferc.rlPopMatrix();c.rlTranslatef(0,y_center,0);c.rlRotatef(z_rot,0,0,1);c.rlRotatef(x_rot,1,0,0);c.DrawCubeWiresV(position,size,if(dark_mode)c.LIMEelsec.BLACK);}if(show_grid)c.DrawGrid(12,0.75);}}}
Retrieved from "https://rosettacode.org/wiki/Draw_a_rotating_cube?oldid=386717"
Categories:
Hidden category:
Cookies help us deliver our services. By using our services, you agree to our use of cookies.

[8]ページ先頭

©2009-2026 Movatter.jp