B4J Question Java3D on B4J Powerful Object Oriented 3D API, problem with JavaObject

max123

Active Member
Licensed User
Longtime User
Hi all,

this is a first attemp to make Java3D working on B4J using JavaObject.

This worked on pure Java and Jabaco that use directly java functions calls, with these I've managed it a lot and worked very well, but with B4J and JavaObject I cannot make it to work.

To start with... I've tried to port a simple demo project of a colored 3D cube that can be rotated with the mouse.
This on Jabaco works, but I cannot make it to work on B4J using JavaObject. Please what I do wrong here ?

Because Java3D works on top of Swing and AWT components I used a SwingNode to adapt it on JFX Form.
Because add directly the Canvas3D to the SwingNode seem not possible (it expets a JComponent), I used a JPanel with a BorderLayout set to the CENTER alignment, than put the Canvas3D inside it and then I add the JPanel to a SwingNode content, and finally to a JFX Form.

With the code I wrote, If I execute it in debug mode all objects seem to be fully initialized, I can see all Java3D properties changes,, no errors at all, but I cannot see the 3D View on the Form, the problem seem to be the JPanel and BorderLayouts? This is the only difference from Jabaco and B4J code, apart JavaObject use.

EDIT: Because this like to peoples, I attached more screenshots, even I prepared 3 executable jar files compiled with Jabaco so you can see yourself what Java3D can do, but I cannot post because the files are too big, about 3MB everyone, compress with 7zip do not help much here, jar files already are compressed.

Please, help solve the problem or I'm unable to port it to B4J platform.


----------------------
I know that now JavaFX has 3D classes similar to Java3D, but Java3D is a must, it is hightly documented on the web and there are billions of tutorials on it, it exist from a lots of years, it is high optimized and work very well on all platforms, some projects I developed with Java3D and Jabaco works very very well on all my Win PCs, Linux, on all Raspberry PIs, even on a small Raspberry Zero. By enabling OpenGL driver RPI support a full hardware optimization and Java3D can take GPU optimizations, just you need to increase in the config the memory assigned to a GPU.

I even know that Java3D now evolved on last years, see even JOGL, on Java3D starting from 1.7.0 version there is even a part of support for Android, but I prefer to use a relatively old version (1.5.2) because this is a version that is on Ubuntu and Raspberry repositories.

As explained I managed it but with pure Java and with Jabaco that by default use Swing components and even permits to access (directly) to Java classes without need of wrappers and use it in a VB6 syntax, very very similar to B4X, sometime when I port some works from Jabaco to B4X (or viceversa) I just copy/paste the code, then just adapt some small differences like between B4A and B4J or B4i.

I even managed to import 3D objects, by default Java3D have an OBJ (wavefont) and LW2 (lightwave) loaders, in Jabaco I wrote an STL (stereolito) and 3DS (3dsmax) loaders and now I can import models that generally I print with my 3D Printer and/or produced with a 3D CAD program. OBJ format even support .mtl files and can map textures on the model.
----------------------

At this time my goal is to port all my code to B4J so other users on this Forum can enjoy it.
Port the full Java3D is pretty impossible because it have a lots of classes, see here the documentation:
https://download.java.net/media/java3d/javadoc/1.5.2/
.... but my goal is just to start making a simple wrapper that exposes the basics classes to start with, then next I can improve it (even with users help).

Because the code is not too long but pretty simple, next I put a non working (in-progress) B4J code and working Jabaco counterpart, I even attach the B4J zip project and some screenshots of some my demo tests and my app written in Jabaco that show what you can do with this powerful 3D rendering engine that have a lots of class written and optimezed to accomplish what the developer need.

Note that in order to test it you need to install Java3D 1.5.2 on the system this is just a small JRE/JDK extension (do not use other versions or maybe it will not work), this just put these 3 jar files in the PATH, j3dcore.jar, j3dutils.jar, vecmath.jar, no other dependencies required, just about 5MB and you have working Java3D, so you can execute and develop with JDK.
With Windows I've found on the web the Java3D 1.5.2 installer that just put these 3 jar files in the right place and add a reference to the PATH .
With Linux you can try it, but maybe you need to place jar files manually in the right position, anyway if you use Raspberry PI I wrote an auto-installer and uninstaller bash script that do all the work automatically by download Java3D from repository, put the file in the right position and then add to the PATH. If you encounter problems please inform me.... these days when I've some time I will put it on github repository.

Many thanks to all.

B4J Not working code::
Sub Process_Globals
    Private fx As JFX
    Private MainForm As Form
 
    Private Universe As JavaObject
    Private Canvas3D As JavaObject
    Private Scene As JavaObject
    Private BranchGroup As JavaObject
    Private TransformGroup As JavaObject
    Private OrbitBehavior As JavaObject
  ' Private Trasform3D As JavaObject

    Private SwingNode As JavaObject  ' SWING NODE TO PUT A SWING CONTROL ON JFX FORM. ON THIS CODE WE USE A JPANEL COMPONENT
    Private jPanel As JavaObject
    Private BorderLayout As JavaObject

    Private ColorCube As JavaObject  ' Our colored cube
    Private Point3D As JavaObject

    Private Bounds As JavaObject
    'Private LightIsOff As Boolean = True
End Sub

Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    MainForm.Show
 
    Log("sun.awt.noerasebackground [before] write it: " & GetSystemProperty("sun.awt.noerasebackground", "false"))
    SetSystemProperty("sun.awt.noerasebackground", "true") ' Use this if you have problems while resize the 3D view
    Log("sun.awt.noerasebackground [after]  write it: " & GetSystemProperty("sun.awt.noerasebackground", "false"))
 
    Point3D.InitializeNewInstance("javax.vecmath.Point3d", Array (2.0, 0.0, 0.0))
    Bounds = Bounds.InitializeNewInstance("javax.media.j3d.BoundingSphere", Array (Point3D, 1000.0))
 
    SwingNode.InitializeNewInstance("javafx.embed.swing.SwingNode", Null)  ' Create a SwingNode
 
    ' We use a temp universe here, because we need to get PreferredConfiguration while initialize Canvas3D, this get
    ' the current configuration to get best performances as default using the SimpleUniverse class.
    ' We cannot call a costructor passing a Null parameter or Java3D will create a new form to put the 3D view inside.
    ' We need to call a costructor passing a Canvas3D as argument, so Java3D use it as a normal 2D B4J Canvas and
    ' can be placed as any other control inside a form, resized etc ...
    Dim u As JavaObject
    u.InitializeStatic("com.sun.j3d.utils.universe.SimpleUniverse")
 
    Dim Config As JavaObject = u.RunMethod("getPreferredConfiguration", Null)
    Canvas3D = Canvas3D.InitializeNewInstance("javax.media.j3d.Canvas3D", Array (Config))
 
    BorderLayout.InitializeNewInstance("java.awt.BorderLayout", Null) ' Create a BorderLayout to put the JPanel
    Dim Alignment As Object = BorderLayout.GetField("CENTER")' Get the CENTER field
    jPanel.InitializeNewInstance("javax.swing.JPanel", Null)  ' Create a JPanel
    jPanel.RunMethod("setLayout", Array (BorderLayout))  ' Set a BorderLayout on JPanel
'    jPanel.RunMethod("setBounds", Array (10, 10, 300, 300)) ' Resize the JPanel ???
    jPanel.RunMethod("add", Array (Canvas3D, Alignment))  ' Put the Canvas3D inside a JPanel with CENTER alignment
 
    '''''''' Change the panel back color just to test if it show on the form (REMOVE IT AFTER TESTS)
    Dim jCol As JavaObject
    jCol = jCol.InitializeStatic("java.awt.Color")
    Dim color As Object = jCol.GetField("RED")
    jPanel.RunMethod("setBackground", Array(color))
    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
 
    SwingNode.RunMethod("setContent", Array(jPanel)) ' Set JPanel as SwingNode content
 
    MainForm.RootPane.AddNode(SwingNode, 10, 10, 300, 300)  ' Finally we add the SwingNode to MainForm
 
    Scene.InitializeStatic("javax.media.j3d.BranchGroup")
    Scene = CreateSceneGraph  ' Create the scene graph containing all scene objects, in this case only a ColorCube
 
    Universe = Universe.InitializeNewInstance("com.sun.j3d.utils.universe.SimpleUniverse", Array (Canvas3D))
 
    Dim j1 As JavaObject = Universe.RunMethodJO("getViewingPlatform", Null)
    j1.RunMethod("setNominalViewingTransform", Null)
 
    Dim j2 As JavaObject = Universe.RunMethodJO("getViewer", Null)
    Dim j3 As JavaObject = j2.RunMethodJO("getView", Null)
    j3.RunMethod("setBackClipDistance", Array (100.0))
 
    Universe.RunMethod("addBranchGraph", Array(Scene))' Add the Scene to the Universe
 
    AddMouseOrbit
End Sub

'Return true to allow the default exceptions handler to handle the uncaught exception.
Sub Application_Error (Error As Exception, StackTrace As String) As Boolean
    Return True
End Sub

Sub MainForm_CloseRequest (EventData As Event)
    Log("MainForm_CloseRequest:    EventData: " & EventData)
    Universe.RunMethod("removeAllLocales", Null)
End Sub

Sub MainForm_Closed
    Log("MainForm_Closed")
End Sub

Sub MainForm_Resize (Width As Double, Height As Double)
    Dim W As Int = Width - 20
    Dim H As Int = Height - 40
    Log($"Form size: ${Width} X ${Height}    3D View bounds: 10, 10, ${W},${H}"$)
    Canvas3D.RunMethod("setBounds", Array (10, 10, W, H))
 
    Dim j1 As JavaObject
    Dim Rect As JavaObject = j1.InitializeNewInstance("java.awt.Rectangle",Null)
    Canvas3D.RunMethod("getBounds", Array(Rect))
    Dim rX As Int = Rect.RunMethod("getX", Null)
    Dim rY As Int = Rect.RunMethod("getY", Null)
    Dim rW As Int = Rect.RunMethod("getWidth", Null)
    Dim rH As Int = Rect.RunMethod("getHeight", Null)
    Log($"New bounds read from Canvas3D: ${rX}, ${rY}, ${rW}, ${rH}"$)
End Sub

Sub CreateSceneGraph As JavaObject
    Log("CreateSceneGraph")
 
    Dim objRoot As JavaObject = BranchGroup.InitializeNewInstance("javax.media.j3d.BranchGroup", Null)
    Dim tGroup As JavaObject = TransformGroup.InitializeNewInstance("javax.media.j3d.TransformGroup", Null)
 
    ColorCube.InitializeNewInstance("com.sun.j3d.utils.geometry.ColorCube", Array(0.30))
 
    tGroup.RunMethod("addChild", Array(ColorCube))
    objRoot.RunMethod("addChild", Array(tGroup))
    objRoot.RunMethod("compile", Null)
 
    Return objRoot
End Sub

Sub AddMouseOrbit 'As JavaObject
    Log("AddMouseOrbit")
 
    Dim tmp As JavaObject = OrbitBehavior.InitializeNewInstance("com.sun.j3d.utils.behaviors.vp.OrbitBehavior", Null)
    Dim Mode As Object = tmp.GetField("REVERSE_ALL")
 
    Dim Orbit As JavaObject = OrbitBehavior.InitializeNewInstance("com.sun.j3d.utils.behaviors.vp.OrbitBehavior", Array (Canvas3D, Mode))
    Orbit.RunMethod("setSchedulingBounds", Array(Bounds))
 
    Orbit.RunMethod("setRotFactors", Array(0.5, 0.5))
    Orbit.RunMethod("setTransFactors", Array(0.2, 0.2))
    Orbit.RunMethod("setZoomFactor", Array(0.2))
 
'    ' or separate for all axes ...
'    Orbit.RunMethod("setRotXFactor", Array(0.0))
'    Orbit.RunMethod("setRotYFactor", Array(0.05))
 
    Dim Center As JavaObject = Point3D.InitializeNewInstance("javax.vecmath.Point3d", Array(0.0, 0.0, 0.0))
    Orbit.RunMethod("setRotationCenter", Array(Center))
End Sub
Working Jabaco code that is a counterpart of working Java code::
Import com#sun#j3d#utils#universe#SimpleUniverse   ' We start from SimpleUniverse that create a default template

Import com#sun#j3d#utils#geometry#ColorCube  ' Import all geometies or just what you need

Import javax#media#j3d#*  ' Import all j3d classes, but you can import separately what you need
'Import javax#media#j3d#BranchGroup
'Import javax#media#j3d#Canvas3D
'Import javax#media#j3d#Alpha
'Import javax#media#j3d#RotationInterpolator
'Import javax#media#j3d#BoundingSphere
'Import javax#media#j3d#AmbientLight
'Import javax#media#j3d#DirectionalLight
'Import javax#media#j3d#Appearance
'Import javax#media#j3d#TransformGroup

'Import javax#vecmath#*  ' Import All vector and point mathematics
Import javax#vecmath#Point3d
Import com#sun#j3d#utils#behaviors#vp#OrbitBehavior

Dim Universe As SimpleUniverse
Dim Canvas As Canvas3D
Dim Bounds = New BoundingSphere(New Point3d(2.0,0.0,0.0), 1000.0)
'Dim LightIsOff As Boolean = True

Public Sub Form_Load()
   System.setProperty("sun.awt.noerasebackground", "true")  ' Use this if you have problems while resize the 3D view

'  ' Get the preferred graphics configuration for the default screen  '(This...)
'  Dim config As GraphicsConfiguration = SimpleUniverse.getPreferredConfiguration()
'  Canvas = New Canvas3D(config)  ' Create a Canvas3D using the preferred configuration
 
   ' Ceate an OpenGL 3D accelerated Canvas using the preferred graphics configuration for the default screen (... or this)
   Canvas = New Canvas3D(SimpleUniverse.getPreferredConfiguration)
 
   Me.add(Canvas)   ' Add the 3D canvas into the Form

   Dim Scene As BranchGroup = CreateSceneGraph()                 ' Create the root of the scene graph

   Universe = New SimpleUniverse(Canvas)                         ' Create a SimpleUniverse with the branch view
   Universe.getViewingPlatform().setNominalViewingTransform()    ' This will move the ViewPlatform back so the objects in the scene can be viewed
   Universe.getViewer().getView().setBackClipDistance(100.0)     ' Optional, set the render distance of objects
   Universe.addBranchGraph(Scene)
 
   AddMouseOrbit()
End Sub

Public Sub Form_Unload()
   Universe.removeAllLocales()
End Sub

Public Sub Form_Resize()
   Canvas.setBounds(10,10, Me.Width - 30, Me.Height - 60) ' We use a form Resize to set new Canvas size

   Dim rect As Rectangle = New Rectangle()
   Canvas.getBounds(rect)
   System.out.println(rect.getX & ", " & rect.getY & ", " & rect.getWidth & ", " & rect.getHeight)
End Sub

' Return a new scene graph as BranchGroup
Public Function CreateSceneGraph() As BranchGroup
 
   Dim objRoot As BranchGroup = New BranchGroup()                 ' Create the root of the branch graph
   Dim tGroup As TransformGroup = New TransformGroup()            ' Create a new Transform group
 
   tGroup.addChild(New ColorCube(0.30))  ' Add a new cube to the TransformGroup (ColorCube do not need Appearence
                                         ' to set it's material or color by dafault is preconfigured)
                         
   ' Here, if you add other primitives like a sphere, cone, cylinder etc. or your customs remember that these show White color,
   ' to apply a material or texture, you need to create an Appearance and pass to a constuctor or just using class methods like setAppearance.
   ' Remember even that you need to add one or more Lights to the scene or you can't see nothing (IMPORTANT).
   ' Java3D put any new object on the center of the scene, so you need to translate it.
 
   objRoot.addChild(tGroup)               ' Add the TransformGroup to the returning BranchGroup
 
   objRoot.compile                        ' Optional (but suggested), have Java 3D perform optimizations on this scene graph.

   CreateSceneGraph = objRoot
End Function

' Add OrbitBehavior
Private Sub AddMouseOrbit()
 
   Dim orbit As OrbitBehavior = New OrbitBehavior(Canvas, OrbitBehavior.REVERSE_ALL)
   orbit.setSchedulingBounds(Bounds)
 
     ' Mouse sensitivity by default 1.0 for all axis
      orbit.setRotFactors(0.5, 0.5)    ' Rotation sensitivity
      orbit.setTransFactors(0.2, 0.2)  ' Translate sensitivity
      orbit.setZoomFactor(0.2)         ' Zoom sensitivity
 
'      orbit.setRotXFactor(0)           ' Or separate for any axis
'      orbit.setRotYFactor(0.05)
'      orbit.setMinRadius(5)            ' Default 0.0

   orbit.setRotationCenter(New Point3d(0.0, 0.0, 0.0))   ' Optionally you can set the center of rotation for the camera, try to move it.
 
   Universe.getViewingPlatform().setViewPlatformBehavior(orbit)   ' Set it to the viewing platform
End Sub
 

Attachments

  • SwingNode_Java3D.zip
    2.7 KB · Views: 51
  • 2022-03-15 12_48_43-.png
    2022-03-15 12_48_43-.png
    71.2 KB · Views: 67
  • 2022-03-15 12_52_08-Jabaco - Java3D Examples - You can Resize or go to Full Screen.png
    2022-03-15 12_52_08-Jabaco - Java3D Examples - You can Resize or go to Full Screen.png
    286.2 KB · Views: 79
  • 2018-08-19 19_11_51-Greenshot.png
    2018-08-19 19_11_51-Greenshot.png
    492.4 KB · Views: 80
  • 2018-08-19 22_04_01-Greenshot.png
    2018-08-19 22_04_01-Greenshot.png
    189.1 KB · Views: 71
  • 2018-08-18 15_24_47-Greenshot.png
    2018-08-18 15_24_47-Greenshot.png
    206.9 KB · Views: 61
  • 2018-08-18 16_13_12-Greenshot.png
    2018-08-18 16_13_12-Greenshot.png
    252.5 KB · Views: 65
  • 2022-03-15 12_53_30-Jabaco - Java3D Examples - You can Resize or go to Full Screen.png
    2022-03-15 12_53_30-Jabaco - Java3D Examples - You can Resize or go to Full Screen.png
    184.7 KB · Views: 66
  • 36770253_1982587511751498_8681378221008093184_n.png
    36770253_1982587511751498_8681378221008093184_n.png
    503.6 KB · Views: 60
  • 36822055_1982588231751426_331040737552498688_n.png
    36822055_1982588231751426_331040737552498688_n.png
    254.1 KB · Views: 63
  • 2018-08-18 15_50_52-Greenshot.png
    2018-08-18 15_50_52-Greenshot.png
    464.6 KB · Views: 59
  • 36944784_1984999961510253_6248535257939705856_n.png
    36944784_1984999961510253_6248535257939705856_n.png
    190.5 KB · Views: 55
  • 37000394_1989946537682262_1240523551656640512_n.png
    37000394_1989946537682262_1240523551656640512_n.png
    337.3 KB · Views: 56
  • 37065058_1989946464348936_1785047197729947648_n.png
    37065058_1989946464348936_1785047197729947648_n.png
    294.8 KB · Views: 52
  • 37175677_1989943794349203_2220796772647698432_n.png
    37175677_1989943794349203_2220796772647698432_n.png
    187.5 KB · Views: 49
  • 2022-03-15 12_55_47-Jabaco - Java3D Examples - You can Resize or go to Full Screen.png
    2022-03-15 12_55_47-Jabaco - Java3D Examples - You can Resize or go to Full Screen.png
    179.4 KB · Views: 58
  • 2022-03-15 12_46_48-Use Left mouse to Rotate, Right mouse to Translate, mouse Whell to Zoom In...png
    2022-03-15 12_46_48-Use Left mouse to Rotate, Right mouse to Translate, mouse Whell to Zoom In...png
    17.2 KB · Views: 61
  • 2022-03-15 22_09_26-Greenshot.png
    2022-03-15 22_09_26-Greenshot.png
    275.7 KB · Views: 54
  • 2022-03-15 20_32_06-Greenshot.png
    2022-03-15 20_32_06-Greenshot.png
    363.7 KB · Views: 52
  • 2022-03-15 20_48_31-Greenshot.jpg
    2022-03-15 20_48_31-Greenshot.jpg
    164.2 KB · Views: 56
Last edited:

max123

Active Member
Licensed User
Longtime User
So no people interested to this, and can help ?
I'm here and cannot code it.

Many thanks
 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
B4J Not working code
Where is the full error you got? Should we guess it? I´m not interested to help as i am not interested in any 3D-Library at all.

But if you expect help you should start giving as much details as you can. This includes any full error too.
 
Upvote 0

max123

Active Member
Licensed User
Longtime User
Where is the full error you got? Should we guess it? I´m not interested to help as i am not interested in any 3D-Library at all.

But if you expect help you should start giving as much details as you can. This includes any full error too.
Dear @DonManfred , many thanks for your reply,

as I explained here I have no errors at all, just I see the Form but not the control:
With the code I wrote, If I execute it in debug mode all object seem to be fully initialized, I can see all Java3D properties changes,, no errors at all, but I cannot see the 3D View on the Form, the problem seem to be the JPanel and BorderLayouts? This is the only difference from Jabaco and B4J code, apart JavaObject use.

I've provided the full code in Text format with CODE Tag, even I provided a full B4J project in Zip format, I provided any explanation....

- Do you tried to copy/paste this code on a new B4J project and execute it ?
- Do you tried the B4J project I provided ?
- Do you really read all my Thread to ensure I do not explained well even if my language is not the english so write it required me about 2 hours ?

If yes then you are right, and please tell me what I need to change in my Thread, because I consider You an Expert I will do it.

This includes any full error too.
My Thread do not contain error log because I have no errors at all on the log, and the app do not crash, just do not show the control I place on the Form.

I´m not interested to help as i am not interested in any 3D-Library at all
If you do not interested to 3D things no one forced you to do this.
I think that any B4X user, expert or not expert, shouldn't help based on his interest, but based on B4X users interest.

Anyway IMHO from other peoples I expected this reply, but not from you. 😞

Many thanks
 
Last edited:
Upvote 0

max123

Active Member
Licensed User
Longtime User
Ok, because there are no users interested to help, and because I'm in a dead point, I abandon completely the project and continue to write my apps. 👍
 
Last edited:
Upvote 0

amorosik

Expert
Licensed User
Ue' ???
Wait a moment
From Tuesday to Wednesday it seems too short a time to understand if there are interested / volunteers to help in the project
I am really interested in getting the result shown by the screenshoots above
I don't know how to help, however, my current knowledge is not so deep as to carry out projects of this type
If I can help with docu conversions or tests or anything like that, let me know, but don't give up on a major project like this
Ciao
 
Upvote 0

JordiCP

Expert
Licensed User
Longtime User
Ue' ???
Wait a moment
From Tuesday to Wednesday it seems too short a time to understand if there are interested / volunteers to help in the project
I am really interested in getting the result shown by the screenshoots above
I don't know how to help, however, my current knowledge is not so deep as to carry out projects of this type
If I can help with docu conversions or tests or anything like that, let me know, but don't give up on a major project like this
Ciao
Agree. It looks really promising, don't abandon it.
Just yesterday evening I saw this post and decided to play a bit with it. However, since all this 3D library is totally new to me, can't contribute much without diving a bit which means time and it is a scarce resource that I don't have every day, as I'm sure it happens with most users.
Made some minor modifications related to when things were called, and in some cases I could see a small red-coloured area on the top-left of the form. Also once I got a gray rect covering the whole form.

my first guess is that the original code is initialized on an already initialized and sized panel, whilst here it is made before all of it is drawn, even if you handle the resize event.
Despite this, there seems to be a problem with dimensions taken from the parent view/panel.

 
Upvote 0

max123

Active Member
Licensed User
Longtime User
@amorosik and @JordiCP many thanks for interest, yes this is a big addon to B4J if it works, I can confirm, as explained Java3D is a very powerful library, I worked around with Java and Jabaco and I wrote some high level helpers to speed up the coding with it, simple, powerful, object oriented, no OpenGL acknowledge, note that I do not know at all OpenGL (I just know it zero x zero = 0), eg. on Jabaco now I manage something like this to create 3D:
B4X:
Dim Universe As Universe
Dim Group as BranchGroup
Dim Scene as Scene
Dim Sphere As Sphere
Dim Light1 As AmbientLight
Dim Light2 As DirectionalLight
Dim Appearance As Appearance
Dim Material As Material

Dim Radius As Float = 5.0
Dim Divisors As Integer = 20

'AMBIENT, EMISSIVE, DIFFUSE, SPECULAR, or AMBIENT_AND_DIFFUSE
'The Material object defines the appearance of an object under illumination.
Material = New Material(Color3f(1.0, 0.4, 0.6), Color3f(1.0, 0.4, 0.6), Color3f(1.0, 0.7, 0.6) , Color3f(1.3, 0.2, 0.5), Color3f(0.0, 0.4, 0.6))
Appearance = New Appareance(Material) 'If the Material object in an Appearance object is null, lighting is disabled for all nodes that use that Appearance object.
                                   
Universe.Initialize(Form1, 10, 10, 600, 500)

Group.Initialize

' Add some geometries, Sphere, Cone, Cylinder, Box, ColorCube etc... see com.sun.j3d.utils.geometry
' ... or a 3D model, OBJ, LW2, STL ...
Group.Add(Sphere(Radius, Divisors, Appearance))
Dim Box As Box = New Box(wx, wy, wh, Divisors, Appearance)
Group.Add(Box)
Box.Rotate(x, y, z)
Box.Translate(x, y, z)
.... or ....
Box.TranslateY(y)
Sphere.TranslateZ(z)
......

' Add some lights
Light1 = CreateAmbientLight(color, position, ....)
Group.Add(Light1)
Light2 = CreateDirectionalLight(color, position, ....)
Group.Add(Light2)

Scene.Add(Group)
Universe.Add(Scene)

Universe.AddMouseBehaviors()  ' to interact with mouse, zoom, translate, scale
Universe.AddKeyboardBehaviors()  ' to interact with keyboard, zoom, translate, scale
........
........
 
Last edited:
Upvote 0

Johan Schoeman

Expert
Licensed User
Longtime User
Upvote 0

max123

Active Member
Licensed User
Longtime User
@JordiCP, searching on rhe web I found that the SwingNode to adapt the Swing JComponent to a JFX Form, only support lightweight components like normal controls, buttons, textboxes, listboxes ecc..., for other components it cannot render, it has some problems with regular controls too, I tried to add a JButton to a JFX Form, it do not show, I see a black band that cover it, to see it I have to place the mouse on or move the form, this even happen in the code I've posted on first post, you says that sometime you see the red panel background, I too see it, but to see it I have to move a form with mouse. After this the control appear, the Ive placed 2 buttons on the form, one regular button (JFX) and a JButton, both have events and if I click the log show what button clicked.

So using the SwingNode is not the right way here with Canvas3D because it is not a lightweight control, for this Java3D expose a JCanvas3D class, see the documentation here at package com.sun.j3d.exp.swing:
https://download.java.net/media/java3d/javadoc/1.5.2/

Searching on the web I found other peoples had the same issues, then I found the JCanvas3D solution, this class convert a Canvas3D in a lightweight component so can be wrapped inside a SwingNode. Peoples using directly java had success to show the 3D view, the code on this post at bottom of the page:
https://stackoverflow.com/questions/45712785/how-to-embed-a-canvas3d-in-a-javafx-application

But other peoples had succes using directly a Canvas3D class wrapped inside a SwingNode, see here:
https://dzone.com/articles/how-do-i-use-java3d-javafx

So now I'm pretty confused if the right way is Canvas3D or JCanvas3D class.

Now I converted this java code to JavaObject, after some corrections on my code now it compile and executes without errors, now I see the black 3D canvas but the best I can archieve is to see a grey rectangle and a black rectangle inside it without a sphere I added to the scene.

This is my last test, I attach the code and a screenshot of result.
B4X:
#Region Project Attributes
    #MainFormWidth: 920
    #MainFormHeight: 720
#End Region

Sub Process_Globals
    Private fx As JFX
    Private MainForm As Form
    
    Private Universe As JavaObject
    Private Canvas3D As JavaObject
'    Private Scene As JavaObject
    Private BranchGroup As JavaObject
    Private TransformGroup As JavaObject
    Private OrbitBehavior As JavaObject
 
    Private VirtualUniverse As JavaObject
    Private Locale As JavaObject
    Private ViewPlatform As JavaObject
    Private JCanvas3D As JavaObject
    Private GraphicsConfigTemplate3D As JavaObject
    Private Transform3D As JavaObject
    Private TransformGroup As JavaObject
    Private DirectionalLight As JavaObject
 
    Private Point3d As JavaObject
'    Private Point3f As JavaObject
    Private Vector3d As JavaObject
    Private Vector3f As JavaObject
    Private Color3f As JavaObject
 
    Private j3dView As JavaObject
    Private j3dPhysicalBody As JavaObject
    Private j3dPhysicalEnvironment As JavaObject
 
    Private SwingNode As JavaObject  ' SWING NODE TO PUT A SWING CONTROL ON JFX FORM. ON THIS CODE WE USE A JPANEL COMPONENT
    Private jPanel As JavaObject
    Private BorderLayout As JavaObject

    ' Geometries
    Private ColorCube As JavaObject  ' Our colored cube
    Private Sphere As JavaObject

    Private Bounds As JavaObject
    Private BoundingSphere As JavaObject
 
    'Private LightIsOff As Boolean = True
 
    Private Dimension As JavaObject
End Sub

Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    MainForm.Show
 
    Dim LibPath As String = GetSystemProperty("java.library.path", "")
    Log("Java library path: " & LibPath)
    Dim LibPathes() As String = Regex.Split(";", LibPath)
    For Each s As String In LibPathes
        Log("On java.library.path: " & s)
    Next
 
    Log("sun.awt.noerasebackground [before] write it: " & GetSystemProperty("sun.awt.noerasebackground", "false"))
    SetSystemProperty("sun.awt.noerasebackground", "true") ' Use this if you have problems while resize the 3D view
    Log("sun.awt.noerasebackground [after]  write it: " & GetSystemProperty("sun.awt.noerasebackground", "false"))
 
    SwingNode.InitializeNewInstance("javafx.embed.swing.SwingNode", Null)  ' Create a SwingNode
 
    BorderLayout.InitializeNewInstance("java.awt.BorderLayout", Null) ' Create a BorderLayout to put the JPanel
 
    jPanel.InitializeNewInstance("javax.swing.JPanel", Null)  ' Create a JPanel
    jPanel.RunMethod("setLayout", Array (BorderLayout))  ' Set a BorderLayout on JPanel
 
    Dimension.InitializeNewInstance("java.awt.Dimension", Array(900, 700))
    jPanel.RunMethod("setPreferredSize", Array(Dimension))
'
'    Dim component As JavaObject
'    component.InitializeStatic("java.awt.Component")
'    component = MakeCanvas
 
'    jp1.InitializeNewInstance("javax.swing.JPanel", Null)  ' Create a JPanel
'    jp1 = MakeCanvas
'    jp1.RunMethod("setLayout", Array (BorderLayout))  ' Set a BorderLayout on JPanel
''    Dimension.InitializeNewInstance("java.awt.Dimension", Array(900, 700))
'    jp1.RunMethod("setPreferredSize", Array(Dimension))
    
    Dim Alignment As Object = BorderLayout.GetField("CENTER")' Get the CENTER field
    jPanel.RunMethod("add", Array (MakeCanvas, Alignment))  ' Put the Canvas3D inside a JPanel with CENTER alignment
 
    SwingNode.RunMethod("setContent", Array(jPanel)) ' Set JPanel as SwingNode content
 
    MainForm.RootPane.AddNode(SwingNode, 10, 10, 900, 680)  ' Finally we add the SwingNode to MainForm
End Sub

'Return true to allow the default exceptions handler to handle the uncaught exception.
Sub Application_Error (Error As Exception, StackTrace As String) As Boolean
    Return True
End Sub

Sub MainForm_Resize (Width As Double, Height As Double)
    Dim W As Int = Width - 20
    Dim H As Int = Height - 40
    Log($"Form size: ${Width} X ${Height}    3D View bounds: 10, 10, ${W},${H}"$)
    Canvas3D.RunMethod("setBounds", Array (10, 10, W, H))
 
    Dim j1 As JavaObject
    Dim Rect As JavaObject = j1.InitializeNewInstance("java.awt.Rectangle",Null)
    Canvas3D.RunMethod("getBounds", Array(Rect))
    Dim rX As Int = Rect.RunMethod("getX", Null)
    Dim rY As Int = Rect.RunMethod("getY", Null)
    Dim rW As Int = Rect.RunMethod("getWidth", Null)
    Dim rH As Int = Rect.RunMethod("getHeight", Null)
    Log($"New bounds read from Canvas3D: ${rX}, ${rY}, ${rW}, ${rH}"$)
End Sub

Sub MakeCanvas As JavaObject
    Log("MakeCanvas")
 
    GraphicsConfigTemplate3D.InitializeNewInstance("javax.media.j3d.GraphicsConfigTemplate3D", Null)
    JCanvas3D.InitializeNewInstance("com.sun.j3d.exp.swing.JCanvas3D", Array (GraphicsConfigTemplate3D))

'    Dim canvasDim AS JavaObject = Dimension.InitializeNewInstance("java.awt.Dimension", Array(900, 700))
    Dimension.InitializeNewInstance("java.awt.Dimension", Array(500, 500))
    JCanvas3D.RunMethod("setPreferredSize", Array (Dimension))
    JCanvas3D.RunMethod("setSize", Array (Dimension))

    BorderLayout.InitializeNewInstance("java.awt.BorderLayout", Null) ' Create a BorderLayout to put the JPanel
 
    Dim jp1 As JavaObject
    jp1.InitializeNewInstance("javax.swing.JPanel", Null)  ' Create a JPanel
    '''    jPanel.RunMethod("setLayout", Array (BorderLayout))  ' Set a BorderLayout on JPanel
    '''    '    jPanel.RunMethod("setBounds", Array (10, 10, 300, 300)) ' Resize the JPanel ???
    '''    jPanel.RunMethod("add", Array (Canvas3D, Alignment))  ' Put the Canvas3D inside a JPanel with CENTER alignment
    Dim Alignment As Object = BorderLayout.GetField("CENTER")' Get the CENTER field
    jp1.RunMethod("add", Array (JCanvas3D, Alignment))

    ' I've added this because sometime Java3D fails to initialize the 3D engine, not sure
    ' if it is necessary or need to be fixed other ways, I've found that the fail depends
    ' on JCanvas3D size, 500x500 works, bigger fails, this not good, with normal Canvas3D
    ' it can go up 1920x1200 without problems at all.
    Dim jo1  As JavaObject
    jo1.InitializeStatic("sun.awt.AppContext")
    Dim context As Object = jo1.RunMethod("getAppContext", Null)
    If context = Null Then
        Dim newcontext As JavaObject
        newcontext.InitializeStatic("sun.awt.SunToolkit")
        newcontext.RunMethod("createNewAppContext", Null)
    End If
    '''''''''''''''
    Canvas3D = JCanvas3D.RunMethod("getOffscreenCanvas3D", Null)
 
    j3dView.InitializeNewInstance("javax.media.j3d.View", Null)
    j3dPhysicalBody.InitializeNewInstance("javax.media.j3d.PhysicalBody", Null)
    j3dPhysicalEnvironment.InitializeNewInstance("javax.media.j3d.PhysicalEnvironment", Null)

    j3dView.RunMethod("setPhysicalBody", Array (j3dPhysicalBody))
    j3dView.RunMethod("setPhysicalEnvironment", Array (j3dPhysicalEnvironment))
    j3dView.RunMethod("addCanvas3D", Array (Canvas3D))
 
    Dim vp As JavaObject = ViewPlatform.InitializeNewInstance("javax.media.j3d.ViewPlatform", Null)
    j3dView.RunMethod("attachViewPlatform", Array (ViewPlatform))
 
    Dim viewTransform As JavaObject = Transform3D.InitializeNewInstance("javax.media.j3d.Transform3D", Null)
    Vector3d.InitializeNewInstance("javax.vecmath.Vector3d", Array (0.0, 0.0, 20.0)) ' Move "back" a little
    viewTransform.RunMethod("setTranslation", Array (Vector3d))
 
    Dim viewTG As JavaObject = TransformGroup.InitializeNewInstance("javax.media.j3d.TransformGroup", Null)
    Dim Capability As Object = viewTG.GetField("ALLOW_TRANSFORM_WRITE")
    viewTG.RunMethod("setCapability", Array (Capability))
    viewTG.RunMethod("setTransform", Array (viewTransform))
 
    viewTG.RunMethod("addChild", Array (vp))
 
    ' Add light
    Dim light As JavaObject = MakeLight
    viewTG.RunMethod("addChild", Array (light))
 
    ' Add a sphere shape
    Dim radius As Float = 5.0
    Dim sph As JavaObject = Sphere.InitializeNewInstance("com.sun.j3d.utils.geometry.Sphere", Array (radius))
    viewTG.RunMethod("addChild", Array (sph))
 
    Dim group As JavaObject = BranchGroup.InitializeNewInstance("javax.media.j3d.BranchGroup", Null)
    group.RunMethod("addChild", Array (viewTG))
'    group.RunMethod("addChild", Array (Light))   ' From original java code this seem not right, we already added lights to the group
'    group.RunMethod("addChild", Array (Sphere))  ' From original java code this seem not right, we already added a sphere to the group
 
    Dim vu As JavaObject = VirtualUniverse.InitializeNewInstance("javax.media.j3d.VirtualUniverse", Null)
    Dim loc As JavaObject = Locale.InitializeNewInstance("javax.media.j3d.Locale", Array(vu))
    loc.RunMethod("addBranchGraph", Array (group))
 
    Return jp1
End Sub

Sub MakeLight As JavaObject
    Dim jCol As JavaObject
    jCol.InitializeStatic("java.awt.Color")
    Dim awtColor As Object = jCol.GetField("WHITE")  ' RED
 
    Dim color As JavaObject = Color3f.InitializeNewInstance("javax.vecmath.Color3f", Array(awtColor))
    Dim x As Float = -1.0
    Dim y As Float = -1.0
    Dim z As Float = -1.0
    Dim position  As JavaObject = Vector3f.InitializeNewInstance("javax.vecmath.Vector3f", Array(x, y, z))
    Dim light As JavaObject = DirectionalLight.InitializeNewInstance("javax.media.j3d.DirectionalLight", Array(color, position))
 
    Dim BSpherePos As JavaObject = Point3d.InitializeNewInstance("javax.vecmath.Point3d", Array(0.0, 0.0, 0.0))
    Dim BSphere As JavaObject = BoundingSphere.InitializeNewInstance("javax.media.j3d.BoundingSphere", Array(BSpherePos, 100.0))
    light.RunMethod("setInfluencingBounds", Array (BSphere))
 
    Return light
End Sub

And Yes, something in panels resize is wrong, when I resize the Form it do not resize the 3D canvas.

Many thanks for your interest
Have a good day
Massimo
 

Attachments

  • Screen Shot 03-17-22 at 05.34 PM.PNG
    Screen Shot 03-17-22 at 05.34 PM.PNG
    32.7 KB · Views: 48
Last edited:
Upvote 0

max123

Active Member
Licensed User
Longtime User
Hi @Johan Schoeman , using inline java I can copy/paste java code, this securely is the way I can do it on FASE2 if I pass this first step to show the control correctly. But if this do not work in some days I no longer continue to develop it.

Inline Java can help yes, but debug on it is a big problem in Debug mode. To start with I think it is better to use JavaObject, then convert to inline java.

Many thanks for your interest
Have a good day
Massimo
 
Last edited:
Upvote 0
Top