Android Example 3D Spinning Cube

It is mostly based on this posting. It is a 3D spinning cube. The code is very simple (the lib does all the hard lifting). You can change the images of the 6 x faces of the cube by replacing image1.png to image6.png in the /DemoRes/drawable folder of the B4A project (too lazy now to add code to the project to allow adding the images from B4A). It can be *.png or *.jpg files - as long as you keep the naming convention of image1.* to image6.*

1. Download the B4A project
2. Download DemoRes.zip and once unzipped you need to copy the DemoRes folder and its contents to be on the same folder level as that of the /Files and /Objects folders of the B4A project
3. Download the B4A lib files, extract them from the zipped file, and copy them to your additional library folder.
4. Note the CustomView in the Designer.

I have edited the images with GIMP just to make the interfaces more visible.

This was done just for the fun of it.....:)


B4A sample code:

B4X:
#Region  Project Attributes
    #ApplicationLabel: b4aOpenGlesPhotoCube
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: portrait
    #CanInstallToExternalStorage: False
#End Region

#AdditionalRes: ..\DemoRes

#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.

End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.

    Private gls1 As glSurfaceView
End Sub

Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    Activity.LoadLayout("main")

End Sub

Sub Activity_Resume
   
    gls1.RESUME

End Sub

Sub Activity_Pause (UserClosed As Boolean)
   
    gls1.PAUSE

End Sub

1.png
 

Attachments

  • b4aLibFiles.zip
    7 KB · Views: 483
  • b4aOpenGlesPhotoCube.zip
    9.2 KB · Views: 477
  • DemoRes.zip
    116.6 KB · Views: 534
  • TheJavaCode.zip
    4.9 KB · Views: 453
Last edited:

ilan

Expert
Licensed User
Longtime User
looks really nice. would it be possible to use this cube as a menu? like if i click on a side of the cube an event will be raised?
 

Johan Schoeman

Expert
Licensed User
Longtime User
looks really nice. would it be possible to use this cube as a menu? like if i click on a side of the cube an event will be raised?
It should be possible to do so. But the Java code needs some serious surgery to allow for that. :)
 

Johan Schoeman

Expert
Licensed User
Longtime User
No more need for the DemoRes folder in the above B4A project. You can now pass the images to the cube from within the B4A project. You can also do the following:
1. As mentioned above, pass the 6 cube face images from the B4A project (it is done via a list of 6 images that is passed to the wrapper)
2. Allow the cube to be zoomed in/out while it is spinning
3. Set the cube spinning speed - it will rotate around the RotationPlane that you set up in the B4A code (setting positive and negative values will change the direction of the rotation)
4.Set the rotation plane (x, y, z) - values should be between -1.0 and 1.0 (float)
Attached new B4A project and new B4A lib files. Copy the lib files (once extracted from the zip) to your additional libs folder.
The images used in this project should be in the /Files folder of the attached B4A project.
My AVD Manager is for some reason not working...:mad: Else I would have posted a GIF to demonstrate the spinning cube. I still have this error and no idea how to solve it.
B4A Code:
B4X:
#Region  Project Attributes
    #ApplicationLabel: b4aOpenGlesPhotoCube
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: portrait
    #CanInstallToExternalStorage: False
#End Region
#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region
Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
End Sub
Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.
    Private gls1 As glSurfaceView
 
    Dim facelist As List
    Dim mbm(6) As Bitmap
 
End Sub
Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    Activity.LoadLayout("main")
 
    facelist.Initialize
    'add 6 images to (List) facelist - one for each of the faces of the cube
    mbm(0).Initialize(File.DirAssets,"image1.png")
    facelist.Add(mbm(0))
    mbm(1).Initialize(File.DirAssets,"image2a.jpg")
    facelist.Add(mbm(1))
    mbm(2).Initialize(File.DirAssets,"image3.png")
    facelist.Add(mbm(2))
    mbm(3).Initialize(File.DirAssets,"image4.png")
    facelist.Add(mbm(3))
    mbm(4).Initialize(File.DirAssets,"image5.png")
    facelist.Add(mbm(4))
    mbm(5).Initialize(File.DirAssets,"image6.png")
    facelist.Add(mbm(5))
 
    'pass (List) facelist on to the wrapper
    gls1.SixFaces = facelist
 
    'this has to be set AFTER the LIST has been passed to the wrapper
    gls1.ZoomInOut = True                       'it will make the cube zoom In/Out while spinning anround the below defined RotationPlane
    gls1.CubeSpeed = 3.0                        'A negative value will reverse the direction of the spin
    gls1.RotationPlane(1.0, -1.0, 0.0)          'Keep these values between 0.0 and 1.0 (you can also apply negative values)
 
End Sub
Sub Activity_Resume
 
    gls1.RESUME
  
End Sub
Sub Activity_Pause (UserClosed As Boolean)
 
    gls1.PAUSE
End Sub
Zoomed in:
1.png

Zoomed out:
2.png

Lib:
glSurfaceView
Version:
1
  • glSurfaceView
    Fields:
    • ba As anywheresoftware.b4a.BA
    Methods:
    • DesignerCreateView (base As anywheresoftware.b4a.objects.PanelWrapper, lw As anywheresoftware.b4a.objects.LabelWrapper, props As anywheresoftware.b4a.objects.collections.Map) As void
    • IsInitialized As boolean
    • Initialize (ba As anywheresoftware.b4a.BA, EventName As java.lang.String) As void
    • RESUME As void
    • PAUSE As void
    • BringToFront As void
    • SetLayout (arg0 As int, arg1 As int, arg2 As int, arg3 As int) As void
    • SendToBack As void
    • SetVisibleAnimated (arg0 As int, arg1 As boolean) As void
    • RemoveView As void
    • Invalidate3 (arg0 As int, arg1 As int, arg2 As int, arg3 As int) As void
    • Invalidate2 (arg0 As android.graphics.Rect) As void
    • RotationPlane (rotation_x As float, rotation_y As float, rotation_z As float) As void
    • SetColorAnimated (arg0 As int, arg1 As int, arg2 As int) As void
    • SetBackgroundImageNew (arg0 As android.graphics.Bitmap) As anywheresoftware.b4a.objects.drawable.BitmapDrawable
    • Invalidate As void
    • SetLayoutAnimated (arg0 As int, arg1 As int, arg2 As int, arg3 As int, arg4 As int) As void
    • RequestFocus As boolean
    Properties:
    • Left As int
    • Background As android.graphics.drawable.Drawable
    • Parent As java.lang.Object [read only]
    • CubeSpeed As float [write only]
    • Color As int [write only]
    • SixFaces As java.util.List [write only]
    • Enabled As boolean
    • ZoomInOut As boolean [write only]
    • Top As int
    • Visible As boolean
    • Padding As int[]
    • Height As int
    • Tag As java.lang.Object
    • Width As int
 

Attachments

  • b4aOpenGlesPhotoCube.zip
    251 KB · Views: 359
  • b4aLibFiles.zip
    18.9 KB · Views: 350
  • TheJavaCode.zip
    17.5 KB · Views: 347
Last edited:

Randy Younger

Member
Licensed User
No more need for the DemoRes folder in the above B4A project. You can now pass the images to the cube from within the B4A project. You can also do the following:
1. As mentioned above, pass the 6 cube face images from the B4A project (it is done via a list of 6 images that is passed to the wrapper)
2. Allow the cube to be zoomed in/out while it is spinning
3. Set the cube spinning speed - it will rotate around the RotationPlane that you set up in the B4A code (setting positive and negative values will change the direction of the rotation)
4.Set the rotation plane (x, y, z) - values should be between -1.0 and 1.0 (float)

Attached new B4A project and new B4A lib files. Copy the lib files (once extracted from the zip) to your additional libs folder.
The images used in this project should be in the /Files folder of the attached B4A project.

My AVD Manager is for some reason not working...:mad: Else I would have posted a GIF to demonstrate the spinning cube. I still have this error and no idea how to solve it.

B4A Code:
B4X:
#Region  Project Attributes
    #ApplicationLabel: b4aOpenGlesPhotoCube
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: portrait
    #CanInstallToExternalStorage: False
#End Region


#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.

End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.

    Private gls1 As glSurfaceView
  
    Dim facelist As List
    Dim mbm(6) As Bitmap
  
End Sub

Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    Activity.LoadLayout("main")
  
    facelist.Initialize
    'add 6 images to (List) facelist - one for each of the faces of the cube
    mbm(0).Initialize(File.DirAssets,"image1.png")
    facelist.Add(mbm(0))
    mbm(1).Initialize(File.DirAssets,"image2a.jpg")
    facelist.Add(mbm(1))
    mbm(2).Initialize(File.DirAssets,"image3.png")
    facelist.Add(mbm(2))
    mbm(3).Initialize(File.DirAssets,"image4.png")
    facelist.Add(mbm(3))
    mbm(4).Initialize(File.DirAssets,"image5.png")
    facelist.Add(mbm(4))
    mbm(5).Initialize(File.DirAssets,"image6.png")
    facelist.Add(mbm(5))
  
    'pass (List) facelist on to the wrapper
    gls1.SixFaces = facelist
  
    'this has to be set AFTER the LIST has been passed to the wrapper
    gls1.ZoomInOut = True                       'it will make the cube zoom In/Out while spinning anround the below defined RotationPlane
    gls1.CubeSpeed = 3.0                        'A negative value will reverse the direction of the spin
    gls1.RotationPlane(1.0, -1.0, 0.0)          'Keep these values between 0.0 and 1.0 (you can also apply negative values)
  
End Sub

Sub Activity_Resume
  
    gls1.RESUME
      
End Sub

Sub Activity_Pause (UserClosed As Boolean)
  
    gls1.PAUSE

End Sub


Zoomed in:
View attachment 67317


Zoomed out:
View attachment 67318
Lib:

glSurfaceView
Version:
1
  • glSurfaceView
    Fields:
    • ba As anywheresoftware.b4a.BA
  • Methods:
    • DesignerCreateView (base As anywheresoftware.b4a.objects.PanelWrapper, lw As anywheresoftware.b4a.objects.LabelWrapper, props As anywheresoftware.b4a.objects.collections.Map) As void
    • IsInitialized As boolean
    • Initialize (ba As anywheresoftware.b4a.BA, EventName As java.lang.String) As void
    • RESUME As void
    • PAUSE As void
    • BringToFront As void
    • SetLayout (arg0 As int, arg1 As int, arg2 As int, arg3 As int) As void
    • SendToBack As void
    • SetVisibleAnimated (arg0 As int, arg1 As boolean) As void
    • RemoveView As void
    • Invalidate3 (arg0 As int, arg1 As int, arg2 As int, arg3 As int) As void
    • Invalidate2 (arg0 As android.graphics.Rect) As void
    • RotationPlane (rotation_x As float, rotation_y As float, rotation_z As float) As void
    • SetColorAnimated (arg0 As int, arg1 As int, arg2 As int) As void
    • SetBackgroundImageNew (arg0 As android.graphics.Bitmap) As anywheresoftware.b4a.objects.drawable.BitmapDrawable
    • Invalidate As void
    • SetLayoutAnimated (arg0 As int, arg1 As int, arg2 As int, arg3 As int, arg4 As int) As void
    • RequestFocus As boolean
  • Properties:
    • Left As int
    • Background As android.graphics.drawable.Drawable
    • Parent As java.lang.Object [read only]
    • CubeSpeed As float [write only]
    • Color As int [write only]
    • SixFaces As java.util.List [write only]
    • Enabled As boolean
    • ZoomInOut As boolean [write only]
    • Top As int
    • Visible As boolean
    • Padding As int[]
    • Height As int
    • Tag As java.lang.Object
    • Width As int


I would love to use this, but when I set the background image, the rotating cube disappears.
 

Johan Schoeman

Expert
Licensed User
Longtime User
@mmieher requested to add the ability to set the background color behind the cube. Use attached library (copy the jar and xml to your additional libs folder (V1.01))
B4X:
gls1.setCubeBackgroundColor(0.5f, 0.0f, 0.0f, 0.5f)

Sequence is r, g, b, a.......see popup help when using this method

3.png
 

Attachments

  • glSurfaceView.jar
    19.2 KB · Views: 63
  • glSurfaceView.xml
    11.3 KB · Views: 66
Last edited:

mmieher

Active Member
Licensed User
Longtime User
I hate to look a gift horse in the mouth, but please see the attached test project...

The bitmap used for the Facelist is transparent, but that black background (on just bitmap) is still there. Any ideas?

Marc
 

Attachments

  • b4aOpenGlesPhotoCube.zip
    170.2 KB · Views: 65

Johan Schoeman

Expert
Licensed User
Longtime User
I hate to look a gift horse in the mouth, but please see the attached test project...

The bitmap used for the Facelist is transparent, but that black background (on just bitmap) is still there. Any ideas?

Marc
Will see if I can sort it out. Probably the 6 faces that have a default color of black....I guess.
 

Johan Schoeman

Expert
Licensed User
Longtime User
I hate to look a gift horse in the mouth, but please see the attached test project...

The bitmap used for the Facelist is transparent, but that black background (on just bitmap) is still there. Any ideas?

Marc
Marc, probably the best I can get it for now with the time that I have available. Seems to be challenging to set the faces to a transparent color in order to "peek" inside the cube from the outside. The only way that I could find thus far to peek inside the cube is to set the "gap" between the faces/ explode the cube slightly.

Set the various parameters in the sample project to see what will work best for you. Have added some additional methods to set the color of the individual faces, to set the gapping between the faces and to set lighting enabled/disabled,

Attached a sample project and the B4A lib files (jar and xml). Extract the Jar and Xml and copy them to your additional library folder.


1.png


B4X:
#Region  Project Attributes
    #ApplicationLabel: b4aOpenGlesPhotoCube
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: portrait
    #CanInstallToExternalStorage: False
#End Region

'    Marc Removed
'#AdditionalRes: ..\DemoRes

#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region

Sub Process_Globals
End Sub

Sub Globals
    Private gls1 As glSurfaceView
  
    '    Added by Marc
    Private Facelist As List
    Private mbm(6) As Bitmap
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("main")
      
    Facelist.Initialize
    'add 6 images to (List) facelist - one for each of the faces of the cube
    mbm(0).Initialize(File.DirAssets,"aacube1.png")
    Facelist.Add(mbm(0))
    mbm(1).Initialize(File.DirAssets,"aacube1.png")
    Facelist.Add(mbm(1))
    mbm(2).Initialize(File.DirAssets,"aacube1.png")
    Facelist.Add(mbm(2))
    mbm(3).Initialize(File.DirAssets,"aacube1.png")
    Facelist.Add(mbm(3))
    mbm(4).Initialize(File.DirAssets,"aacube1.png")
    Facelist.Add(mbm(4))
    mbm(5).Initialize(File.DirAssets,"aacube1.png")
    Facelist.Add(mbm(5))
  
    gls1.SixFaces = Facelist
  
    gls1.setCubeBackgroundColor(0.1f, 0.1f, 0.0f, 0.0f)   'set the background color of the cube - note that values should be between 0.0f and 0.1f
  
    gls1.LightingEnabled = False
  
    gls1.CubeHalfSize = 1.2f                               'set the gap between the 6 faces of the cube(1 => face align perfectly, < 1 => faces overlap, > 1 => faces spaced outwards and can see inside the cube)
  
    gls1.CubeSpeed = -2.5f                                 'set the cube rotation speed (positive value => CCW, negative value => CW)
  
    gls1.ZoomInOut = True                                  'if true then zoom in and out, if false then don't zoom in and out
  
    gls1.setFace_1_Color(0.0f, 0.0f, 1.0f, 1.0f)          'blue
    gls1.setFace_2_Color(1.0f, 0.0f, 0.0f, 1.0f)          'red
    gls1.setFace_3_Color(0.0f, 1.0f, 0.0f, 1.0f)          'green
    gls1.setFace_4_Color(1.0f, 1.0f, 0.0f, 1.0f)          'yellow
    gls1.setFace_5_Color(0.0f, 1.0f, 1.0f, 1.0f)          'cyan
    gls1.setFace_6_Color(1.0f, 0.0f, 1.0f, 1.0f)          'magenta
  
  
End Sub


Sub Activity_Resume
  
    If gls1.IsInitialized Then
'    this line from the original demo crashes every time
'        gls1.RESUME
    End If

End Sub

Sub Activity_Pause (UserClosed As Boolean)
  
    gls1.PAUSE

End Sub
 

Attachments

  • b4aLibFiles.zip
    9.1 KB · Views: 58
  • b4aOpenGlesPhotoCube.zip
    146 KB · Views: 67
Last edited:

mmieher

Active Member
Licensed User
Longtime User
Thank you. For some reason I am just now seeing this. Did not get an email. Will check out your update.

Marc
 

Johan Schoeman

Expert
Licensed User
Longtime User
It's terrific @Johan Schoeman! Thanks again.

PS -- Looks like you accidently backed the version of the library back to 1.0.
Take a look at this project.


It will definitely make it more flexible to use. You will have to read up a bit on Open gl ES. Search the web for NeHe Open gl tutorial (http://myhsts.org/blog/Android_3D.html)

You will also need to download @agraham library from post #1 of his thread.
 
Last edited:
Top