So I found this cube tutorial at Skytopia with some code that's easy to read and quickly modified it into a Livecode script. Then I spent hours noodling with variables and controls, then I stripped all the controls off to give you a simple stack to play with.
VERY IMPORTANT: Click RESET before pressing keys the first time the stack opens. Local variables need set or your cube will vanish.
The Key Control button is a toggle, click the label name area to make it snap the list out of view.
The Mode checkbox switches between isometric 3D simulation and actual 3D simulation
There's two buttons used as labels at the top center of screen "TheKey" and "TheValue".
TheKey shows the key name associated with the rawKeyDown values that the script is using. These are store in a custom property of the stack.
TheValue shows what value you are modifying with the current key you are holding down.
A third button "RawKey" in the top right corner is showing the actual rawkeydown numbers, in case you need to add more keys to the KeyNameArray custom property and HandleKeys handler for whatever reason.
The stack has some other custom properties but the one ones of concern at the moment are:
- xArray
yArray
zArray
You won't need to modify them, but if you are going to try to maybe make another geometric shape, you'll need a similar aray.
The array is created and values are set with the InitCubeCoordinates handler, if you copy the code of this stack to a new stack you'lll need to run this handler once to set up your custom property.
Code: Select all
on InitCubeCoordinates
--// "I" = the distance of the vertice from center, ie, pivot
put 60 into I
--//X
SetX 1,I
SetX 2,I
SetX 3,I
SetX 4,I
SetX 5,-I
SetX 6,-I
SetX 7,-I
SetX 8,-I
--//Y
SetY 1,I
SetY 2,I
SetY 5,I
SetY 6,I
SetY 3,-I
SetY 4,-I
SetY 7,-I
SetY 8,-I
--//Z
SetZ 2,-I
SetZ 6,-I
SetZ 6,-I
SetZ 8,-I
SetZ 1,-I
SetZ 3,-I
SetZ 5,-I
SetZ 7,-I
end InitCubeCoordinates
Code: Select all
---// get or set values in custom property arrays
on setX n,tVal
put the xArray of of stack (the mainStack of this stack) into tArray
put tVal into tArray[n]
set the xArray of of stack (the mainStack of this stack) to tArray
end setX
Okay custom property is set up now for the cube manipulation:
Local Variables in the stack to match th tutorial:
Code: Select all
--// Initial start up variables:
local theSIZE=40
local theMODE=0
local CAMX=0 , CAMY=0 , CAMZ=300 --// Position of the camera.
local MOVEX=0 , MOVEY=0 , TheSCALE=1 --// Image fixed to 'paper' so you can move around and 'scale' in/out.
local ANGLEX=0 , ANGLEY=0 , ANGLEZ=0 --// Angle of rotation about the following pivots:
local PIVX=0 , PIVY=0 ,PIVZ=0 --// Pivots x, y and z
Code: Select all
--// additional variables beyond tutorial
local CenterX,CenterY --// the center, or pivot point of the object(s)
local P1,P2,P3,P4,P5,P6,P7,P8 --// the vertices that make the cube
local CubePoints --// store the whole cube in here
local LoopIndex=1 --// for tracking loop N position to identify circle vertice markers
local fXrot,fYrot,fZrot --// values to modify angles each loop. "f" for float
The P1,P2,P3 etc variables are used to store the virtual vertices of the cube as it they are updated each run of CUBE_LOOP, at the end of the loop they are associated with each other to create the points of the lines that make the cube. The default code as translated spits out a mangled ugly mess of lines, I left the single line of commented code in there for you to see it for yourself.
CubePoints combines all the P1,P2,P3,etc vertice to line associations into a single point list to define a "line" graphic object
LoopIndex is used to give a name to the circle objects that identify the vertice positions, ie, circle1, circle2, etc
fXrot,fYrot,fZrot modifiy the ANGLEX,ANGLEY,ANGLEZ variables at the top of each run of the loop. The tutorial had some high integer values 5,8,3 and the cube was spinning like crazy every iteration of the handler, these values are floats so we get fine control over our cube rotation. Shift key with X,Y, and/or Z will set these values to zero so you can do things like zooming in and out without the cube spinning constantly.
Okay that covers the local variables. On to the CUBE_LOOP
The tutorial linked above can explain how this works better than I can.
Just note that this code differs from the tutorial:
- to gain control over the initial ANGLE modifiers via fXrot,fYrot,fZrot variables
- to track the circle graphics by giving them each names
- control rendering the pivot point "pixel"
- to render a clean cube line by line using the P1,P2,P3, etc variables
- additional conditionals to trap some bugs generated by using things like sliders to modify variable values
- finish off with an actual Livecode graphic control object that can be copy/pasted, colored, click on or whatever.
Code: Select all
On CUBE_LOOP
--// Rotation values make the spin happen
--// if these are 0 or empty the prorgram does nothing
--// values 5,8,3 given in tutorial are crazy high and hideous
put ANGLEX+fXrot into ANGLEX --//5
put ANGLEY+fYrot into ANGLEY --//8
put ANGLEZ+fZrot into ANGLEZ --//3
put fXrot,fYrot,fZrot
focus nothing
--// repeat through each vertice of the object
Repeat with N=1 To 8
put N into LoopIndex
--// Rotation code
put (getX(N)-PIVX) into XD
put (getY(N)-PIVY) into YD
put (getZ(N)-PIVZ) into ZD
--// read the tutorial if you want to understand what happens here
put XD*Cos(ANGLEZ) - YD*Sin(ANGLEZ) - XD into ZX
put XD*Sin(ANGLEZ) + YD*Cos(ANGLEZ) - YD into ZY
put (XD+ZX)*Cos(ANGLEY) - ZD*Sin(ANGLEY) - (XD+ZX) into YX
put (XD+ZX)*Sin(ANGLEY) + ZD*Cos(ANGLEY) - ZD into YZ
put (YD+ZY)*Cos(ANGLEX) - (ZD+YZ)*Sin(ANGLEX) - (YD+ZY) into XY
put (YD+ZY)*Sin(ANGLEX) + (ZD+YZ)*Cos(ANGLEX) - (ZD+YZ) into XZ
--//the code above results in these offsets
put (YX+ZX) into XROTOFFSET
put (ZY+XY) into YROTOFFSET
put (XZ+YZ) into ZROTOFFSET
--// modifying theScale manually can result in errors, trapped here
if theScale = 0 then put 0.01 into theScale --// no divide by zero
--// Yes, it's the *SPLAT* code (aka 2D to 3D conversion):
If theMODE=0 then
Put ( getX(N) + XROTOFFSET + CAMX )/theSCALE +MOVEX into X
Put ( getY(N) + YROTOFFSET + CAMY )/theSCALE +MOVEY into Y
Else
Put ( getZ(N) + ZROTOFFSET + CAMZ ) into Z
Put ( getX(N) + XROTOFFSET + CAMX )/Z /theSCALE +MOVEX into X
Put ( getY(N) + YROTOFFSET + CAMY )/Z /theSCALE +MOVEY into Y
End If
--// modifying CAMZ manually can result in errors, trapped here
--// keep the zoom (camz) from overloading the x,y values
if x > 1600 then put 1600 into X
if y > 1600 then put 1600 into Y
if x < -1300 then put -1300 into x
if y < -1300 then put -1300 into y
--// the x,y values derived above applied to the center of the screen
put X+CenterX & comma & Y+CenterY into curPoint
--// store individual vertices in their own variables
--// this is so we can draw a clean cube
--// instead of the zig-zag incomplete mess that the tutorial code makes
if n= 1 then put curPoint into P1
if n= 2 then put curPoint into P2
if n= 3 then put curPoint into P3
if n= 4 then put curPoint into P4
if n= 5 then put curPoint into P5
if n= 6 then put curPoint into P6
if n= 7 then put curPoint into P7
if n= 8 then put curPoint into P8
--//## original messy zig zag vertices. To compare uncomment this
--//## and set a "line" graphic's points to thesePoints after the end repeat
-- put cr & X+400 & comma & Y+300 after thesePoints
--// give each circle a name so we don't have to recreate them constantly
put "circle"& LoopIndex into circName
--// Drawing code
If theMODE=0 then
--// theMode 0 is an isometric representation of 3D
put theSIZE/theSCALE into radius
--// manually adjusting CAMZ,theSize, and/or theScale can result in errors,trapped here
if radius <1 or radius is not a number then put 1 into radius
if radius >30 then put 30 into radius
if exists(graphic circName) then
--// a label for tracking vertices on screen
set the label of graphic circName to LoopIndex
--// the location and size of the circle
set the loc of graphic circName to X+CenterX, Y+CenterY
--// got a safe size? Set the size of the circle
set the height of graphic circName to radius
set the width of graphic circName to radius
else
--// if the circles don't exist then we draw them, default size/scale is assumed safe
Draw_Circle X+CenterX, Y+CenterY, theSIZE/theSCALE
end if
--// in isometric mode we hide the pixel/pivot
if exists(graphic "pixel") then
hide graphic "Pixel"
end if
Else
--// theMODE 1 is a true 3D in 2D simulation
put ( getZ(N) + ZROTOFFSET + CAMZ ) into Z
--// Z greater than 300 may be off screen
if Z > 300 then put 300 into z
--// manualy modifying CAMZ,theSize,and/or theScale can result errors, trapped here
put ((theSIZE/Z)/theSCALE) into radius
if radius <1 or radius is not a number then put 1 into radius
if radius >30 then put 30 into radius
if exists(graphic circName) then
set the loc of graphic circName to X+CenterX, Y+CenterY
set the height of graphic circName to radius
set the width of graphic circName to radius
else
Draw_Circle X+CenterX,Y+CenterY, radius
end if
--// Display of the pivot point code (optional)
put ( (PIVX+CAMX) / (PIVZ+CAMZ) ) /theSCALE +MOVEX +CenterX into PX
put ( (PIVY+CAMY) / (PIVZ+CAMZ) ) /theSCALE +MOVEY +CenterY into PY
Draw_Pixel PX, PY
End If
end repeat
--// Build a clean cube line by line
--// The double cr after the end of each statement defines a line unconnected to the next
--// This was done to clarify which two vertices create a line
--// So as to define a nice clean cube made by drawing the connecting
--// lines of each face in turn without zig-zagging across the faces
put cr & P1 & cr & P3 & cr & cr after tPoints
put cr & P1 & cr & P2 & cr & cr after tPoints
put cr & P1 & cr & P5 & cr & cr after tPoints
put cr & P2 & cr & P4 & cr & cr after tPoints
put cr & P2 & cr & P6 & cr & cr after tPoints
put cr & P3 & cr & P4 & cr & cr after tPoints
put cr & P4 & cr & P8 & cr & cr after tPoints
put cr & P5 & cr & P6 & cr & cr after tPoints
put cr & P5 & cr & P7 & cr & cr after tPoints
put cr & P6 & cr & P8 & cr & cr after tPoints
put cr & P7 & cr & P3 & cr & cr after tPoints
put cr & P7 & cr & P8 & cr & cr after tPoints
--unify all the lines as a single graphic object stored in one variable and/or object
put tPoints into CubePoints
set the points of graphic "cubeLine" to CubePoints
end CUBE_LOOP
There's a big long HandleKeys handler in the stack script, but that's pretty simple repetitive stuff.
I changed the tutorials ANGLE modifiers in there to floats so the cube rotates smoothly instead of all wacky.case "j"
put MOVEX-2 into MOVEX
set the label of button "theValue" to "MOVEX:"&& MOVEX
break
Other than that it all works as tutorialized.
I have another stack full of control knobs to twist and slide coming up. Then we'll see if we can do another polygon object. How hard could it be?
Oh meanwhile I found this 3D Library, holy smokes!