Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

New Code: a floating cube (2011-12-12: Major update)

edited December 2011 in Code Sharing Posts: 2,161

Don't be put off by the title!

I've uploaded a new project to the cube project. It displays a cube defined by vertices and edges. Main features:

  1. The cube is stereographically projected onto the screen from an "eye" above the screen.
  2. The elements are ordered according to how far from the eye they are and placed on the screen in the right order to create the 3D effect (a little shading, using a technique from TikZ/PGF, ensures that over/under looks right).
  3. As you tilt the iPad, the cube "stays level" in that it adjusts so that the bottom face always appears to be downwards. So if you tilt the iPad up, you look at the top of the cube.
  4. You can rotate the cube by touching and dragging on the screen. You should imagine a sphere containing the cube and as you drag your finger across the screen, you rotate this sphere. (Then if you further tilt the iPad, it keeps the current orientation relative to the ground.)

Main code features:

  1. An extended Vec3 class for holding 3-dimensional vectors. I figured out how to make the + and so forth operators work, so things like u + v just work. I had to be a bit creative: u * v returns the cross product, u .. v the dot product, and #v the length. It also has a crude applyMatrix function where the matrix is specified as a triple of Vec3 objects. Many of the operations work with vec3 objects as well. It has functions for stereographic projection of vectors onto the screen from an "eye".
  2. A class Quaternion for dealing with quaternions. "What's a quaternion?", I hear you cry. If you don't know then think of them as a neat way of encoding rotations. You can apply a quaternion (rotation) to a Vec3 object by the notation v^q. Composing rotations corresponds to multiplying quaternions: q * p.

Things to do:

  1. The vertical stuff is done by ordering the elements according to their distance from the "eye". I'd planned on using zLevel for this but couldn't get it to work as I expected so went for a manual sort. Now that I know a bit more about zLevel I could put this back (maybe).
  2. The vertical stuff can't cope with this problem: triple lines (image included, with the permission of the author, from this blog post which is about something a little similar). This would need more advanced drawing tools, or extremely finickity computation.
  3. The radius of the "balls" for the vertices varies with the depth, but the calculation is a little crude. This could be improved.
  4. Adding support for pinch-to-zoom would be super cool!
  5. The stereographic projection doesn't do anything sensible with points behind the viewer. This should be possible, though there are a few edge cases to consider.
  6. Defining the data is fairly abstract, but could be made more so with a 3DObject class.
  7. The vertices themselves don't look very 3D.

Other suggestions welcome!


  • BortelsBortels Mod
    Posts: 1,557

    This is insanely awesome. Well implemented quaternions alone will be handy in the long run, as will the operator overloading. (I implemented a c++ class to do them in the distant past when I had been doing everything with Euler angles and hit the dreaded gimbal lock - I won't pretend I ever fully understood it all, a lot of trial and error and code that worked, eventually, but I couldn't explain why). Plus - wonderful explanations. Thank you for this whole thing.

  • Posts: 2,161

    Incidentally (since it took me quite some time to find it) the overloading is described in the reference manual at the metatable entry.

  • Posts: 2,161

    (In my background research for this, then I read about the gimbal lock but it just made my brain freeze. If anyone can explain it, I'll be very grateful! I used quaternions purely and simply because I know about them from my work.)

  • BortelsBortels Mod
    Posts: 1,557

    Left-right dragging (iPad in landscape mode) is wonky for me. (I also deeply appreciate a good trackball controller!)

    It's sad that this basically duplicates most of the functionality of the c++ code I mentioned - sticks and balls in 3d rotatable - in maybe one twentieth of the code, and it took me 6 months. It was a good learning experience, but woof!

    I plan on swiping this, with great gusto, for my strategic space game (oft started, never completed - I think I'm on my 10th version now). Yay!

  • Posts: 2,161

    Could you be more precise? "Wonky" is a little ... open to interpretation!

    I'm not convinced that I have the dragging in its most intuitive fashion, it often takes me a couple of goes to get it right. In particular, I'm not totally sure that I have the interaction between the gravitational rotation and the touch rotation quite right. There was a lot of "try a few things until something looks right" instead of sitting down with a pen and paper (sorry! I mean stylus and ipad) and working out what it ought to be.

  • BortelsBortels Mod
    Posts: 1,557

    Drag up - cube spins away (ie. closest vertex goes up) - good. Down likewise.

    Drag right - close vertex moves up and right. Drag left, close vertex goes down and left.

    Something is skewed somewhere. This is all with the iPad held steady. Hmm. Ah - orientation matters. I am holding the iPad "screen up" leaning over it. If I hold the screen closer to vertical, the effect is less pronounced. (if I hold it very vertical, the cube disappears)

  • Posts: 2,161

    Hmm, it looks as though I'm not correcting for the tilt when working out the effect of the touches. Ah, well. Back to the drawing-board^H^H^H^H^HiPad.

    The cube shouldn't disappear at any orientation. If you hold it completely flat then it might spin round a bit as it tries to work out what orientation to use (the gravity vector is no longer sufficient when it's completely flat).

    Just spotted another bug which happens when one rotates the iPad all the way around with the rotation lock on (I wonder if we can detect the rotation lock ...). Halfway around then some assumption goes false and the gravity vector is in the wrong direction.

  • BortelsBortels Mod
    Posts: 1,557

    Hold the iPad landscape mode in front of you, like a window - at vertical (or close) - no cube.

    This is with rotation lock on, as is only right and proper. Non-lockers are a menace to society!

    Man I need to go to bed.

  • Posts: 2,161

    I get a strange flicker every now and then as I try to orient it exactly at vertical, but I can't find a position where it actually vanishes for long enough for me to see.

    I'll have a think and see if I can work out some diagnostics for you to run that might tell me what's going on, if you'd be prepared to do that for me. (But I need to finish writing a lecture so I won't do it now ... you can go to bed.)

  • beebee
    Posts: 378

    I wonder what your daily job, guys. You both seem to have plenty of free time to play around with Codea. I envy you! I hardly able to pull my iPad from my kids! :D

  • BortelsBortels Mod
    Posts: 1,557

    Heh - was 2am for me. Just getting up now... 5 hours of sleep is plen.t..y.... Zzzzzzzzz

    Andrew - I have iPad 1 - maybe you have iPad 2 and it's a speed thing? Happy to try whatever.

  • BortelsBortels Mod
    Posts: 1,557

    BTW - confirmed, when I set the gravity vector to Vec3(1,0,0,0) - the trackball works perfectly. For my purposes, this is more than sufficient (You see vertexes and lines, or perhaps atoms and molecular bonds - I see planets, and when I'm done a minimal spanning tree connecting them all for my awesome strategic wargame :-) )

  • Posts: 2,161

    Okey-dokey. Glad that's figured out. For the record, yes I have an iPad 2.

    In an ideal world, I'd have a touch-button for turning gravity on and off. Maybe I'll program that in ...

  • "hardly able to pull my iPad from my kids!" You have to call homework:complete()

    This usually returns false then the iPad is yours.

  • beebee
    Posts: 378

    @Ipda41001: Hahahaha... It's usually called by their mother and when it returns false the iPad goes to her, not me. :D Actually, I bought the iPad for her and the kids after all. I didn't think I would be able to do something productive with it and a macbook pro is all I need. It's true... until I found Coders and then Codify. :) I think I have to buy another one for myself. But I'll wait for iPad 3 since iPad 2 is starting to get old. :)

  • Posts: 2,161

    Yes, I was under the misapprehension that it was my iPad as well. Ah, well.

  • Posts: 19

    @Andrew: it's the first outside project I'm trying, and I have to say it's amazing, both for the learning value as for the potential applications. Thanks for sharing it!

    (Also, thanks for the suggestion on your web page to use GoodReader to copy and paste the source code, it was most useful.)

  • Posts: 2,161

    Major Update

    I've fixed some bugs, and introduced a fair few new features; mainly to do with interaction.

    1. Pinch-zoom is now implemented. There are two directions: a horizontal pinch changes the scaling after the stereographic projection is done, a vertical pinch changes it before.

    2. Tapping affects gravity. A single tap turns it on or off. A double tap resets everything to its starting configuration (including the zooms).

    3. Data is now abstracted into its own class (Data3d.lua). There's a new shape, which is cyclohexane in "chair" format (pretty much cut-and-pasted from pubchem).

    4. Touches are also abstracted just a little.

    Have a play!

  • Posts: 2,161

    May as well record my ideas for extending this.

    1. Make vertices and edges objects in their own right. Then add styles (size, colour).
    2. Figure out the simplest way to specify a molecule from pubchem for input.
    3. Specify edges by giving each vertex a valency and then forming edges to the nearest other vertices up to the valency.
    4. Double swipe for translate?
    5. Add a menu to swap between shapes
    6. Make it possible to edit the shape by dragging vertices. In a particular view, dragging a vertex moves it parallel to the view. Need to have a toggle button somewhere to say "now I'm in editing mode", otherwise the gestures get too complicated. One could add/remove edges as well.
    7. Abstract the "viewport" stuff a little (mainly with regard to the interaction with touches).
  • BortelsBortels Mod
    Posts: 1,557

    1 and 4 are my main wishes - I'm looking at this less as a "molecule viewer" and more as a toolkit. Anything abstracting away details is therefore welcome.

    Also - momentum on the trackball controller would be nice, so if you give it a good spin, it coasts to a stop; it feels odd that it stops instantly when you let up, the iPad has trained me to expect things to coast to a stop unless I stop them.

    BY THE WAY - if I haven't made it clear before - this is pretty damn cool. Thank you.

  • Posts: 2,161

    Also - momentum on the trackball controller would be nice

    I pondered that. You're right that it's "expected" on the iPad, it would also be quite fun. I have code for this in another project (the touch code on the wiki) so it wouldn't be hard to add. I think in terms of implementing it, it would fit in most naturally once (7) has been done.

    Maybe I'm taking abstraction a bit too far, but I'd really like my main program to be:

    function setup()
       touches = Touches()
       viewport = Viewport() -- maybe pass some defaults here
       shape = Shape("cube")
    function draw()
    function touched(touch)
  • BortelsBortels Mod
    Posts: 1,557

    I agree. ideally, main() (er, draw() that is) should fit on one page.

    I'm trying very hard with the Font/Keyboard stuff to be:

    f = HersheyRomanSimplex()
    k = Keyboard()

    and then just draw em.

    Keyboard should probably take an argument for what font to use, thinking about it.

  • It's funny how we think alike but on different levels (or actually dimensions :-D ) I had half started a 2D valence bond program.

  • Andrew, would it be possible to add a function that would allow to draw 3D functions using a mesh?

  • Posts: 2,161

    Okay, 1 4 6 7 are now done. The code is as a .codea file on my website at the above link (the other files are old, I'll update them later).

    Also, a "flick" will set the shape rotating.

    With the swipes for translating, a two-fingered swipe translates before translating and a three-fingered one translates after.

    Once we get a decent data serialiser, after moving the vertices then it would be nice to be able to save the new data.

  • BortelsBortels Mod
    Posts: 1,557

    The vertex/edge data is just a couple of tables, no? It seems it would be easy enough to simply save them as strings of numbers, and parse them again. See

  • Posts: 2,161

    Yes, that would work. I'll look into it. Thanks!

    (I must take a longer look at that site. Just about every "how do I do X in lua" search that I do ends up there.)

  • SimeonSimeon Admin Mod
    Posts: 4,506

    I really like this and made a video of it


  • Posts: 2,161

    New version, now with more refined shape editing.

    There's a big red circle in the top left. Touching that toggles between "view" mode and "edit" mode. In edit mode, tapping a node selects it, moving a node moves it and all selected nodes. Double tapping a node toggles the edges (ie removes those that exist and creates those that don't) between it and all selected nodes. Tapping somewhere where there isn't a node creates a new node. (Should provide a way to delete a node as I keep creating new nodes by accident).

    Still to do: saving and loading shapes.

  • Posts: 2,161

    This version is a fairly major update as I'm using the new clip capabilities to deal with the non-transitivity of edges overlapping (see picture in first post). Basically, when we draw a new piece (vertex or edge) then we go back through the previously drawn edges and see if any should be on top of the latest one. If so, we redraw the old edge but clipped so that only the bit over the new edge is seen. (It's not completely ideal - there are some "edge effects" - but it's pretty darned good, if I say so myself.)

    I've also added the ability to specify a shape using valencies on the vertices. Each vertex is given an edge to the nearest other vertices up to its valency (and so long as those other ones have spare valency). This makes it much easier to specify something like, say, buckminster fullerene. The routine that specifies that is remarkably simple, considering the complexity of the molecule!

    Predefined shapes now include:

    • Cube
    • Octahedron
    • Borromean "rings" (actually rectangles)
    • Four sticks (to demonstrate the non-transitivity of "is in front of")
    • Two sticks (mainly for debugging)
    • "Chair" form of cyclic hexane

    The shape that is shown when the program is run is actually a "merge" of the cube and the octahedron, demonstrating the mutual symmetries of the two.

    It feels a bit sluggish because it is using the new routine for rendering edges. On some shapes, that isn't necessary and can be turned off (actually, the default is for it to be off).

    Need to work on the UI a bit, and severely comment the code (that's the one bit of programming that I actively dislike doing in Codea so I'm waiting until next time my iPad is hooked up to my Linux machine and I can use Emacs).

  • Posts: 130

    WOW! It's amazing! I'm not able to do that. :O I know many programming languages HTML, CSS2/3 Javascript/Ajax, PHP, Java and little C++, but I can not do that. Maybe I do not know about algorithms. (:|

  • Posts: 1,222

    Latest version is terrific, Andrew. Very impressive.

  • BortelsBortels Mod
    Posts: 1,557

    I, for one, am deeply disappointed.

    I've done balls-and-sticks before - a few times. This SO BLOWS AWAY even my best efforts, I can't even look at myself in the mirror. :-) (Ah, who am I kidding? I love me.)

    Next step is being able to define different types of vertices - we can pretend this is a molecule thing, and you're differentiating hydrogen, oxygen, carbon, and so on, but know in the back of your mind I'm thinking planets (or stars) and hyperspace lanes.

  • Posts: 2,161

    Next step is being able to define different types of vertices

    Vertices can already have their own colour, radius, and valency, overriding the defaults. Ditto edges. What else would you like?

  • Posts: 2,820

    Wholly crap! How did I miss this! As always, I like to give ideas. Possibly, you could define the number of vertices?

  • Posts: 2,161

    What would you have the program do if you specified, say, 4 vertices? Where would it put them? You can already edit the shape and add or delete vertices.

  • Posts: 2,820

    Oh... Sorry. Feel free to submit it. You can submit one price of code in each section in my compitition. I like it.

  • Posts: 109

    I really wanted to check this out but looks like the link is dead.

Sign In or Register to comment.