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 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.
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 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.zip2.7 KB · Views: 271
-
2022-03-15 12_48_43-.png71.2 KB · Views: 262
-
2022-03-15 12_52_08-Jabaco - Java3D Examples - You can Resize or go to Full Screen.png286.2 KB · Views: 301
-
2018-08-19 19_11_51-Greenshot.png492.4 KB · Views: 300
-
2018-08-19 22_04_01-Greenshot.png189.1 KB · Views: 268
-
2018-08-18 15_24_47-Greenshot.png206.9 KB · Views: 264
-
2018-08-18 16_13_12-Greenshot.png252.5 KB · Views: 275
-
2022-03-15 12_53_30-Jabaco - Java3D Examples - You can Resize or go to Full Screen.png184.7 KB · Views: 288
-
36770253_1982587511751498_8681378221008093184_n.png503.6 KB · Views: 269
-
36822055_1982588231751426_331040737552498688_n.png254.1 KB · Views: 277
-
2018-08-18 15_50_52-Greenshot.png464.6 KB · Views: 257
-
36944784_1984999961510253_6248535257939705856_n.png190.5 KB · Views: 242
-
37000394_1989946537682262_1240523551656640512_n.png337.3 KB · Views: 245
-
37065058_1989946464348936_1785047197729947648_n.png294.8 KB · Views: 262
-
37175677_1989943794349203_2220796772647698432_n.png187.5 KB · Views: 236
-
2022-03-15 12_55_47-Jabaco - Java3D Examples - You can Resize or go to Full Screen.png179.4 KB · Views: 337
-
2022-03-15 12_46_48-Use Left mouse to Rotate, Right mouse to Translate, mouse Whell to Zoom In...png17.2 KB · Views: 269
-
2022-03-15 22_09_26-Greenshot.png275.7 KB · Views: 282
-
2022-03-15 20_32_06-Greenshot.png363.7 KB · Views: 270
-
2022-03-15 20_48_31-Greenshot.jpg164.2 KB · Views: 268
Last edited: