Share My Creation Small 3D Engine

Hi,

As you might remember, I published a small 3D engine for windows mobile. (as found here: http://www.b4x.com/forum/share-your-creations/3125-3d-plotter.html)
Today i rewrote it in Basic4Android. The engine animates a cube which rotates. Can you guys please test it? I just tested it in the emulator and I dont have any android device yet.
Just paste the below code in a new project.
Thanks

Ps.: I also appreciate hints and tips

B4X:
Sub Process_Globals
   Dim time As Timer
End Sub

Sub Globals

globxrot=0
globyrot=0
globzrot=0
framecount=0
zoom = 200
depth = 40
Dim matrix(64,64) As Boolean
Dim xarr(8) As Int
Dim yarr(8) As Int
Dim zarr(8) As Int

Dim xpoints(8) As Float
Dim ypoints(8) As Float
counteri=0

Dim testbtn As Button
Dim Label1 As Label
Dim ProgressBar1 As ProgressBar
Dim can As Canvas

End Sub

Sub init
xarr(0)=10:   yarr(0)=10:   zarr(0)=10
xarr(1)=10:   yarr(1)=10:   zarr(1)=-10
xarr(2)=10:   yarr(2)=-10:zarr(2)=-10
xarr(3)=-10:yarr(3)=-10:zarr(3)=-10
xarr(4)=-10:yarr(4)=-10:zarr(4)=10
xarr(5)=-10:yarr(5)=10:   zarr(5)=10
xarr(6)=-10:yarr(6)=10:   zarr(6)=-10
xarr(7)=10:   yarr(7)=-10:zarr(7)=10

matrix(1,0)=True
matrix(5,0)=True
matrix(7,0)=True

matrix(2,1)=True
matrix(6,1)=True

matrix(3,2)=True
matrix(7,2)=True


matrix(4,3)=True
matrix(6,3)=True

matrix(7,4)=True
matrix(5,4)=True

matrix(6,5)=True
End Sub

Sub Activity_Create(FirstTime As Boolean)
init
can.Initialize(Activity)
time.Initialize("Time",50)
time.Enabled=True
End Sub

Sub Activity_Resume
   time.Enabled=True
End Sub

Sub Activity_Pause (UserClosed As Boolean)
   time.Enabled=False
End Sub


Sub plot_object(xrot,yrot,zrot)
counteri=0
For i=0 To 7
   threedpoints(xarr(i),yarr(i),zarr(i),xrot,yrot,zrot)
Next
linecon
End Sub

Sub threedpoints(xthreed,ythreed,zthreed,rotx,roty,rotz)
   x2 = (xthreed * Cos(rotZ)) - (ythreed * Sin(rotZ))
   y2 = (xthreed * Sin(rotZ)) + (ythreed * Cos(rotZ))
   x3 = (x2 * Cos(rotY)) - (zthreed * Sin(rotY))
   z2 = (x2 * Sin(rotY)) + (zthreed * Cos(rotY))
   y3 = (y2 * Cos(rotX)) - (z2 * Sin(rotX))
   z3 = (y2 * Sin(rotX)) + (z2 * Cos(rotX))
      xtwod = zoom * (x3 / (z3 + depth)) + 120
        ytwod = zoom * (y3 / (z3 + depth)) + 130
        
      xpoints(counteri)=xtwod
      ypoints(counteri)=ytwod
      counteri=counteri+1
End Sub

Sub linecon
For n=0 To 7
   For i=n To 7
      If matrix(i,n)=True Then
         can.DrawLine(xpoints(n),ypoints(n),xpoints(i),ypoints(i),Colors.White,1)
      End If
   Next 
Next
End Sub

Sub time_Tick
can.DrawColor(Colors.Black)
globxrot=globxrot+0.1
globyrot=globyrot+0.1
plot_object(globxrot,globyrot,globzrot)
Activity.Invalidate
End Sub
 
Last edited:

tremara1

Active Member
Licensed User
Longtime User
working

I tried your app on a Samsung galaxy 5 phone, it worked quite well it was a bit slow in the emulator but a bit better on the device. I dont know how smooth it should run.
 

alfcen

Well-Known Member
Licensed User
Longtime User
Runs smoothly on a Sharp IS03 phone. Though hardly noticeable, it pauses slightly as it changes rotation axes (for a good reason). Accurately rendered 3D! Brilliant!

Assuming you are a 3D expert, would it be possible to wrap a world map around a globe and set a view point as such as "ViewGlobe(x,y,z)"? Constant rotation is not necessary. I did that before in VB6 but it took too long time to wrap the map, while the coordinate grid plotted fast enough in 30 degrees intervals.
 

MM2forever

Active Member
Licensed User
Longtime User
Thanks for assuming Im a 3D expert. Unfortunally, I'm not ^^
I got the trigonomy routine from an old QBasic tutorial and spiced it up a little bit.

But now to your question: Maybe I should at first make some kind of small 3d editor to be able to make such a globe easily... Maybe I'll find a good tutorial about texture mapping - and then we're on the go.
I will definately care about your idea. :sign0060:
 

karmacomposer

Member
Licensed User
Longtime User
Works amazingly well on a Viewsonic Gtablet (rooted and using TnTLite)

Any chance of you developing a full on 3d engine and editor to create games with? I own Shiva 3D but cannot seem to deploy to Android no matter what I do, meanwhile, I can easily deploy with Basic4Android and google app developer.

Love to see this raytraced or at least phong shaded. Now all you need is a terrain builder, world editor and the ability import .obj, .x, and maybe even collada files (hey, I can dream, can't I?)

Great job!

Mike
 

alfcen

Well-Known Member
Licensed User
Longtime User
Often dreams come true....

What I'd like to realize using B4A is someting like the Earth globe in TerraTime (on the Android market). This app is certainly written in native Java and tied to a 3D engine which either comes with the app or is part of the Android O/S. If the latter is true....
 

MM2forever

Active Member
Licensed User
Longtime User

I'm not sure if I'm that good... as I said to alfcen, I will give further development a shot....
 

karmacomposer

Member
Licensed User
Longtime User
I'm not sure if I'm that good... as I said to alfcen, I will give further development a shot....

Cool! I know that my gtablet, and many phone and tablet devices have the opengl engine - which is a gaming engine - so we just need to tap into that.

Mike
 

alfcen

Well-Known Member
Licensed User
Longtime User
Rotating Globe Grid

Play with angles and Timer interval

B4X:
'Activity module
Sub Process_Globals
   'These global variables will be declared once when the application starts.
   'These variables can be accessed from all modules.
   Dim Timer1 As Timer
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.
   Dim rad As Double: rad = 180 / cPI
   Dim PI_2 As Double: PI_2 = cPI / 2
   Dim PI2 As Double: PI2 = cPI * 2
   Dim Canvas1 As Canvas
   Dim Label1 As Label
   Dim xx, yy As Double
        Dim xc: xc = Activity.Width / 2
        Dim yc: yc = Activity.Height / 2
   Dim rx, ry, rz, w As Double
   'For earth globe: rx = latitude, ry = longitude, rz = orbit inclination (23.45)
   Dim x, y, z, ax, ay, az As Double
   Dim r, d, x1, x2, x3, y1, y2, y3, z1, z2, z3 As Double
   Dim rad1, rad2, rad3, rad15 As Double
   rad1 = 0.0174532925: rad2 = rad1*2: rad3 = rad1*3 : rad15 = rad1*15
End Sub

Sub Activity_Create(FirstTime As Boolean)
   Activity.Title = "Test Globe"
   Label1.Initialize("Label1")
   Activity.AddView(Label1,0,0,320dip,30dip)
   If FirstTime Then Timer1.initialize("Timer1", 1500)
   canvas1.Initialize(Activity)
   Timer1.Enabled = True
End Sub

Sub Activity_Resume
   rx = 26 / rad: ry = -5 / rad: rz = 23.45 / rad: w = 140dip
        Timer1_Tick
End Sub

Sub Activity_Pause (UserClosed As Boolean)
   Timer1.Enabled = False
End Sub

Sub Timer1_Tick
   'rx = rx + 5 / rad
   ry = ry + 5 / rad
   'rz = rz + 5 / rad
   Canvas1.DrawColor(Colors.Black)
   Globe
   Label1.Text = " Lat: " & Round(rx * rad) & Chr(176) & " Long: " & Round(ry * rad) & Chr(176) & " Incl: " & (rz * rad) & Chr(176) 
End Sub

Sub Globe
  Canvas1.DrawLine(xc, 0, xc, yc*2, Colors.RGB(128,0,0),1)
  Canvas1.DrawLine(0, yc, xc*2, yc, Colors.RGB(128,0,0),1)
  Canvas1.DrawCircle(xc,yc,w,Colors.Gray,False,1)
  x1 = Cos(rx) * Cos(ry)
  x2 = -Cos(rx) * Sin(ry)
  x3 = Sin(rx)
  y1 = Cos(rz) * Sin(ry) + Sin(rz) * Sin(rx) * Cos(ry)
  y2 = Cos(rz) * Cos(ry) - Sin(rz) * Sin(rx) * Sin(ry)
  y3 = -Sin(rz) * Cos(rx)
  z1 = Sin(rz) * Sin(ry) - Cos(rz) * Sin(rx) * Cos(ry)
  z2 = Sin(rz) * Cos(ry) + Cos(rz) * Sin(rx) * Sin(ry)
  z3 = Cos(rz) * Cos(rx)
  For r = 0 To PI2 Step rad15
    For d = PI_2 To -PI_2 Step -rad1
      GetPlotCoords
      Canvas1.DrawPoint(xx,yy,Colors.White)
    Next
  Next
  For d = PI_2 To -PI_2 Step -rad15
    For r = 0 To PI2 Step rad1
      GetPlotCoords
     Canvas1.DrawPoint(xx,yy,Colors.White)
    Next
  Next
  Activity.Invalidate
End Sub

Sub GetPlotCoords
  x = Cos(d) * Cos(r)
  y = Cos(d) * Sin(r)
  z = Sin(d)
  ax = x1 * x + x2 * y + x3 * z
  If ax > 0 Then
    ay = y1 * x + y2 * y + y3 * z
    az = z1 * x + z2 * y + z3 * z
    xx = xc + ay * w
    yy = yc - az * w
  End If
End Sub
 

Attachments

  • globe.jpg
    12.4 KB · Views: 608

fdx12345

Active Member
Licensed User
Longtime User
Rotate a 3D menu

I see some very nice ways to handle 2D rotation of a menu but not 3D. Seems the amination library is restricted to 2D.

I am looking at openGL but not sure if a rotatable item is selectable much less have several selectable items on the rotating object.

Any suggestions, or better yet, examples?

Thanks much,
 

noega33

Member
Licensed User
Longtime User
3D Text rotation

Hi,
just if anyone is interested by small example of 3D text rotation using the 3D engine proposed by MM2forever

B4X:
' 3D Text, Noega33, Jan 6, 2012
'Inspired from MM2forever Code published on Basic4Android Blog
'Draws text in a 3D rotating cube, text is entered line 84. Beware complete alphabet not yet available
' alternatively it can plot a curve using the "courbe" sub: comment lines 119-130 & 138, uncomment 131
'
Sub Process_Globals
    Dim time As Timer
End Sub

Sub Globals
Rot_X=0
Rot_Y=0
Rot_Z=0
zoom = 8000
depth = 40
Dim xarr(16) As Int
Dim yarr(16) As Int
Dim zarr(16) As Int
Dim xAxe(6) As Int
Dim yAxe(6) As Int
Dim zAxe(6) As Int
Dim xpoints(400) As Float
Dim ypoints(400) As Float
Dim x(400) As Float
Dim xcourbe(400) As Float
Dim ycourbe(400) As Float
Dim zcourbe(400) As Float
Dim EchelX As Float
Dim k As Int
Dim i As Int
Dim can As Canvas
Dim courbe_Max As Int
Dim EditText1 As EditText
Dim EditText2 As EditText
Dim EditText3 As EditText
Dim X_Angle As SeekBar
Dim Y_Angle As SeekBar
Dim Z_Angle As SeekBar
Dim Label1 As Label
Dim Label2 As Label
Dim Label3 As Label
Dim AFont As String
Dim DecodeStr(30) As String
Dim Automatic As CheckBox
Dim Autom As Boolean
Dim Text As String
Dim Car As String
Dim NbLtr As Int
Dim Color_line As Int
Dim Taille As Int
End Sub

Sub init
' Cube Coordinates
'    Note: All coordinates are normalized from -1 to +1
'    Some segments will be drawn twice
xarr(0)=1:    yarr(0)=1:    zarr(0)=1
xarr(1)=1:    yarr(1)=1:    zarr(1)=-1
xarr(2)=1:    yarr(2)=-1:   zarr(2)=-1
xarr(3)=1:    yarr(3)=-1:   zarr(3)=1
xarr(4)=1:    yarr(4)=1:    zarr(4)=1
xarr(5)=-1:      yarr(5)=1:    zarr(5)=1
xarr(6)=-1:      yarr(6)=1:    zarr(6)=-1
xarr(7)=-1:      yarr(7)=-1:   zarr(7)=-1
xarr(8)=-1:      yarr(8)=-1:   zarr(8)=1
xarr(9)=-1:      yarr(9)=1:    zarr(9)=1
xarr(10)=-1:   yarr(10)=1:    zarr(10)=-1
xarr(11)=1:    yarr(11)=1:    zarr(11)=-1
xarr(12)=1:    yarr(12)=-1:      zarr(12)=-1
xarr(13)=-1:   yarr(13)=-1:   zarr(13)=-1
xarr(14)=-1:   yarr(14)=-1:   zarr(14)=1
xarr(15)=1:    yarr(15)=-1:      zarr(15)=1

'Axes Coordinates
xAxe(0)=-1:   yAxe(0)=0:   zAxe(0)=0
xAxe(1)=1:   yAxe(1)=0:   zAxe(1)=0
xAxe(2)=0:   yAxe(2)=-1:   zAxe(2)=0
xAxe(3)=0:   yAxe(3)=1:   zAxe(3)=0
xAxe(4)=0:   yAxe(4)=0:   zAxe(4)=-1
xAxe(5)=0:   yAxe(5)=0:   zAxe(5)=1

Automatic_CheckedChange(True)

Text="NOEGA33"

End Sub

Sub Activity_Create(FirstTime As Boolean)
Activity.LoadLayout("3D_Golf.bal")
can.Initialize(Activity)
init
time.Initialize("Time",10)
time.Enabled=True
End Sub

Sub Activity_Resume
    time.Enabled=True
End Sub

Sub Activity_Pause (UserClosed As Boolean)
    time.Enabled=False
End Sub

Sub plot_object(xrot,yrot,zrot)
' Plot Cube
For i=0 To 15
    threedpoints(xarr(i),yarr(i),zarr(i),xrot,yrot,zrot)
Next
courbe_Max=16
Color_line=Colors.White
Taille=1
linecon3
'Plot Axis
For i=0 To 5
    threedpoints(xAxe(i),yAxe(i),zAxe(i),xrot,yrot,zrot)
Next
linecon2
'Plot Text
NbLtr=Text.Length
EchelX=2/(NbLtr)
For k=0 To NbLtr-1
   Car= Text.CharAt(k)
   vector(Car)
   courbe_Max=(AFont.Length-1)/4
   DecodeStr=Regex.Split(",",AFont)
      For p=0 To courbe_Max-1
         xcourbe(p)=k*EchelX-1+EchelX*0.1*DecodeStr(1+p*2)
         ycourbe(p)=0
         zcourbe(p)=EchelX*0.1*DecodeStr(2+p*2)
      Next
   'courbe
   For i =0 To courbe_Max-1
      threedpoints(xcourbe(i),ycourbe(i),zcourbe(i),xrot,yrot,zrot)
   Next
   Color_line=Colors.Green
   Taille=4
   linecon3
Next
End Sub

Sub threedpoints(xthreed,ythreed,zthreed,rotx,roty,rotz)
'3D Engine...
    x2 = (xthreed * CosD(rotz)) - (ythreed * SinD(rotz))
    y2 = (xthreed * SinD(rotz)) + (ythreed * CosD(rotz))
    z2 = (x2 * SinD(roty)) + (zthreed * CosD(roty))   
    x3 = (x2 * CosD(roty)) - (zthreed * SinD(roty))
    y3 = (y2 * CosD(rotx)) - (z2 * SinD(rotx))
    z3 = (y2 * SinD(rotx)) + (z2 * CosD(rotx))
        xpoints(i) = zoom * (x3 / (z3 + depth)) + 300
        ypoints(i) = zoom * (y3 / (z3 + depth)) + 300
End Sub

Sub linecon2
' Draws single segments
    For i=0 To 2
            can.DrawLine(xpoints(i*2),ypoints(i*2),xpoints(i*2+1),ypoints(i*2+1),Colors.Red,1)
    Next 
End Sub

Sub linecon3
' Draws multiple segments
For n=0 To courbe_Max-2
            can.DrawLine(xpoints(n),ypoints(n),xpoints(n+1),ypoints(n+1),Color_line,Taille)
Next
End Sub

Sub time_Tick
If Autom=True Then
can.DrawColor(Colors.Black)
Rot_X=Rot_X+1
Rot_Y=Rot_Y+1
Rot_Z=Rot_Z+1
plot_object(Rot_X,Rot_Y,Rot_Z)
EditText1.Text=X_Angle.Value
EditText2.Text=Y_Angle.Value
EditText3.Text=Z_Angle.Value
Activity.Invalidate
End If
End Sub

Sub courbe
courbe_Max=200
For k=0 To courbe_Max-1
   x(k)=k-Floor(courbe_Max/2)
   xcourbe(k)=SinD(5*x(k))
   ycourbe(k)=CosD(5*x(k))
   zcourbe(k)=x(k)/Floor(courbe_Max/2)
Next
End Sub

Sub vector(Carac As String)
' Font Vectors are generated on a 8X10 grid
' for example for letter "A"
' 1,1 is first point (x=1, y=1)
' 1,8 is second point (X=1, Y=8)
' 4,9 is thrid point (X=4, Y=9)
' and so on...
' Code is done to draw without lifting the pen...
Select Carac
Case "A"
AFont="A,1,1,1,8,4,9,7,8,7,1,7,5,1,5"
Case "B"
AFont="B,1,1,1,9,5,9,7,7,5,5,1,5,5,5,7,3,5,1,1,1"
Case "C"
AFont="C,7,1,1,1,1,9,7,9"
Case "D"
AFont="D,1,1,1,9,5,9,7,7,7,3,5,1,1,1"
Case "E"
AFont="E,7,1,1,1,1,5,5,5,1,5,1,9,7,9"
Case "F"
AFont="F,1,1,1,5,6,5,1,5,1,9,7,9"
Case "G"
AFont="G,4,5,7,5,7,1,7,1,1,1,1,9,7,9"
Case "U"
AFont="U,7,9,7,1,1,1,1,9"
Case "S"
AFont="S,7,9,1,9,1,5,7,5,7,1,1,1"
Case "L"
AFont="L,6,1,1,1,1,9"
Case "O"
AFont="O,7,1,1,1,1,9,7,9,7,1"
Case "I"
AFont="I,4,1,4,9"
Case "N"
AFont="N,1,1,1,9,7,1,7,9"
Case "3"
AFont="3,1,1,7,1,7,5,2,5,7,5,7,9,1,9"
Case " "
AFont=" ,1,1"
End Select

End Sub

Sub Z_Angle_ValueChanged (Value As Int, UserChanged As Boolean)
Update
End Sub

Sub Y_Angle_ValueChanged (Value As Int, UserChanged As Boolean)
Update
End Sub

Sub X_Angle_ValueChanged (Value As Int, UserChanged As Boolean)
Update
End Sub

Sub Update
can.DrawColor(Colors.Black)
Rot_X=X_Angle.Value
Rot_Y=Y_Angle.Value
Rot_Z=Z_Angle.Value
plot_object(Rot_X,Rot_Y,Rot_Z)
EditText1.Text=X_Angle.Value
EditText2.Text=Y_Angle.Value
EditText3.Text=Z_Angle.Value
Activity.Invalidate
End Sub

Sub Automatic_CheckedChange(Checked As Boolean)
   If Checked=True Then 
   Autom=True
   Else 
   Autom=False
   End If
End Sub


Note that all the fonts are not yet available, the attached excel file helps generating missing characters
Enjoy, Cheers
 

Attachments

  • Vector_Font_Noega33.zip
    53.7 KB · Views: 369
  • 3D_Charts_take_2.zip
    2.7 KB · Views: 348

JesseW

Active Member
Licensed User
Longtime User
... Ps.: I also appreciate hints and tips ...

Nice little cube demo! If you're looking for tips and hints, here's one I learned early on in Basic4android: Always declare the types of all of your variables, becuase when you don't, they default to a type of variant which is held in a string variable, and that's the slowest type of variable.

I changed your Sub Globals to this

B4X:
Sub Globals

Dim globxrot As Float = 0
Dim globyrot As Float = 0
Dim globzrot As Float = 0
'framecount=0
Dim zoom As Int = 400
Dim depth As Int = 40
Dim matrix(64,64) As Boolean
Dim xarr(8) As Int
Dim yarr(8) As Int
Dim zarr(8) As Int

Dim xpoints(8) As Float
Dim ypoints(8) As Float
Dim counteri As Int = 0

Dim testbtn As Button
Dim Label1 As Label
Dim ProgressBar1 As ProgressBar
Dim can As Canvas

End Sub

See how they are now defined as Float and Int? Now, any routine that uses them will execute faster. I also added this line to the top of Sub threedpoints

B4X:
   Dim x2, y2, z2, x3, y3, z3, xtwod, ytwod As Float

Does it make this particular demo run any faster? hard to tell on my Droid Razr M. But perhaps you might see some difference in the emulator.

Keep up the good work!

ps. Just so you know, Int's are the fastest type of variable, even faster than Short's and Byte's, since that's the native size of all the microprocessors internal registers. All variables that do not need to be of another type should always be Dim'd as Int.
 

noega33

Member
Licensed User
Longtime User
3D Rotating Text

Hi,
This post is in addition to my previous one dated Jan 6 2013, because I had forgotten to provide the .bal file in the ZIP
I also took into account JesseW comments
Cheers
Noega33
 

Attachments

  • 3D_Text_Jan-10-2013.zip
    9.4 KB · Views: 385
Cookies are required to use this site. You must accept them to continue using the site. Learn more…