B4J Tutorial Fxyz3d - samples

It is a sample project for this Github posting - using fxyz3d (have added it via inline Java code in a B4J class and then added some setters to the class.

Download fxyz3d-0.5.4 from the web and add it to your B4J additional libs folder.

Move the sliders left/right to see the change of the SurfacePlotMesh when changing the values of a, b, c, m, n


1672401491201.png
 

Attachments

  • MathVis.zip
    4.1 KB · Views: 274
Last edited:

Johan Schoeman

Expert
Licensed User
Longtime User
A SpringMesh making use of inline Java code. Have added some setters to be able to change the appearance via the Sliders. You can also move it around with your mouse. Change it to your liking....

Code of class Main:
B4J - Main:
#Region Project Attributes
    #MainFormWidth: 1200
    #MainFormHeight: 800
#End Region

#AdditionalJar: fxyz3d-0.5.4


Sub Process_Globals
    Private fx As JFX
    Private MainForm As Form
    Private xui As XUI
    Private Pane1 As Pane
   
    Dim mc As mycalss
    Dim bb As JavaObject
   
    Private Slider1 As Slider
    Private Slider2 As Slider
    Private Slider3 As Slider
    Private Slider4 As Slider
    Private Slider5 As Slider

    Private Slider6 As Slider
End Sub

Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    MainForm.RootPane.LoadLayout("Layout1")
    MainForm.Show
   
    Sleep(0)
   
    mc.Initialize

    bb = mc.makethecube(MainForm.Width, MainForm.Height)
   
    Pane1.AddNode(bb, 0, 0, -1, -1)

End Sub

Private Sub Slider1_ValueChange (Value As Double)
   
    mc.DefaultMeanRadius = Value
   
End Sub

Private Sub Slider2_ValueChange (Value As Double)
   
    mc.WireRadius = Value
   
End Sub

Private Sub Slider3_ValueChange (Value As Double)
   
    mc.Pitch = Value
   
End Sub

Private Sub Slider4_ValueChange (Value As Double)
   
    mc.Length = Value
   
End Sub

Private Sub Slider5_ValueChange (Value As Double)
   
    mc.LengthDivisions = Value
   
End Sub


Private Sub Slider6_ValueChange (Value As Double)
   
    mc.WireDivisions = Value
   
End Sub


Code of "myclass":

B4J - myclass:
Sub Class_Globals
   
    Private fx As JFX
    Dim nativeMe As JavaObject
   
End Sub

'Initializes the object. You can add parameters to this method if needed.
Public Sub Initialize
   
    nativeMe = Me

End Sub

public Sub makethecube (wdth As Int, hght As Int) As JavaObject
   
    Return nativeMe.RunMethod("start1", Array(wdth, hght))
   
End Sub

public Sub setDefaultMeanRadius (value As Double)
   
    nativeMe.RunMethod("setDefaultMeanRadius", Array(value))
   
End Sub

public Sub setWireRadius (value As Double)
   
    nativeMe.RunMethod("setWireRadius", Array(value))
   
End Sub

public Sub setPitch (value As Double)
   
    nativeMe.RunMethod("setPitch", Array(value))
   
End Sub

public Sub setLength (value As Double)
   
    nativeMe.RunMethod("setLength", Array(value))
   
End Sub

public Sub setLengthDivisions (value As Int)
   
    nativeMe.RunMethod("setLengthDivisions", Array(value))
   
End Sub

public Sub setWireDivisions (value As Int)
   
    nativeMe.RunMethod("setWireDivisions", Array(value))
   
End Sub




#if Java

import java.util.function.BiFunction;
import java.util.function.Function;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.geometry.Point2D;
import javafx.scene.Group;
import javafx.scene.PerspectiveCamera;
import javafx.scene.PointLight;
import javafx.scene.Scene;
import javafx.scene.SubScene;
import javafx.scene.SceneAntialiasing;
import javafx.scene.paint.Color;
import javafx.scene.shape.CullFace;
import javafx.scene.transform.Rotate;
import javafx.stage.Stage;
import javafx.util.Duration;
import org.fxyz3d.scene.paint.Patterns.CarbonPatterns;
import org.fxyz3d.shapes.primitives.SurfacePlotMesh;
import org.fxyz3d.utils.CameraTransformer;
import org.fxyz3d.shapes.primitives.SpringMesh;

import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.scene.Camera;
import javafx.scene.Group;
import javafx.scene.PerspectiveCamera;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.Box;
import javafx.scene.transform.Rotate;
import javafx.geometry.Point3D;
import javafx.scene.transform.Affine;


    XformBox cameraXform = new XformBox();
    XformBox ballXForm = new XformBox();

    private double time = 0;
    PerspectiveCamera camera;
    SubScene scene;
    Group group;
    SpringMesh spring;

    private double anchorX, anchorY;
    private double anchorAngleX = 0;
    private double anchorAngleY = 0;
    private DoubleProperty angleX = new SimpleDoubleProperty(0);
    private DoubleProperty angleY = new SimpleDoubleProperty(0);


    private double DEFAULT_MEAN_RADIUS = 10.0D;
    private double DEFAULT_WIRE_RADIUS = 0.2D;
    private double DEFAULT_PITCH = 5.0D;
    private double DEFAULT_LENGTH = 100.0D;
   
    private int DEFAULT_LENGTH_DIVISIONS = 200;
    private int DEFAULT_WIRE_DIVISIONS = 50;
    private int DEFAULT_LENGTH_CROP = 0;
    private int DEFAULT_WIRE_CROP = 0;
   
    private double DEFAULT_START_ANGLE = 0.0D;
    private double DEFAULT_X_OFFSET = 0.0D;
    private double DEFAULT_Y_OFFSET = 0.0D;
    private double DEFAULT_Z_OFFSET = 1.0D;
   
   
   
    private static double CAMERA_INITIAL_DISTANCE = -450;
    private static double CAMERA_INITIAL_X_ANGLE = -10.0;
    private static double CAMERA_INITIAL_Y_ANGLE = 0.0;
    private static double CAMERA_NEAR_CLIP = 0.1;
    private static double CAMERA_FAR_CLIP = 10000.0;
    private static double AXIS_LENGTH = 250.0;
    private static double MOUSE_SPEED = 0.1;
    private static double ROTATION_SPEED = 2.0;
   
   
   
    double mouseStartPosX, mouseStartPosY;
    double mousePosX, mousePosY;
    double mouseOldX, mouseOldY;
    double mouseDeltaX, mouseDeltaY;  
    int wdth = 400;
    int hght = 400;


    public void setDefaultMeanRadius(double meanRadius) {
        spring.setMeanRadius(meanRadius);
    }
   
    public void setWireRadius(double wireRadius) {
        spring.setWireRadius(wireRadius);
    }    

    public void setPitch(double pitch) {
        spring.setPitch(pitch);
    }
   
    public void setLength(double length) {
        spring.setLength(length);
    }
   
    public void setLengthDivisions(int rDivs) {
        spring.setLengthDivisions(rDivs);
    }        
   
    public void setWireDivisions(int tDivs) {
        spring.setWireDivisions(tDivs);
    }        

    public SubScene start1(int wdth, int hght) {
        this.wdth = wdth;
        this.hght = hght;
        camera = new PerspectiveCamera(true);      
        camera.setNearClip(0.1);
        camera.setFarClip(10000.0);
        camera.setTranslateX(10);
        camera.setTranslateZ(-100);
        camera.setFieldOfView(40);
       
        CameraTransformer cameraTransform = new CameraTransformer();
        cameraTransform.getChildren().add(camera);
        cameraTransform.ry.setAngle(-10.0);
        cameraTransform.rx.setAngle(-15.0);
       

       
       spring = new SpringMesh(DEFAULT_MEAN_RADIUS, DEFAULT_WIRE_RADIUS, DEFAULT_PITCH, DEFAULT_LENGTH, DEFAULT_LENGTH_DIVISIONS, DEFAULT_WIRE_DIVISIONS, DEFAULT_LENGTH_CROP, DEFAULT_WIRE_CROP);

//     SpringMesh spring = new SpringMesh(10, 2, 2, 8 * 2 * Math.PI, 200, 100, 0, 0);

        spring.setCullFace(CullFace.NONE);
        spring.setTextureModeVertices3D(1530, p -> p.f);
 
 
        ballXForm.getChildren().add(spring);
     
        group = new Group(cameraTransform, ballXForm);
       
        scene = new SubScene(group, wdth, hght, true, SceneAntialiasing.BALANCED);
        scene.setFill(Color.TRANSPARENT);
        scene.setCamera(camera);
        initMouseControl();
       
       
        return scene;
    }
   
   
   
        private void initMouseControl() {
        scene.setOnMousePressed(me -> {
            mouseStartPosX = me.getSceneX();
            mouseStartPosY = me.getSceneY();
            mousePosX = me.getSceneX();
            mousePosY = me.getSceneY();
            mouseOldX = me.getSceneX();
            mouseOldY = me.getSceneY();
        });

        scene.setOnMouseDragged(me -> {
            mouseOldX = mousePosX;
            mouseOldY = mousePosY;
            mousePosX = me.getSceneX();
            mousePosY = me.getSceneY();
            mouseDeltaX = (mousePosX - mouseOldX);
            mouseDeltaY = (mousePosY - mouseOldY);

            if (me.isPrimaryButtonDown()) {
                ballXForm.addRotation(-mouseDeltaX * MOUSE_SPEED * ROTATION_SPEED, Rotate.Y_AXIS);
                ballXForm.addRotation(mouseDeltaY * MOUSE_SPEED * ROTATION_SPEED, Rotate.X_AXIS);
            }
        });
    }
   
   
   
   
class XformBox extends Group {

    XformBox() {
        super();
        getTransforms().add(new Affine());
    }

    /**
     * Accumulate rotation about specified axis
     *
     * @param angle
     * @param axis
     */
    public void addRotation(double angle, Point3D axis) {
        Rotate r = new Rotate(angle, axis);
        /**
         * This is the important bit and thanks to bronkowitz in this post
         * https://stackoverflow.com/questions/31382634/javafx-3d-rotations for
         * getting me to the solution that the rotations need accumulated in
         * this way
         */
        getTransforms().set(0, r.createConcatenation(getTransforms().get(0)));
    }

    /**
     * Reset transform to identity transform
     */
    public void reset() {
        getTransforms().set(0, new Affine());
    }
}  

#End If

1672480928382.png
 

Attachments

  • Spring.zip
    5 KB · Views: 171

Johan Schoeman

Expert
Licensed User
Longtime User
A TorusMesh making use of inline Java code. Have added some setters to be able to change the appearance via the Sliders. You can also move it around with your mouse. Change it to your liking....

1672484115564.png


1672484253427.png


Change the inline Java code to the below to show a CYAN torus:

Inline Java Code:
//       spring = new SpringMesh(DEFAULT_MEAN_RADIUS, DEFAULT_WIRE_RADIUS, DEFAULT_PITCH, DEFAULT_LENGTH, DEFAULT_LENGTH_DIVISIONS, DEFAULT_WIRE_DIVISIONS, DEFAULT_LENGTH_CROP, DEFAULT_WIRE_CROP);

//     SpringMesh spring = new SpringMesh(10, 2, 2, 8 * 2 * Math.PI, 200, 100, 0, 0);

        spring = new TorusMesh();
        ShapeContainer sc = new ShapeContainer(spring);
        sc.setDiffuseColor(Color.CYAN);
 

Attachments

  • Torus.zip
    4.9 KB · Views: 163
Last edited:

Johan Schoeman

Expert
Licensed User
Longtime User
Last one for now (KnotMesh) - change the code to your liking (see KnotMesh). Move the knot with your mouse.


knot.gif
 

Attachments

  • Knot.zip
    5.1 KB · Views: 184

Johan Schoeman

Expert
Licensed User
Longtime User
Johan is amazing!
The guys that wrote the Java code are amazing. I am just trying to impliment it in B4J via inline Java code - other than having to add some setters to make changes work and a tweak here and there.

It makes more sense to me to do it via inline Java code rather than using only JavaObject. But one way or the other - you have to study the original Java code (eg the jar) to impliment it and browse the web for suitable answers that will make it work. Unless your name is Erel.
 
Last edited:
Top