B4J Question 3D rotation

rayellam

Member
Licensed User
Hi All,
I just started on B4J yesterday so forgive me if im missing something here. I want to squirt some numbers into B4J via Bluetooth serial port from a 6 axis IMU i will be making. I have a 3D rectangle in designer (shapes - box(FX8) that i have full control over at DESIGN time BUT i want to manipulate the rotate and transition parameters at RUN time. There seem to be no methods with box to do this.

So i found a wrapper to do this called rotate transition V1.0 BUT you have no control at run time on selecting which axis to rotate. If i go into designer and select box - transforms - select axis the axis then at run time it rotates correctly. How can i get control of the select x, y, z axis parameters?

Thanks
Ray
 

derez

Expert
Licensed User
Long ago I made a program for 3D (without any library). If it may serve you - look below.
The body is defined by an array of points, by polygons which are defined by the points number in the array, and by color for each polygon.
The 3d "engine" works by finding the new coordinates of each point according to the new angles (by each axis), then flattening the points to the board and then decide for each polygon if it is displayed or hiden by the body.
The code below is just a part of an application.
B4X:
Sub Globals
Dim bmp As Bitmap

Type bodyframe(x As Float,y As Float,z As Float)  ' body 3D coordinates
Dim body(21) As bodyframe
Dim rotbody(21) As bodyframe
Dim flat(15,3) As Float
end sub

Sub DrawBody
Dim x,y,z As Float

x = posx  ' offset where to put the body
y = posy
z = posz
          
For i = 0 To 18
    rotbody(i).x = body(i).x
    rotbody(i).y = body(i).y
    rotbody(i).z = body(i).z
Next
                ' calculate new body points
rotate
flatten
Polygons
End Sub

Sub rotate
Dim sx,cx,sy,cy,sz,cz,tempx,tempy As Float

sx = SinD(pitch)
cx = CosD(pitch)
sy = SinD(angle_xz)
cy = CosD(angle_xz)
sz = SinD(roll)
cz = CosD(roll)
       
For i=0 To nVertices - 1
    tempx = (cz*cy-sz*sx*sy)*rotbody(i).x -(cy*sz+sy*sx*cz)*rotbody(i).y + sy*cx*rotbody(i).z
    tempy = cx*sz *rotbody(i).x + cz*cx*rotbody(i).y + sx*rotbody(i).z
    rotbody(i).z = -(sy*cz+cy*sx*sz)*rotbody(i).x +(sy*sz-cy*sx*cz)*rotbody(i).y + cx*cy*rotbody(i).z
    rotbody(i).x = tempx
    rotbody(i).y = tempy
Next          
End Sub

Sub  flatten
Dim zfx,zfy,newx,newy,newz As Float

zfx = SinD(45)/2  ' viewing angle
zfy = CosD(45)/2
For i=0 To nVertices -1       
       newx = rotbody(i).x + posx
       newy = rotbody(i).y + posy
       newz = rotbody(i).z + posz
       flat(i,0) = centx +  zoom *(newx + zfx*newz) /(1+perspective*newz)
    flat(i,1) = centy - 0.92 * (zoom*(newy + zfy*newz))/(1+perspective*newz)
    flat(i,2) = newz
Next
End Sub

Sub Polygons '(Int nPolygons,String [] PL , Double  [,] FL,Int [] CL  )
Dim det, big As Float
Dim strarr() As String 'To split the polygon String To points.
Dim m,k0,k1,k2, order As Int
Dim xy As Path

det = 0       ' determinant of 3 first points of each polygon

Dim mp, mp1 As Map 
mp.Initialize
mp1.Initialize
For i = 0 To npolygons - 1
      strarr = Regex.Split(",",pol(i))
      Zsum(i) = 0
      For j=0 To strarr.Length -1
        m = strarr(j)
          Zsum(i) = Zsum(i) + flat(m,2) ' add Z values To sum
    Next
    mp.put(i,Zsum(i))
Next
For j = 0 To npolygons - 1
    big = 0
    order = 0
    For i = 0 To mp.Size - 1
        If mp.GetValueAt(i) > big Then
            big = mp.GetValueAt(i)
            order = i
        End If
    Next
    mp1.Put(order,big)
    mp.Remove(mp.GetKeyAt(order))
Next

Activity.SetBackgroundImage(bmp)
gr.Initialize(Activity)

For m = 0 To npolygons - 1
      strarr = Regex.Split(",",pol(m))
    k0 = strarr(0)
    k1 = strarr(1)
    k2 = strarr(2)
          det = flat(k0,0) * ( flat(k2,1) - flat(k1,1)) + flat(k1,0) * ( flat(k0,1) - flat(k2,1)) + flat(k2,0) * ( flat(k1,1) - flat(k0,1))

        If det < 0 Then ' the poligon Is in front
            xy.Initialize(flat(k0,0),flat(k0,1))
            xy.LineTo(flat(k1,0),flat(k1,1))
            xy.LineTo(flat(k2,0),flat(k2,1))
            xy.LineTo(flat(k0,0),flat(k0,1))
            gr.DrawPath(xy,Color(m),True,2)
        End If
Next
Activity.Invalidate
End Sub

Sub s7_click
Dim stx(),sty(),stz() As String

nVertices = 15
npoligons = 18
stx = Regex.Split(",","6,0,0,0,0,-6,-1,1,0,0,0,-0.17,-1.5,1.5,0.17")
stz = Regex.Split(",","-3,-1.5,0,1.5,0,-3,-2,-2,-5,-5.5,-3.5,-3.5, -5.5,-5.5,-3.5")
sty = Regex.Split(",","1.5,0,0.5,0,-0.25,1.5,0,0,0,1.5,0.17,0,0,0,0")

For i = 0 To nVertices - 1
     body(i).x = stx(i)
    body(i).y = sty(i)
    body(i).z = stz(i)
Next

pol(0) = "5,6,4"
Color(0) = Colors.Blue
pol(1) = "5,4,3"
Color(1) = Colors.rgb(255,125,125)
pol(2) = "0,7,2"
Color(2) = Colors.Yellow
pol(3) = "0,2,3"
Color(3) = Colors.Green 'Rgb(255,128,192)
pol(4) = "6,5,2"
Color(4) = Colors.Green
pol(5) = "2,5,3"
Color(5) = Colors.Yellow
pol(6) = "7,0,4"
Color(6) = Colors.rgb(255,125,125)
pol(7) = "4,0,3"
Color(7) = Colors.Blue
pol(8) = "2,8,6"
Color(8) = Colors.Yellow
pol(9) = "8,2,7"
Color(9) = Colors.Green
pol(10) = "4,6,8"
Color(10) = Colors.rgb(255,125,125)
pol(11) = "4,8,7"
Color(11) = Colors.Blue
pol(12) = "8,9,10"
Color(12) = Colors.Red
pol(13) = "10,9,8"
Color(13) = Colors.Red
pol(14) = "11,8,12"
Color(14) = Colors.Red
pol(15) = "14,13,8"
Color(15) = Colors.Red
pol(16) = "14,8,13"
Color(16) = Colors.Red
pol(17) = "12,8,11"
Color(17) = Colors.Red
zoom = 15
End Sub
 

Attachments

  • 1.png
    1.png
    24 KB · Views: 276
  • 2.png
    2.png
    35.1 KB · Views: 287
Last edited:
Upvote 0

rayellam

Member
Licensed User
I think im making some progress using java object to run jfx methods on box. I can read which axis is set but i get an error when trying to set the rotation axis "java.lang.RuntimeException: Method: setRotationAxis not matched."

I think its a problem with the way im passing the parameters to setRotationAxis?
 
Upvote 0

rayellam

Member
Licensed User
Sub AppStart (Form1 As Form, Args() As String)
MainForm = Form1
MainForm.RootPane.LoadLayout("Main2") 'Load the layout file.
MainForm.Show

'Turn an Object into a JavaObject AND Then run a method on it.
'See which axis is currently set to rotate
tempstring = asJavaObject(box1).RunMethod("getRotationAxis",Null)
label1.Text = tempstring

'Set the rotation axis
asJavaObject(box1).RunMethod("setRotationAxis",Array(0.0,0.0,1.0))
'asJavaObject(box1).RunMethod("setRotationAxis",Array("Rotate.X_AXIS"))
End Sub

Sub asJavaObject(j As JavaObject) As JavaObject
Return j
End Sub
 
Upvote 0

Daestrum

Well-Known Member
Licensed User
You could try
B4X:
dim jo as javaobject
jo.initializestatic("javafx.scene.transform.Rotate")
(....)
asJavaObject(box1).RunMethod("setRotationAxis",Array(jo.getfield("X_AXIS"))
(...)

below is a project I was trying 3d out a while back - it may give you some pointers.
 

Attachments

  • box test.zip
    1.3 KB · Views: 258
Last edited:
Upvote 0

rayellam

Member
Licensed User
Hi Daestrum,
You have earned a VERY large medal from me for this....................it works like a charm :) iv been messing with this all day, learnt a fair bit about how to interface with java libs and i think now its about time to have a LARGE cold beer or 2.

Thank you :)

Ray
 
Upvote 0

Daestrum

Well-Known Member
Licensed User
I have not really done much with this since.
I made a Custom Control that used transforms to mimic a flip sign (like old train ones that flip the letters at the centre vertically)

flipsign.png


You're welcome to see the code it uses. (mostly pure java).
 
Upvote 0

alienhunter

Active Member
Licensed User
I have not really done much with this since.
I made a Custom Control that used transforms to mimic a flip sign (like old train ones that flip the letters at the centre vertically)

View attachment 50058

You're welcome to see the code it uses. (mostly pure java).

Hi ,thanks
i was looking for ever for an flip letter like that , would be nice to know how too ..
My main intention was to build a simple machine simulator and hoped you have also the translation/scale
figured it out ;) in 2D point and 3D point
the way you wrote the rotation i understand better then other code , my problem is i do not understand too much about
how to with javaobject , i do not have too much time on my hands to learn new stuff :oops:
just putting 1+1 together what i can find on the forum
Would be nice if B4J had more of this 3D stuff ...

thanks AH

predator_virtual_cnc_machine_simulation.jpg
 
Upvote 0

alienhunter

Active Member
Licensed User
Got it
it is easier than i thought :oops:

B4X:
  transset.Initializenewinstance("javafx.scene.transform.Translate",Null)
   transset.RunMethod("setX",Array(50.0))
   transset.RunMethod("setY",Array(50.0))
   transset.RunMethod("setZ",Array(0.0))
   box.RunMethodjo("getTransforms",Null).RunMethod("add",Array(transset))


B4X:
  transscale.Initializenewinstance("javafx.scene.transform.Scale",Null)
   transscale.RunMethod("setX",Array(2.0))
   transscale.RunMethod("setY",Array(2.0))
   transscale.RunMethod("setZ",Array(2.0))
   box.RunMethodjo("getTransforms",Null).RunMethod("add",Array(transscale))



This will scale the box by factor 2 and this will shift the box by 50,50,0 .. one step closer :)
 
Last edited:
Upvote 0

Star-Dust

Expert
Licensed User
This code works well with object declared as a box but does not work on Label or node views.
Is there a way to get rotation on the axes of the views, panels or nodes?
 
Upvote 0

Daestrum

Well-Known Member
Licensed User
Uses JavaObject library small example

B4X:
Sub Process_Globals
 Private fx As JFX
 Private MainForm As Form
 Dim tf As TextField
 Dim rotate As JavaObject
 Dim point3D As JavaObject
End Sub
Sub AppStart (Form1 As Form, Args() As String)
 MainForm = Form1
 'MainForm.RootPane.LoadLayout("Layout1") 'Load the layout file.
 MainForm.Show
 tf.Initialize("") ' just a textField
 MainForm.RootPane.AddNode(tf,100,100,100,20) ' add to form
 
 ' 1.0,0.0,0.0, = x axis, 0.0,1.0,0.0 = y axis and 0.0,0.0,1.0 = z axis
 point3D = point3D.InitializeNewInstance("javafx.geometry.Point3D",Array(0.0,1.0,0.0))
 ' rotate 45degrees on axis defined above (y axis)
 rotate.InitializeNewInstance("javafx.scene.transform.Rotate",Array(45.0,point3D))
 ' transform the node/control
 asJO(tf).RunMethodJO("getTransforms",Null).RunMethod("add",Array(rotate))
End Sub
Sub asJO(o As JavaObject)As JavaObject
 Return o
End Sub
 
Upvote 0

Daestrum

Well-Known Member
Licensed User
Note on the above code
z axis any angle is ok
on x and y axis , angle 90, 180 and 270 will cause node to not show, as they have no thickness and you are looking end on.
 
Upvote 0

Star-Dust

Expert
Licensed User
Ok, I'll do the tests later.
Thank you
 
Upvote 0
Top