PDA

View Full Version : Best approach for large Rubik's cube with dynamic colors and dynamically hidden parts



Alketi
04-09-2015, 07:59 PM
Hi all, I'm hoping to find some advice on a beginner opengl question.

I have what's essentially an NxNxN Rubik's cube. Let's say for example, it's 10x10x10.

I can safely use opengl version 2, maybe pushing it to opengl 3. But my application has to run on a variety of hardware, so opengl 2 is safe.

My current approach is to simply render the cube using the equivalent of glutSolidCube() in a for loop, for the 1,000 cubelets, for each frame. This has some obvious performance penalties, so I'm looking for a better approach.

My requirements are:

1. The (1,000) cubelets need to become visible dynamically, as their data becomes available.
2. The cubelets may have different colors.
3. The cubelets can all change both color and visibility dynamically, via an event. So, for example, I may only want to show the green cubelets, hiding the others. Another event may change the colors of all the cubelets, from green/red to light blue/dark blue, for example.

- Can someone point me in the right direction as to how to accomplish this while optimizing performance?

- Can VBO or VAO be used while dynamically changing the cubelet colors and visibility?

- Can any optimizations be accomplished in opengl v2?

Thank you very much for any advice or guidance.

[EDIT: Examples of the behavior I want to provide]


1741 1742 1740

Alfonse Reinheart
04-09-2015, 08:17 PM
My current approach is to simply render the cube using the equivalent of glutSolidCube() in a for loop, for the 1,000 cubelets, for each frame. This has some obvious performance penalties, so I'm looking for a better approach.

Well, there's an immediate improvement you can make by not rendering 1,000 cubes when the user can only ever see ~300 of them (given your 10x10x10 case). There's no point in rendering interior cubes or cubes for the back side of the main cube.

Then, there's not rendering cubes at all. Render squares. Render the visible surface, not what would actually be there if it were a true Rubick's cube. You should be able to accomplish this with a single glDrawArrays call with GL_QUADS (or GL_TRIANGLES). You'll have to duplicate vertex colors, but let's face facts: even for a 1000x1000x1000 cube, you're not going to be hurting that much for memory.

If you want to be able to show specific colors, that's accomplished easily too. Make 6 glDrawArrays calls instead of 1. One call per color. If you don't want a color to be visible, don't draw it (though your model will have holes in it if you don't render some squares, so I would suggest using a neutral color instead of not drawing it).

I'll assume you're going to want to animate the rotation of a particular part of the cube (row/column/depth). In that case, you should build a model for that part of the animation (one for a middle piece, one for a side piece. Use translation and orientation to adjust where it appears). Then, just don't draw the squares for the piece that's animating. Instead, draw your special animation model, which will rotate around. Once it gets to the final position, stop drawing the animation model and go back to drawing the colored squares (with updated colors for the new position, of course).

Alketi
04-09-2015, 08:42 PM
Thank you for the response Alfonse.

I should clarify a few points, since I don't think I did a very good job in my initial post. :)

The Rubik's cube is only an analogy for the "shape" of the object, not for the actual behavior, the motion, or the colors. For example, the colors wouldn't be limited to six and I would need to at some point render the interior cubes.

These examples below show what I'm after.

1. The user can view the entire cube
2. Can slice the cube in any of the three planes (XY, XZ, YZ)
3. And also peer through the cube to only see certain colors (making all other colored cubes invisible)

1741

1742

1740

Alfonse Reinheart
04-09-2015, 10:08 PM
While this effectively turns this into a "draw like Minecraft" problem, the solution is still more or less the same: you draw the visible surface, not the series of cubes. That's how Minecraft works; it computes the surface that's visible and draws a mesh made of squares based on that. It breaks the surface up into chunks to do so, but that's the general idea.

If you turn off some set of cubes, then you recompute the surface based on those cubes not being present.

You could even use a form of Marching Cubes to generate the surface. A cube that is surrounded on all 6 primary sides by visible cubes cannot be seen. A cube that is surrounded by only 5 cubes has one exposed face on its surface. And so forth.

From your pictures, it's not clear that you even need the camera to move. If you don't, then you can also disregard all faces that point away from the camera's fixed position. But if the camera rotates, that would involve more frequent surface recomputation, so let backface culling do its job.