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

max123

Well-Known 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: 164
  • 2022-03-15 12_48_43-.png
    2022-03-15 12_48_43-.png
    71.2 KB · Views: 182
  • 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: 217
  • 2018-08-19 19_11_51-Greenshot.png
    2018-08-19 19_11_51-Greenshot.png
    492.4 KB · Views: 200
  • 2018-08-19 22_04_01-Greenshot.png
    2018-08-19 22_04_01-Greenshot.png
    189.1 KB · Views: 185
  • 2018-08-18 15_24_47-Greenshot.png
    2018-08-18 15_24_47-Greenshot.png
    206.9 KB · Views: 172
  • 2018-08-18 16_13_12-Greenshot.png
    2018-08-18 16_13_12-Greenshot.png
    252.5 KB · Views: 178
  • 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: 187
  • 36770253_1982587511751498_8681378221008093184_n.png
    36770253_1982587511751498_8681378221008093184_n.png
    503.6 KB · Views: 173
  • 36822055_1982588231751426_331040737552498688_n.png
    36822055_1982588231751426_331040737552498688_n.png
    254.1 KB · Views: 172
  • 2018-08-18 15_50_52-Greenshot.png
    2018-08-18 15_50_52-Greenshot.png
    464.6 KB · Views: 154
  • 36944784_1984999961510253_6248535257939705856_n.png
    36944784_1984999961510253_6248535257939705856_n.png
    190.5 KB · Views: 150
  • 37000394_1989946537682262_1240523551656640512_n.png
    37000394_1989946537682262_1240523551656640512_n.png
    337.3 KB · Views: 155
  • 37065058_1989946464348936_1785047197729947648_n.png
    37065058_1989946464348936_1785047197729947648_n.png
    294.8 KB · Views: 159
  • 37175677_1989943794349203_2220796772647698432_n.png
    37175677_1989943794349203_2220796772647698432_n.png
    187.5 KB · Views: 148
  • 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: 201
  • 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: 175
  • 2022-03-15 22_09_26-Greenshot.png
    2022-03-15 22_09_26-Greenshot.png
    275.7 KB · Views: 159
  • 2022-03-15 20_32_06-Greenshot.png
    2022-03-15 20_32_06-Greenshot.png
    363.7 KB · Views: 163
  • 2022-03-15 20_48_31-Greenshot.jpg
    2022-03-15 20_48_31-Greenshot.jpg
    164.2 KB · Views: 179
Last edited:

max123

Well-Known Member
Licensed User
Longtime User
WOW @Johan Schoeman, this works !!!

As you read in the link you posted, the user needed to call swingNode.setContent in a runnable more times before it render, I suppose this is an issue too on my code, I call it one time.

Anyway, now I will study your code and post here results.

Many Many Thanks
 
Last edited:
Upvote 0

max123

Well-Known Member
Licensed User
Longtime User
I do not know this line on B4J code, I know it add a node to a panel, but I do not know the position and size.
B4X:
Pane1.AddNode(bb, Pane1.Width * 0.025, Pane1.Height * 0.025, Pane1.Width * 0.95, Pane1.Height * 0.95)
You center it manually the StackPane inside Pane1 ?
 
Upvote 0

Johan Schoeman

Expert
Licensed User
Longtime User
Go to designer and change the color of the Panel to for eg Cyan. Run the project again and you will see how "bb" is positioned in the pane (2.5% of Panel1's width from the left and right, and filling 95% of the width and height of Pane1)
 
Upvote 0

max123

Well-Known Member
Licensed User
Longtime User
Yes, tried this to test and know and now I know it, you center it....
B4X:
Pane1.AddNode(bb, 10, 10, Pane1.Width-20, Pane1.Height-20)
I'm here now with JavaFX SceneBuilder 2.0 to better understand a StackPane, I never used it.

I suppose I can replace it in the java code with a normal Pane or AnchorPane ?
 
Last edited:
Upvote 0

max123

Well-Known Member
Licensed User
Longtime User
Thanks to @Johan Schoeman I've managed it to work, now it is possible set the jCanvas3D size directly from B4J this way:
B4X:
Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    MainForm.RootPane.LoadLayout("Layout1")
    MainForm.Show
 
    NativeMe = Me
    Log(NativeMe)
 
'    Pane1.AddNode(bb, Pane1.Width * 0.025, Pane1.Height * 0.025, Pane1.Width * 0.95, Pane1.Height * 0.95)
'    Pane1.AddNode(bb, 10, 10, Pane1.Width-20, Pane1.Height-20)
 
    ' Construct a 3D view of 900x720 pixels at 10,10 inside Pane1 added by designer
    Pane1.AddNode(NativeMe.RunMethod("GetCanvas3D", Array(900, 720)), 10, 10, Pane1.Width, Pane1.Height)
End Sub

This code show a 3D color cube that is possible rotate with mouse.
I've tried to wrap the 3D canvas inside a StackPane, then inside an AnchorPane and finally I've decided to use just a Pane.

I would load an .obj 3D model file, I have the elephant.obj file but the compiler says that cannot find it, here's the log;
(Class) class b4j.example.main
STARTING
IN RUN ...
IN TRY ...
Creating SwingNode content: Size: 900x720
//// DONE ////
JCanvas3DPanel CONSTRUCTOR
IN MAKE CANVAS
InternalWorld: createSceneGraph: isInteractive: true
java.io.FileNotFoundException: elephant.obj (Impossibile trovare il file specificato)
at java.base/java.io.FileInputStream.open0(Native Method)
at java.base/java.io.FileInputStream.open(FileInputStream.java:219)
at java.base/java.io.FileInputStream.<init>(FileInputStream.java:157)
at java.base/java.io.FileInputStream.<init>(FileInputStream.java:112)
at java.base/java.io.FileReader.<init>(FileReader.java:60)
at b4j.example.main$JCanvas3DPanel.makeModel(main.java:295)
at b4j.example.main$JCanvas3DPanel.CreateSceneGraph(main.java:387)
at b4j.example.main$JCanvas3DPanel.makeCanvas(main.java:277)
at b4j.example.main$JCanvas3DPanel.<init>(main.java:264)
at b4j.example.main$1.run(main.java:250)
at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:313)
at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:770)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:721)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:715)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:740)
at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
AMBIENT LIGHT
DIRECTIONAL LIGHT 1
DIRECTIONAL LIGHT 2
Is not clear to me how put the elephant.obj model, I've put it on Files folder and B4J do not find it, I've put it on the main folder of the project and it do not find.

I've attached the full project, can someone test it to know where put the 3D model file ?

Thanks

EDIT: OOOOK I found the solution, 3D model file should be in the Objects folder where a Jar file is.
After that I can see the elephant.obj in a 3D view. Now I will manage to rotate it with mouse or keyboard or B4J controls, eg. a slider.
 

Attachments

  • j3d-InlineJava-SwingNode-obj.zip
    195.9 KB · Views: 64
  • Screen Shot 12-15-22 at 02.06 PM.PNG
    Screen Shot 12-15-22 at 02.06 PM.PNG
    18 KB · Views: 62
Last edited:
Upvote 0

Johan Schoeman

Expert
Licensed User
Longtime User
Thanks to @Johan Schoeman I've managed it to work, now it is possible set the jCanvas3D size directly from B4J this way:
B4X:
Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    MainForm.RootPane.LoadLayout("Layout1")
    MainForm.Show
 
    NativeMe = Me
    Log(NativeMe)
 
'    Pane1.AddNode(bb, Pane1.Width * 0.025, Pane1.Height * 0.025, Pane1.Width * 0.95, Pane1.Height * 0.95)
'    Pane1.AddNode(bb, 10, 10, Pane1.Width-20, Pane1.Height-20)
 
    ' Construct a 3D view of 900x720 pixels at 10,10 inside Pane1 added by designer
    Pane1.AddNode(NativeMe.RunMethod("GetCanvas3D", Array(900, 720)), 10, 10, Pane1.Width, Pane1.Height)
End Sub

This code show a 3D color cube that is possible rotate with mouse.
I've tried to wrap the 3D canvas inside a StackPane, then inside an AnchorPane and finally I've decided to use just a Pane.

I would load an .obj 3D model file, I have the elephant.obj file but the compiler says that cannot find it, here's the log;

Is not clear to me how put the elephant.obj model, I've put it on Files folder and B4J do not find it, I've put it on the main folder of the project and it do not find.

I've attached the full project, can someone test it to know where put the 3D model file ?

Thanks

EDIT: OOOOK I found the solution myself, 3D model file should be in the Objects folder where a Jar file is.
After that I can see the elephant.obj in a 3D view. Now I will manage to rotate it with mouse or keyboard or B4J controls, ed a slider.
Well done @max123 !

1671117642230.png
 
Upvote 0

max123

Well-Known Member
Licensed User
Longtime User
Yes, @Johan Schoeman, it works now, try the attached project.

Try to rotate the elephant with mouse.....

Note that jCanvas3D seem to use a software rendering, I'm not sure but on my fast PC it works fast, on my old PC with Win XP if I set small 3D window it works fast, when I increase the size or set fullscreen it slow down a bit and the CPU is 100%, but note that this is an AMD singlecore PC with 1GB ram. On AMD Ryzen7 I cannot see it slow down even when I rotate a 3D view in fullscreen on a 24 inch LCD screen. But need to see it when add more to the 3D scene....

Using jCanvas3D vs Canvas3D need a precisation, using Canvas3D I always used OrbitBehavior, this class permits to:
- Rotate a view hold down mouse Left button
- Zoom-in and Zoom-out a view with mouse wheel
- Translate a view hold down mouse Right button

Is even possible by code to set a rotation XYZ center (the pivot) where object or mesh rotate around.

With this class and just some lines of code, it even permits to set the resolution indipendent for Rotation, Zoom, Translation. See here:

I've read that jCanvas3D do not support it, in the attached project I've used MouseRotate that just rotate.

Here the OrbitBehavior class:
https://download.java.net/media/jav...sun/j3d/utils/behaviors/vp/OrbitBehavior.html

I searched on the web and found a class that add OrbitControl to jCanvas3D (custom OrbitBehaviorJCanvas3D class)
I've tried it but seem do no work, I can see the 3D view and object but I cannot rotate, not zoom, not translate, something is wrong but mous wheel is recognized on the 3D view.

I've ttached a full Eclipse project, I need to solve it or this option cannot be used and currently is not possible to zoom or translate a 3D world with mouse.
 

Attachments

  • j3d-InlineJava-SwingNode-obj.zip
    6.3 KB · Views: 65
  • Java3D_JCanvas3DExample.zip
    38.2 KB · Views: 69
Last edited:
Upvote 0
Top