I have been trying to figure out how to take the good 'ol trigonometric functions and make a program on the ti 84 that allows me to use the arrow keys to rotate the cube by the x axis and the y axis, z axis maybe later. I have the general idea down but I cannot really figure out what I need to code. I know that I found a program once that did this seamlessly on ticalc.org (cant remember what it was) and I also know that there is a very good looking 3D figure rotation program on ticalc.org for the Nspire. Does anybody know exactly how to do this?

Sorry, don't know much about 3D rendering on the calculator, but I found this program on TiCalc.org. They also have an entire directory dedicated to 3D rendering.

Projects: BexIDE (hold), Hadean.NET, Legend of Zelda: Link to the Future

Have you looked into Linear Algebra? You could internally keep track of the corner cooridinates, and then "project" from some point away from the cube (by drawing lines from that point through each corner, and then solving for where they intersect the plane of the calculator screen).

That method seems fairly "bulky" if you know what I mean, though. I'm sure there's something simpler…

So… after much math I have succesfully built a 3d rendering engine using the method in my above post. As I had guessed, it's agonizingly slow (seeing as it has to recalculate and redraw every line after every transformation) (EDIT: has been slightly improved), but it's capable of supporting any set of vertex coordinates (stored as lists L_{x} L_{y} and L_{z}) you give it (though you have to physically go into the program to change the coordinates and what vertex connects to which others). Right now it has a tetrahedron cube built in for testing.

Features include translations through 3d space (you can move up/down, left/right, and back/forth) and rotations about the x, y, or z axes (I plan to add the ability to rotate about any line of the form "x=" "y=" or "z=" later). Built-in scale factors let you change the magnitude of each transformation through variables S (set to 4 pixels per keypress as of now) and θ (currently set to 15º per keypress).

A major issue is the resolution of the screen; the 3d illusion breaks down rather easily.

I'll upload the program later (no later than tomorrow) after some tweaks (or at least post the source; I don't have TI connect yet… ;^ ^) I could use help with some optimization; it's still in the brute force proof-of-concept phase and that's not really an area I excel at…

So… I don't have the right cable thing for TI connect, so here's the code. Yes, I typed that all, lol.

As I said, optimizations are strongly encouraged. I realize there's tons of ending parentheses to be chopped off, but I'm worried more about speed optimizations than size. Specifically, rotations are über-slow.

Basically, the center of the calc screen is (0,0,0). There's an imaginary "vantage point" at (0,0,30) that represents the user's perspective. A line is drawn from the perspective point through each vertex (x,y,z) of the polyhedron in question and solved for the point (x',y',0) where it intersects the graphing calculator's screen. Then, these points are connected in the correct order and voila! you have a wireframe shadow of the polyhedron.

I forgot to mention—if we can get this running at an acceptable speed, I'm excited to try extending the idea to four dimensions. Something tells me that might be a bit too big for the calculator though; it already takes on the order of seconds to find the new coordinates in three dimensions.

```
... //Set up graph screen, (window=Zsquare/Zinteger), mode=degree, ready lists X,Y,Z
:{10,10,-10,-10,10,10,-10,-10}→∟X
:{10,-10,-10,10,10,-10,-10,10}→∟Y
:{10,10,10,10,-10,-10,-10,-10}→∟Z //Corner verticies of cube
:4→S:15→θ //magnitude of transformations
:dim(∟X)→D //# of verticies
:Lbl A
:ClrDraw //This next section projects the 3d cube onto the 2d screen
:For(T,1,3)
:30/(30-∟Z(T))→K //The recurring 30/(30-∟Z) is basically the factor that the X and Y coordinates get extended by to intersect the calc screen
:30/(30-∟Z(T+1)) //set this for Ans
:Line(K∟X(T),K∟Y(T),Ans∟X(T+1),Ans∟Y(T+1)) //Connect vertecies 1-2,2-3,3-4
:30/(30-∟Z(T+4))→K
:30/(30-∟Z(T+5))
:Line(K∟X(T+4),K∟Y(T+4),Ans∟X(T+5),Ans∟Y(T+5)) //Connect vertecies 5-6,6-7,7-8
:END
:30/(30-∟Z(8))→K
:30/(30-∟Z(5))
:Line(K∟X(8),K∟Y(8),Ans∟X(5),Ans∟Y(5)) //Connect verticies 8-5
:30/(30-∟Z(4))→K
:30/(30-∟Z(1))
:Line(K∟X(4),K∟Y(4),Ans∟X(1),Ans∟Y(1)) //Connect verticies 4-1
:For(T,1,4)
:30/(30-∟Z(T))→K
:30/(30-∟Z(T+4))
:Line(K∟X(T),K∟Y(T),Ans∟X(T+4),Ans∟Y(T+4)) //Connect verticies 1-5,2-6,3-7,4-8
:END //Done drawing the box. Everything following is independent of the shape you're manipulating (i.e. it's the "engine" part)
:Repeat max(Ans={24,26,25,34,14,15,73,93,82,84,63,64})
:getKey→K //I'll explain each key as I get to it; they're surprisingly intuitive for so many degrees of freedom.
:END
:∟X+S(Ans=26)-S(Ans=24)→∟X //Left/right=translate along x axis
:∟Y+S(K=25)-S(K=34)→∟Y //Up/down=translate along y axis
:∟Z+S(K=15)-S(K=14)→∟Z //"Trace"/"Graph" translate along z axis
:cos(θ)→U
:1-2((K=64)+(K=73)+(K=82)) //Is rotation negative?
:Ans sin(θ)→V
:If K=63 or K=64:Then //Open/close parentheses rotate on z axis
:∟X→∟W //store this so the new value of ∟X doesn't mess up the second equation. It took me an eternity of debugging to find this.
:U Ans-V∟Y→∟X //rotation equation for the new set of x coordinates
:V∟W+U∟Y→∟Y //rotation equation for new set of y coordinates
:END
:If K=84 or K=82:Then //"4"/"6" rotate on y axis
:∟Z→∟W
:U Ans-V∟X→∟Z
:V∟W+U∟X→∟X
:END
:If K=73 or K=93:Then //"8"/"2" rotate on x axis
:∟Y→∟W
:UAns-V∟Z→∟Y
:V∟W+U∟Z→∟Z
:END
:Goto A
```

Hmm… I'll have to dedicate some time to putting this on my calculator. By the way, just as a tip for "optimization", you don't need the extra parenthesis, braces, brackets, or quotes on the ends of expressions if they are the last thing on the line. I.e., "Repeat max(Ans={…})" doesn't need the two items at the end.

Projects: BexIDE (hold), Hadean.NET, Legend of Zelda: Link to the Future

Derp, I just realized that I used a For( loop solely to perform an operation on every element of a list. I fixed that and rotations are nearly three times faster. Since I don't need the For( loop, I wonder if using piecewise functions for rotations would be better than checking explicitly for which key was pressed…

Also @BlakPilar, I realize that, but I have a compulsion to keep things tidy and explicit… I'd chop them off eventually in the final product.

Hmm… Yeah, the piecewise functions could work…

Also, as a side question? Do you program in / have an understanding of… I'm going to say C#?

Projects: BexIDE (hold), Hadean.NET, Legend of Zelda: Link to the Future

Nope, TI-Basic is the only language I've programed in.

EDIT: I'm having trouble seeing how to piecewise-ify it compactly… Hmmm, Self-Modifying Code. I wonder if I could put that to use somehow. I'm not really experienced with it, though.

Alright. I was just wondering because continuous (full/partial line) comments in C# begin with "//" and you indent.

Anyway, back on track. Using SMC with u, v, and w is normally for expressions like "randInt(1,10)" so that recalling any of the three will bring up a result of that expression. You might be able to put expressions in the key checks, and after all of them store them to u, v, or w and recalling that expression later? Not sure if that makes much sense…

Projects: BexIDE (hold), Hadean.NET, Legend of Zelda: Link to the Future

Yeah, so pretty much the idea with SMC in BASIC is that you can modify strings and you can store strings to y-vars, but y-vars don't act like strings. Instead, they are pretty much one line functions. So, if you use something like randInt(1,10 quite a bit or if you have some equation that you use a lot in a program, you can store it to a y-var like so:

`"randInt(1,10→u`

Then, every time you use u, the code "randInt(1,10" is executed. So extending that:

```
"randInt(1,10→u
Line(u,u,u,u
```

That will make a line whose coordinates are all random integers from 1 to 10. So anyway, here are the real specifics of SMC…

Pretty much, if you needed to, you could do Str1→u where Str1 contains some code. The only problem is that not all commands can be used (only the ones you can graph). So in some (usually rare) cases, you might do something like this:

```
If not(A
"getKey
If A=1
"0
If A=2
"randInt(0,4
Ans→u
Repeat not(A
<<code>>
u→A
<<code>>
End
<<More code>>
u→A
<<Even More code>>
```

In all, I've never really found a legitimate use for this form of SMC. However, the y-vars are very useful for storing equations to and using them. For an example of that:

```
"12-9873x+12403(A²+A)-10426(A³+3A²+2A)/3+1489(A^4+6A³+11A²+6x)/6+i(3(A²+A)/2-A-(A³+3A²+2A)/2+(A^4+6A³+11A²+6x)/24→Y1
For(A,0,4
Disp Y1
End
```

By the way, if I typed that equation in correctly, it does actually do something… I was challenged to make an equation to hit the data points (0,12),(1,49),(2,1056),(3,49),(4,i) where i is the imaginary number… Yeah, that was fun x.x

47%? Take a look and try to imagine how cool 100% will be. This has won zContest 2011 and made news on TICalc. This compromise between Assembly and BASIC parses like BASIC and is fast like assembly. Grammer 2

@BlakPilar

Actually, I just realized I lied… XP I did some programming with scripts in the construction set for the game "Oblivion"; that's where I probably picked up indenting lines. Plus it looks nicer. I use // for comments 'cause that seemed to be the norm here.

@Xeda

o_O That's ridiculous; I wouldn't even know how start to tackle that. I mean, if you were given roots it'd be easy, but O_O

BACK TO THE TOPIC AT HAND…

Yeah, at first glance I thought I might be able to use SMC and piecewise functions to combine all three rotations into one equation, but alas, 'tis impossible.

I think the current form is the best bet, with one exception: I'd store cos(θ) and sin(θ) (or -sin(θ) for negative rotaions) to real vars prior to using them; it's a lot of work for the calculator to do trig functions on so many elements. Also, it removes the need to modify θ for negative rotations (and thus the need to un-negative it).

I like equations… :P

Anywho, yes, it is a good idea for speed if you need to calculate sin(θ) a bunch of times simply to store sin(θ) to a real var. Like you said, it is faster for the calc than computing it a bunch of times. I have had my share of fun with making functions like that and it is very likely faster for the calc to find a var than it is to compute sin(. In the stuff that I worked on, it was several hundred times faster, actually (which wasn't actually too noticeable), but it helped that the vars were fixed in RAM :)

47%? Take a look and try to imagine how cool 100% will be. This has won zContest 2011 and made news on TICalc. This compromise between Assembly and BASIC parses like BASIC and is fast like assembly. Grammer 2

Sadly, the only variables available for that are u, v, and w, but you could also store extra ones into r1, etc. or any other equation variables that people don't use too often, and recall them from there and store them into u, v, or w.

Projects: BexIDE (hold), Hadean.NET, Legend of Zelda: Link to the Future

Oh, I only meant doing something like this to save speed:

```
sin(θ→A
cos(θ→B
Line(0,0,A,B
Line(A,B,A,cos(θ+π/4
```

47%? Take a look and try to imagine how cool 100% will be. This has won zContest 2011 and made news on TICalc. This compromise between Assembly and BASIC parses like BASIC and is fast like assembly. Grammer 2

This is one instance in which using piecewise expressions would actually just slow things down, but for the sake of experience, here is the rotation code fully piecewise'd.

```
(K=63)(K=64)⌊X+(K=84)(K=82)⌊Z+(K=73)(K=93)⌊Y→⌊W
(K=63)(K=64)(Ans cos(θ)-⌊Ysin(θ))+(K=84)(K=82)(Ans sin(θ)+⌊Xcos(θ))+(K=73)(K=93)⌊X→⌊X
(K=63)(K=64)(⌊Wsin(θ)+⌊Ycos(θ))+(K=63)(K=64)⌊Y+(K=73)(K=93)(⌊W cos(θ)-∟Zsin(θ))→⌊Y
(K=63)(K=64)(⌊Z)+(K=84)(K=82)(⌊W cos(θ)-⌊Xsin(θ))+(K=73)(K=93)(⌊Wsin(θ)+⌊Zcos(θ))→⌊Z
```

"Reality is that which, when you stop believing in it, doesn't go away."

-Philip K. Dick

I was afraid of that. That's pretty much what I got—a big, nasty mess.