#JavaFX Fluid Simulation

1 messages ยท Page 2 of 1

boreal socket
#

yeah I think so

grand garnet
#

ok nvm ๐Ÿ˜ญ

#

it does prevent the moving but it doesn't accept it as a keybind

#

so i guess i gotta do something about that

boreal socket
#

is settingsPane the tabpane?

grand garnet
#

yep

boreal socket
#

hm

#

yeah that wont work then

#

hm

grand garnet
#

ahh

#

wait nvm

#

it won't work

#

wait

#

i am maybe a genius

#

hold on a sec

#

so i have this method

#
    @FXML
    public void onKeyPressed(KeyEvent keyEvent) {
        if (setKeyBindFlag) {
            keyBindMap.put(recentlyPressedAction, keyEvent.getCode());
            buttonMap.get(recentlyPressedAction)
                    .setText(keyEvent.getCode()
                            .getName()
                            .toUpperCase());
            changeButtonColor(recentlyPressedAction, primaryButtonColor);
            setKeyBindFlag = false;
        }
    }```
cedar tigerBOT
grand garnet
#

i could just do this no?

#
settingsPane.addEventFilter(KeyEvent.ANY, keyEvent -> {
            if (keyEvent.getCode()
                    .isArrowKey()) {
                onKeyPressed(keyEvent);
                keyEvent.consume();
            }
        });```
boreal socket
#

probably works

grand garnet
#

YES

#

IT WORKS

boreal socket
#

but I am not sure if thats a good solution though

grand garnet
#

WOOOOO

boreal socket
#

lol

grand garnet
#

how come ๐Ÿ˜ญ

boreal socket
#

javafx internally should handle events, but now you are firing your event outside of that

#

but whatever

grand garnet
#

๐Ÿ˜ญ

#

i mean

boreal socket
#

just work with that

#

its fine

grand garnet
#

it's not tooo much of a big deal yeah

#

OK

#

i can now move onto my graphics settings

boreal socket
#

I am going to find out if there is a better way

#

and you can continue working on other stuff

grand garnet
#

i should be done with this main menu prototype within the next 2 hours

#

sure!

#

btw

#

quick question

#

do you do a cs degree lmao

boreal socket
#

not yet

#

later this year I am going to start

#

still sitting in school

grand garnet
#

ohhh same

#

but im doing maths ๐Ÿ˜ญ

#

hence why i suck with gui stuff

#

i do love the logic side of cs though

boreal socket
#

try this:

tabs.setEventDispatcher((event, chain) -> {
    if (event instanceof KeyEvent keyEvent) {
        if (keyEvent.getCode().isArrowKey()) {
            event.consume();
        }
    }
    return chain.dispatchEvent(event);
});
grand garnet
#

nope

#

my keybinds don't work at all if ido that

boreal socket
#

hm ok :D

grand garnet
#

how should i make it so i can change these settings ๐Ÿ˜ญ

#

i changed the fluid cace one

boreal socket
#

then if you click on them you handle it

#

are there specific options for cell size for example?

#

so the user can switch between 10x10, 100x100, ... and not any value of N?

grand garnet
#

yeahh

boreal socket
#

otherwise you would want text inputs

boreal socket
grand garnet
#

hmm

#

and for the settings should i use something like a circular linked list?

boreal socket
#

if the user clicks on it it is going to jump to the next value of the possible ones

boreal socket
#

but also a normal list will work

grand garnet
#

so like lets say FPS i would have 20 -> 30 -> 45 -> 60 -> 75

grand garnet
boreal socket
#

yeah anything would work here tbh

grand garnet
#

hmm

#

also the linked list, should i store it in the controller?

boreal socket
#

you might want to create a custom class for graphics settings

#

and have an instance of that in the controller

grand garnet
#

hmm

#

should i call it GraphicsController?

boreal socket
#

no it wouldnt be a controller in this case

#

it would just handle graphics settings

grand garnet
#

GraphicsHandler?

boreal socket
#

yeah why not

grand garnet
#

i made a circular linked list

#

for the marks

#
package com.fluidity.program.utilities;

import javafx.scene.Node;

public class CircularLinkedList<T> {
    private LinkedListNode<T> head;
    private LinkedListNode<T> tail;

    public CircularLinkedList() {
        head = null;
        tail = null;
    }

    public CircularLinkedList(T[] initalList) {
        for (T item : initalList) {
            addNode(item);
        }
    }

    public void addNode(T value) {
        LinkedListNode<T> newNode = new LinkedListNode<>(value);

        if (head == null) {
            head = newNode;
        } else {
            tail.nextNode = newNode;
        }

        tail = newNode;
        tail.nextNode = head;
    }

    public void deleteNode(T valueToDelete) {
        LinkedListNode<T> currentNode = head;
        if (head == null) {
            return;
        }
        do {
            LinkedListNode<T> nextNode = currentNode.nextNode;
            if (nextNode.payload == valueToDelete) {
                if (tail == head) {
                    head = null;
                    tail = null;
                } else {
                    currentNode.nextNode = nextNode.nextNode;
                    if (head == nextNode) {
                        head = head.nextNode;
                    }
                    if (tail == nextNode) {
                        tail = currentNode;
                    }
                }
                break;
            }
            currentNode = nextNode;
        } while (currentNode != head);
    }

    public boolean containsNode(T searchValue) {
        LinkedListNode<T> currentNode = head;

        if (head != null) {
            do {
                if (currentNode.payload == searchValue) {
                    return true;
                }
                currentNode = currentNode.nextNode;
            } while (currentNode != head);
        }
        return false;
    }
}
#
package com.fluidity.program.utilities;

public class LinkedListNode<T> {
    public T payload;
    public LinkedListNode<T> nextNode;

    public LinkedListNode(final T payload, final LinkedListNode<T> nextNode) {
        this.payload = payload;
        this.nextNode = nextNode;
    }

    public LinkedListNode(final T payload) {
        this.payload = payload;
        this.nextNode = null;
    }

    public LinkedListNode() {
        this.payload = null;
        this.nextNode = null;
    }
}
boreal socket
#

would have just used a normal list, but whatever

grand garnet
#

fair enough ๐Ÿ˜ญ

cedar tigerBOT
#

@grand garnet

Your question has been closed due to inactivity.

If it was not resolved yet, feel free to just post a message below
to reopen it, or create a new thread.

Note that usually the reason for nobody calling back is that your
question may have been not well asked and hence no one felt confident
enough answering.

When you reopen the thread, try to use your time to improve the quality
of the question by elaborating, providing details, context, all relevant code
snippets, any errors you are getting, concrete examples and perhaps also some
screenshots. Share your attempt, explain the expected results and compare
them to the current results.

Also try to make the information easily accessible by sharing code
or assignment descriptions directly on Discord, not behind a link or
PDF-file; provide some guidance for long code snippets and ensure
the code is well formatted and has syntax highlighting. Kindly read through
https://stackoverflow.com/help/how-to-ask for more.

With enough info, someone knows the answer for sure ๐Ÿ‘

boreal socket
#

.

grand garnet
#

I AM HOME

#

TIME TO CONTINUE THE PROJECT

#

ok

#

I must now start with the second prototype

#

I am not sure if i should conduct the testing first

#

surely i can just make the second prototype and test the first one separately?

boreal socket
#

prototype?

grand garnet
#

yeahh

#

so in my school we have to conduct the development in prototypes

#

like sections of devvelopment

#

i have broken mine down into the following:

Prototype 1 - Creating the main menu
Prototype 2 - Implementing the fluid functionality
Prototype 3 - Implementing the simulation functionality(Simulation Loop and rendering)
Prototype 4 - Barriers and Objects to place in fluid
Prototype 5 - Backtracking and saving the recordings of the fluid```
boreal socket
#

so I would first completely finish prototype 1 before starting with the second

grand garnet
#

hmm ok

steep elbow
grand garnet
#

i mean i have made prototype 1 already

#

just need to test and discuss about it

grand garnet
#

but

#

prototype 1 is done anyways

boreal socket
#

btw you can already put your project on github so I can give some feedback on your code

#

its easier if this is done step by step like the prototype stuff

#

@grand garnet

grand garnet
#

i'm just doing finishing touches on prototype 1

grand garnet
#
import java.awt.event.MouseEvent;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.function.Consumer;

import static java.lang.Math.hypot;

public class MouseAdapter extends java.awt.event.MouseAdapter {
    private int[] previousCoords;
    private boolean mouseHeld = false;
    private List<FluidInput> sourceQueue;
    private Instant startAdd;

    public MouseAdapter() {
        sourceQueue = new ArrayList<>(); //TALK ABOUT LINKED LIST
        startAdd = Instant.now();
    }

    public void mousePressed(MouseEvent e) {
        previousCoords = new int[] { e.getX(), e.getY() };
        mouseHeld = true;
        startAdd = Instant.now();
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        mouseHeld = false;
    }

    public synchronized void mouseDragged(MouseEvent e) {
        double velocityX = 0;
        double velocityY = 0;
        double dragScalar = 5.0;

        if (previousCoords != null) {
            velocityX = dragScalar * ((double) e.getX() - previousCoords[0]);
            velocityY = dragScalar * ((double) e.getY() - previousCoords[1]);
        }

        startAdd = Instant.now();
        previousCoords = new int[] { e.getX(), e.getY() };
        sourceQueue.add(new FluidInput(previousCoords[0], previousCoords[1] - (30), velocityX, velocityY,
                6.0 * hypot(velocityX, velocityY)));
    }

    synchronized void consumeSources(Consumer<FluidInput> sourceConsumer) {
        if (mouseHeld) {
            long timeHeld = Duration.between(startAdd, Instant.now())
                    .toMillis();
            startAdd = Instant.now();
            sourceQueue.add(new FluidInput(previousCoords[0], previousCoords[1], 0, 0, timeHeld * 20.0));
        }

        for (FluidInput source : sourceQueue) {
            sourceConsumer.accept(source);
        }
        sourceQueue.clear();
    }
}
cedar tigerBOT
grand garnet
#

need help converting this into javafx stuff ๐Ÿ˜ญ

boreal socket
#

you can copy most of it

dense hare
boreal socket
grand garnet
#

yeah i will be

#

haven't implemented it yet

boreal socket
#

you can just change the onMousePressed and onMouseReleased on that element

boreal socket
dense hare
boreal socket
#

.

#

it also looks weird when looking at the hierarchy, its the same as doing:

public class Dog extends different.location.Dog {

}

what makes it different?

grand garnet
#

that is very true

#

i am sorry about that ๐Ÿ˜ญ

#

does this presentation look nice?

limber mirage
#

Yeah looks nice

boreal socket
#

Yeah looks decent

#

The control elements on the right menu could get some redesign using css

grand garnet
#

hmm true

#

my justification for a grayscale simulation is for it to be accesssible for colorblind ๐Ÿ˜ญ

grand garnet
#

today i couldnt' get much work done ๐Ÿ˜ญ

#

had to go to my uncles wedding anniversary

boreal socket
#

tomorrow is another day

#

dw

grand garnet
#

yes ofc

#

actually

#

im in the car rn omw home

#

imma just do some rn

boreal socket
#

imma go sleep now

grand garnet
#

imma just do my write up

grand garnet
#

good night bro

boreal socket
#

gn

cedar tigerBOT
#

In Java, the forward slash ("/") at the beginning of a path represents an absolute path.

When you provide an absolute path, it means that you are specifying the complete and exact location of the file or resource you want to access. The absolute path starts from the root directory of your file system.

On the other hand, when you don't include a forward slash at the beginning of a path, it is considered a relative path. A relative path is interpreted relative to the current working directory or the location where your program is being executed.

By using an absolute path with a forward slash at the beginning ("/MainMenu.fxml"), you ensure that Java looks for the file in a specific and fixed location in your file system. This can be useful when you want to access resources that are stored in specific directories regardless of where your program is being executed from.

If you omit the forward slash ("MainMenu.fxml"), Java will interpret it as a relative path and look for the file in relation to the current working directory. This can lead to issues if your program is being executed from different locations or if there are multiple files with similar names in different directories.

In summary, using an absolute path with a forward slash at the beginning ensures that your program can consistently locate and load resources regardless of its execution context.

cedar tigerBOT
#

@grand garnet

Your question has been closed due to inactivity.

If it was not resolved yet, feel free to just post a message below
to reopen it, or create a new thread.

Note that usually the reason for nobody calling back is that your
question may have been not well asked and hence no one felt confident
enough answering.

When you reopen the thread, try to use your time to improve the quality
of the question by elaborating, providing details, context, all relevant code
snippets, any errors you are getting, concrete examples and perhaps also some
screenshots. Share your attempt, explain the expected results and compare
them to the current results.

Also try to make the information easily accessible by sharing code
or assignment descriptions directly on Discord, not behind a link or
PDF-file; provide some guidance for long code snippets and ensure
the code is well formatted and has syntax highlighting. Kindly read through
https://stackoverflow.com/help/how-to-ask for more.

With enough info, someone knows the answer for sure ๐Ÿ‘

boreal socket
#

.

cedar tigerBOT
#

SLF4J (Simple Logging Facade for Java) is a logging framework that provides a simple and efficient way to log messages in Java applications. It serves as a facade or abstraction layer for various logging frameworks, allowing developers to switch between different logging implementations without changing their code.

One of the key benefits of SLF4J is its ability to decouple the application code from the underlying logging implementation. By using SLF4J, developers can write log statements using a common API, and then choose the desired logging framework at deployment time. This flexibility enables easy migration or integration with different logging systems based on specific requirements or preferences.

Providing information on how a program works through logging is highly beneficial for several reasons:

  1. Debugging and Troubleshooting: Logging allows developers to track the flow of execution, identify potential issues, and debug problems in real-time. By providing detailed information about the program's behavior, including variable values, method calls, and error messages, it becomes easier to pinpoint and fix bugs or unexpected behavior.
cedar tigerBOT
# cedar tiger SLF4J (Simple Logging Facade for Java) is a logging framework that provides a si...
  1. Monitoring and Performance Analysis: Logging can be used to monitor the performance of an application by capturing metrics such as response times, resource utilization, or database queries. This information helps in identifying bottlenecks or areas that require optimization.

  2. Auditing and Compliance: In certain industries or applications where regulatory compliance is crucial (e.g., finance or healthcare), logging plays a vital role in auditing activities. By recording important events or actions within the program, it becomes possible to trace back any unauthorized access attempts or detect suspicious behavior.

  3. Documentation and Communication: Logs serve as a form of documentation that captures the history of an application's execution. They provide insights into how different components interact with each other and help in understanding complex workflows. Additionally, logs can be shared with other team members or stakeholders to communicate issues, progress, or changes made during development.

In summary, SLF4J simplifies logging in Java applications by providing a unified API and decoupling the code from specific logging implementations. By leveraging logging, developers gain valuable insights into the program's behavior, enabling efficient debugging, performance analysis, compliance adherence, and effective communication within the development team.

#

There are several reasons why using SLF4J logging is preferred over print statements. Firstly, SLF4J provides a flexible and efficient logging framework that allows you to control the log output without modifying your code. This means that you can easily change the log level or redirect logs to different destinations (e.g., files, databases) without having to modify your codebase.

Secondly, SLF4J supports different logging implementations (e.g., Logback, Log4j) which allows you to choose the one that best suits your needs. This flexibility ensures that you can easily switch between logging frameworks without having to rewrite your code.

Additionally, SLF4J provides various logging levels (e.g., debug, info, error) which allow you to categorize and filter log messages based on their importance. This helps in troubleshooting and debugging as you can focus on relevant logs while ignoring less important ones.

Furthermore, using SLF4J promotes good coding practices by separating the concerns of logging and business logic. By using SLF4J's logger interface, you can write log statements with placeholders for variables or parameters, improving readability and maintainability of your code.

Lastly, SLF4J offers performance benefits over print statements. While print statements may introduce overhead due to I/O operations or string concatenation for constructing log messages, SLF4J's logging implementations are optimized for performance and provide efficient ways of handling log messages.

Overall, by using SLF4J logging instead of print statements, you gain flexibility in controlling log output, support for different logging frameworks, better organization of log messages with various levels, improved coding practices, and enhanced performance.

boreal socket
#

if you got a question just ask

grand garnet
#

oh no im just doing this for my write up ๐Ÿ˜ญ

#

not copying but just taking ideas

#

btw does the bot use gpt4?

boreal socket
#

no

grand garnet
#

oh

#

gpt3?

boreal socket
#

gpt3.5 smth smth

grand garnet
#

ahh

boreal socket
#

gpt-3.5-turbo

grand garnet
#

oooh

#

cool

cedar tigerBOT
#

When you close the stage in JavaFX, the application window is closed and the program terminates. The close operation can be triggered by clicking on the close button (X) on the window or by calling the close() method on the stage object.

By default, closing the stage will also trigger an onCloseRequest event. You can handle this event to perform any necessary cleanup or save operations before closing the application.

If you have multiple stages in your application, closing one stage does not automatically close all other stages. Each stage needs to be closed individually.

In addition, if your JavaFX application is running as a standalone application (not embedded within another Java application), closing the main stage will terminate the entire Java Virtual Machine (JVM) and exit the program.

grand garnet
#

second prototype beginning soon ๐Ÿ’ช

grand garnet
#
package com.fluidity.program.ui;

public enum FluidUIAction {
    // The different fluid actions and their string identifiers
    PRIMARY_PAUSE("primary-pause"),
    PRIMARY_STEP_FORWARD("primary-step-forward"),
    PRIMARY_STEP_BACKWARD("primary-step-backward"),
    SECONDARY_PAUSE("secondary-pause"),
    SECONDARY_STEP_FORWARD("secondary-step-forward"),
    SECONDARY_STEP_BACKWARD("secondary-step-backward");

    private final String path;

    FluidUIAction(String path) {
        this.path = path;
    }

    public String getPath() {
        return path;
    }

    // Returns the fluid action based off its path
    public static FluidUIAction getByPath(String path) {
        for (FluidUIAction action : FluidUIAction.values()) {
            if (action.path.equals(path)) {
                return action;
            }
        }
        // Throws an exception if there is no action which has the path in the parameter
        throw new IllegalArgumentException();
    }
}```
cedar tigerBOT
grand garnet
#

What are the benefits of storing these actions as an enum?

boreal socket
#

first I wouldnt separate primary and secondary action

grand garnet
#

๐Ÿ˜ญ

#

i cannot be bothered doing that rn tbh i just need to do the writeup i can probably change it after development stage

boreal socket
#

yeah ok then just ignore that for now

grand garnet
#

idk what i should write about it in my report ๐Ÿ˜ญ

boreal socket
#

how would you do it differently?

#

you would likely use a String to identify it

#

which is bad, as it could easily lead to errors you will only notice at runtime

#

for example:

#

you identify an action like this:

"primary-pause"

and then have a typo or anything, it will compile like normal, because its still a valid string, but the program wont act normal
because it cant identify that action because it doesnt 100% equal the real action identified using strings

#

enum give you compile time safety

#

also enums are just kinda like normal objects but predefined

#

which makes sense here

#

because you already know beforehand which actions exists and you can define them through that enum

#

you have a clear set of named constants that represent the different actions

grand garnet
#

yeahh

grand garnet
#

it's kinda just like an abstraction of the string stuff as well i guess

cedar tigerBOT
#

@grand garnet

Your question has been closed due to inactivity.

If it was not resolved yet, feel free to just post a message below
to reopen it, or create a new thread.

Note that usually the reason for nobody calling back is that your
question may have been not well asked and hence no one felt confident
enough answering.

When you reopen the thread, try to use your time to improve the quality
of the question by elaborating, providing details, context, all relevant code
snippets, any errors you are getting, concrete examples and perhaps also some
screenshots. Share your attempt, explain the expected results and compare
them to the current results.

Also try to make the information easily accessible by sharing code
or assignment descriptions directly on Discord, not behind a link or
PDF-file; provide some guidance for long code snippets and ensure
the code is well formatted and has syntax highlighting. Kindly read through
https://stackoverflow.com/help/how-to-ask for more.

With enough info, someone knows the answer for sure ๐Ÿ‘

boreal socket
#

.

cedar tigerBOT
#

@grand garnet

Your question has been closed due to inactivity.

If it was not resolved yet, feel free to just post a message below
to reopen it, or create a new thread.

Note that usually the reason for nobody calling back is that your
question may have been not well asked and hence no one felt confident
enough answering.

When you reopen the thread, try to use your time to improve the quality
of the question by elaborating, providing details, context, all relevant code
snippets, any errors you are getting, concrete examples and perhaps also some
screenshots. Share your attempt, explain the expected results and compare
them to the current results.

Also try to make the information easily accessible by sharing code
or assignment descriptions directly on Discord, not behind a link or
PDF-file; provide some guidance for long code snippets and ensure
the code is well formatted and has syntax highlighting. Kindly read through
https://stackoverflow.com/help/how-to-ask for more.

With enough info, someone knows the answer for sure ๐Ÿ‘

grand garnet
#

d

#

I must keep it open

boreal socket
#

๐Ÿ‘€

grand garnet
#

I have taken a day and a bit off for this project

#

like i think i lost brain cells tryinig to develop that UI

#

The rest of this week is crazy ๐Ÿ˜ญ

boreal socket
#

how much time you got for this?

grand garnet
boreal socket
#

this project

#

you got no deadline?

grand garnet
#

oh I do

#

over here

#

i've done what I would say is the hardest prototypes for me

boreal socket
#

ah ok

grand garnet
#

P1 - Structure of main menu (done)
P2 - Interactivity of main menu (done but need to write up like maybe 1 more page not long left probably 90%)
P3 - Fluid Behaviour Implementation (90% done but need to write up)
P4 - Simulation loop and Simulation interactivity implementation (done but in AWT I just need to bring it to JFX)
P5 - Adding barriers to the fluid (not done)
P6 - Fluid Recording and backtracking (not done)

boreal socket
#

ok yeah mostly done already

grand garnet
#

yeahh

cedar tigerBOT
#

@grand garnet

Your question has been closed due to inactivity.

If it was not resolved yet, feel free to just post a message below
to reopen it, or create a new thread.

Note that usually the reason for nobody calling back is that your
question may have been not well asked and hence no one felt confident
enough answering.

When you reopen the thread, try to use your time to improve the quality
of the question by elaborating, providing details, context, all relevant code
snippets, any errors you are getting, concrete examples and perhaps also some
screenshots. Share your attempt, explain the expected results and compare
them to the current results.

Also try to make the information easily accessible by sharing code
or assignment descriptions directly on Discord, not behind a link or
PDF-file; provide some guidance for long code snippets and ensure
the code is well formatted and has syntax highlighting. Kindly read through
https://stackoverflow.com/help/how-to-ask for more.

With enough info, someone knows the answer for sure ๐Ÿ‘

grand garnet
#

weeeeeeeeeeeeee

boreal socket
#

weeeeeee

grand garnet
#

is it possible if i could keep this channel open until I finish my project ๐Ÿ˜ญ

boreal socket
#

not really

grand garnet
#

whyyyy

#

I'm not even lying i might have to take my laptop to the gym with me

#

i have so much writing to do

#

not even coding

#

WRITING

boreal socket
#

and it wasnt needed before

#

but feel free to create a github issue and suggest it

#

or #server-suggestions

#

but yeah it wasnt needed before

grand garnet
#

ahh true

cedar tigerBOT
#

@grand garnet

Your question has been closed due to inactivity.

If it was not resolved yet, feel free to just post a message below
to reopen it, or create a new thread.

Note that usually the reason for nobody calling back is that your
question may have been not well asked and hence no one felt confident
enough answering.

When you reopen the thread, try to use your time to improve the quality
of the question by elaborating, providing details, context, all relevant code
snippets, any errors you are getting, concrete examples and perhaps also some
screenshots. Share your attempt, explain the expected results and compare
them to the current results.

Also try to make the information easily accessible by sharing code
or assignment descriptions directly on Discord, not behind a link or
PDF-file; provide some guidance for long code snippets and ensure
the code is well formatted and has syntax highlighting. Kindly read through
https://stackoverflow.com/help/how-to-ask for more.

With enough info, someone knows the answer for sure ๐Ÿ‘

boreal socket
#

.

cedar tigerBOT
#

@grand garnet

Your question has been closed due to inactivity.

If it was not resolved yet, feel free to just post a message below
to reopen it, or create a new thread.

Note that usually the reason for nobody calling back is that your
question may have been not well asked and hence no one felt confident
enough answering.

When you reopen the thread, try to use your time to improve the quality
of the question by elaborating, providing details, context, all relevant code
snippets, any errors you are getting, concrete examples and perhaps also some
screenshots. Share your attempt, explain the expected results and compare
them to the current results.

Also try to make the information easily accessible by sharing code
or assignment descriptions directly on Discord, not behind a link or
PDF-file; provide some guidance for long code snippets and ensure
the code is well formatted and has syntax highlighting. Kindly read through
https://stackoverflow.com/help/how-to-ask for more.

With enough info, someone knows the answer for sure ๐Ÿ‘

grand garnet
#

www

#

is it opened again?

#

where was the 1 week cooldown ๐Ÿ˜ญ

#

anyways

#

sickness got onto me

#

been in bed for around 24 hours now

#

ofc i got up to do my stuff but

#

i am soooooo sick

#

doesn't stop the grind though ๐Ÿ’ช

#

im gonna finish the writing for prototype 2 today

#

hopefully i start prototype 3 tmrw

#

anyways

#

does anyone know how i can fake an error for file reading and writing ๐Ÿ˜ญ

#

like something that sounds believable and not stupid

#

what happened to 1 week limit

grand garnet
boreal socket
#

what are you using to read/write the files?

grand garnet
#

FileHandler class

boreal socket
#

thats your custom class

grand garnet
#
package com.fluidity.program.utilities;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

public class FileHandler {
    private static Logger logger = LogManager.getLogger(FileHandler.class);

    // Prevents the object from being created with the default constructor
    private FileHandler() {
        throw new UnsupportedOperationException("Utility Class");
    }

    public static boolean createFile(String name) {
        try {
            Path newFilePath = Paths.get(name);
            Files.createFile(newFilePath);
        } catch (IOException e) {
            logger.error("Creating new file failed.", e);
            return false;
        }
        return true;
    }

    public static List<String> readFile(String fileName) {
        Path path = Path.of(fileName);
        List<String> file = new ArrayList<>();
        try {
            file = Files.readAllLines(path);
        } catch (IOException e) {
            logger.error("Reading file failed.", e);
        }
        return file;
    }

    public static boolean writeLine(String fileName, String data) {
        Path path = Path.of(fileName);
        try {
            Files.writeString(path, data);
        } catch (IOException e) {
            logger.error("Writing to file failed.", e);
            return false;
        }
        return true;
    }

    public static boolean clearFile(String fileName) {
        Path path = Path.of(fileName);

        try (BufferedWriter writer = Files.newBufferedWriter(path)) {
            writer.write("");
            writer.flush();
        } catch (IOException e) {
            logger.error("Writing to file failed.", e);
            return false;
        }
        return true;
    }
}
cedar tigerBOT
boreal socket
#

what uses it internal?

grand garnet
#

NIO

boreal socket
#

I would just look at the docs

#

to find out reasons it could fail

#

for example Files.createFile

#

or do you want to simulate a fail?

steep elbow
grand garnet
#

hmm true

#

i should do that at the end

grand garnet
boreal socket
#

you shouldnt do that

grand garnet
#

i need to get marks ๐Ÿ˜ญ

#

well

#

i do have an 'error' i got before

#

not sure if it counts as one though

#

it was basically

#

I had String[] configuration = line.split(":");

#

but i wanted to split only at the first colon

#

so i did String[] configuration = line.split(":", 1);

#

but it was meant to be 2

boreal socket
#

and how is that related?

grand garnet
#

im not sure if that's an error worth talking about

#

because all i had to do was simply change a number

boreal socket
#

ah so you need to talk about stuff that went wrong while creating the software?

grand garnet
#

yeahh

boreal socket
#

then talk about stuff that really happened

#

and not fake something

steep elbow
grand garnet
#

fairss

grand garnet
#

oh are you taklkng about the yaml stuff

boreal socket
#

there is java.util.Properties

#

I remember we told you before

grand garnet
#

yeahh i think i said i didn't want to use extra stuff i think

#

my teacher doesn't like it either

steep elbow
#

?

boreal socket
#

that makes no sense in the real world

#

I hate it

#

also that is provided by java

#

its like not using arraylist

steep elbow
#

wdym you don't want to use extra stuff ?

#

like you don't want to use String because it's extra compared to char[] ?

grand garnet
#

๐Ÿ˜ญ

grand garnet
#

i had to make my own linked list for the marks

#

and just to have all that extra logic in my program

boreal socket
#

who told you to create your own linked list?

grand garnet
#

my teacher

#

lemme try finding the email

boreal socket
#

did he really say you need to create your own linked list??? ๐Ÿ’€

grand garnet
#

Ok this one is not the linked list one

#

i couldn't find it

#

but here is the one for the queue

#

he was talking about gaining marks

boreal socket
#

Am assuming you wrote the queue classes yourself
pepe_sad

grand garnet
#

๐Ÿ˜ญ

#

which is why i have to do a lot of the stuff manually

#

i did not send that wait

#

WTF

#

bruh

#

bruh

#

i think someones on my account

#

1 second

#

ok reset password

#

im chilling

boreal socket
steep elbow
boreal socket
#

I think the teacher wants more files so he can give marks for more done, smth like that

grand garnet
#

ye

boreal socket
#

which is just so giga stupid and makes no sense at all

#

but whatever

grand garnet
#

very giga mega tera peta yotta zotta kilo milli micro nano pico femto stupid

#

don't ask why i know that

#

we do too many conversions in physics

steep elbow
# grand garnet ye

but if you already have a lot of classes, then there is no need to do that right ?

#

also don't use any linked list, they are bad

grand garnet
#

๐Ÿ˜ญ๐Ÿ˜ญ

#

fair enough

#

so if i am implementing a queue i should do so using an arraylist implementation?

#

well if i want a max number of elements I can do an array implementation of max size

limber mirage
#

Have you simulated the fluids yet

steep elbow
grand garnet
#

it's a bit basic

#

and not in jfx

#

but in awt

#

i gotta chang eit to jfx

cedar tigerBOT
#

@grand garnet

Your question has been closed due to inactivity.

If it was not resolved yet, feel free to just post a message below
to reopen it, or create a new thread.

Note that usually the reason for nobody calling back is that your
question may have been not well asked and hence no one felt confident
enough answering.

When you reopen the thread, try to use your time to improve the quality
of the question by elaborating, providing details, context, all relevant code
snippets, any errors you are getting, concrete examples and perhaps also some
screenshots. Share your attempt, explain the expected results and compare
them to the current results.

Also try to make the information easily accessible by sharing code
or assignment descriptions directly on Discord, not behind a link or
PDF-file; provide some guidance for long code snippets and ensure
the code is well formatted and has syntax highlighting. Kindly read through
https://stackoverflow.com/help/how-to-ask for more.

With enough info, someone knows the answer for sure ๐Ÿ‘

grand garnet
#

alathreon scammed it

#

where is my 1 week timeout

steep elbow
#

๐Ÿคท

grand garnet
#

๐Ÿ˜ญ

boreal socket
#

lmao

grizzled inlet
#

our bot is not using discord timeout, should do tho

steep elbow
#

huh

grand garnet
#

need help converting this into jfx for a canvas

#
public synchronized void render(DataProvider pixelStream) {
        BufferedImage imageContainer = new BufferedImage(IMAGE_WIDTH, IMAGE_HEIGHT, BufferedImage.TYPE_BYTE_GRAY);
        byte[] buffer = ((DataBufferByte) imageContainer.getRaster()
                .getDataBuffer()).getData();

        for (int y = 0; y < imageContainer.getHeight(); y++) {
            for (int x = 0; x < imageContainer.getWidth(); x++) {
                buffer[y * IMAGE_WIDTH + x] = pixelStream.provideData(x, y);
            }
        }

        this.buffer = imageContainer;
        repaint();
    }```
cedar tigerBOT
boreal socket
#

check these methods

cedar tigerBOT
#

@grand garnet

Your question has been closed due to inactivity.

If it was not resolved yet, feel free to just post a message below
to reopen it, or create a new thread.

Note that usually the reason for nobody calling back is that your
question may have been not well asked and hence no one felt confident
enough answering.

When you reopen the thread, try to use your time to improve the quality
of the question by elaborating, providing details, context, all relevant code
snippets, any errors you are getting, concrete examples and perhaps also some
screenshots. Share your attempt, explain the expected results and compare
them to the current results.

Also try to make the information easily accessible by sharing code
or assignment descriptions directly on Discord, not behind a link or
PDF-file; provide some guidance for long code snippets and ensure
the code is well formatted and has syntax highlighting. Kindly read through
https://stackoverflow.com/help/how-to-ask for more.

With enough info, someone knows the answer for sure ๐Ÿ‘

grand garnet
#

.

grand garnet
boreal socket
#

you want to set individual pixels right?

grand garnet
#

hmm

#

is there a way I can set the image to be of TYPE_BYTE_GRAY

boreal socket
#

idk

#

why would you want that?

grand garnet
#

my fluid is grayscale

boreal socket
#

yeah then just store gray pixel

#

it will have the same effect

grand garnet
#

i am so confused this is so overwhelming lmao

#

where should I start?

boreal socket
#

what does pixelStream.provideData return?

grand garnet
#

I have this so far

#
PixelWriter pixelWriter = canvas.getGraphicsContext2D().getPixelWriter();
        
        for (int y = 0; y < canvas.getHeight(); y++) {
            for (int x = 0; x < canvas.getWidth(); x++) {
                
            }
        }```
cedar tigerBOT
grand garnet
boreal socket
#

yeah then set all r, g, b to that same value and you get the grayscale as an RGB

#

so if pixelStream provideData at one location gives you 100 it will be:
R = 100
G = 100
B = 100
to give you a grayscale pixel

boreal socket
grand garnet
#

ohhh

#

ok

boreal socket
#

because there is Color#gray/Color#grayRgb

grand garnet
#
public synchronized void render(DataProvider<Byte> pixelStream) {
        PixelWriter pixelWriter = canvas.getGraphicsContext2D()
                .getPixelWriter();

        for (int y = 0; y < canvas.getHeight(); y++) {
            for (int x = 0; x < canvas.getWidth(); x++) {
                pixelWriter.setColor(x, y, Color.grayRgb(pixelStream.provideData(x, y)));
            }
        }
    }```
cedar tigerBOT
grand garnet
#

that should work right?

boreal socket
#

yeah

grand garnet
#

anyone good at conic sections here?

boreal socket
#

just ask your question directly

#

dont ask to ask

#

or ask if anyones around

#

just ask

cedar tigerBOT
#

@grand garnet

Your question has been closed due to inactivity.

If it was not resolved yet, feel free to just post a message below
to reopen it, or create a new thread.

Note that usually the reason for nobody calling back is that your
question may have been not well asked and hence no one felt confident
enough answering.

When you reopen the thread, try to use your time to improve the quality
of the question by elaborating, providing details, context, all relevant code
snippets, any errors you are getting, concrete examples and perhaps also some
screenshots. Share your attempt, explain the expected results and compare
them to the current results.

Also try to make the information easily accessible by sharing code
or assignment descriptions directly on Discord, not behind a link or
PDF-file; provide some guidance for long code snippets and ensure
the code is well formatted and has syntax highlighting. Kindly read through
https://stackoverflow.com/help/how-to-ask for more.

With enough info, someone knows the answer for sure ๐Ÿ‘

grand garnet
#

yoo

boreal socket
#

yo

grand garnet
#

I am struggling

#

it isn't rendering at alllll

boreal socket
#

share your code

grand garnet
#

ahhh it' s aprivate rep hold on

#

I think i'm just going to redo this section it's very long and convoluted

boreal socket
#

why though?

grand garnet
#

it's going to be long for you to understand it and I haven't uploaded it onto github because i want to keep the previous version

#

becaysue this one doesn't work

boreal socket
#

you can point back to a previous commit in order to undo it

grand garnet
#

oh ok

#

how exactly do i do that?

boreal socket
#

git reset

#

you can look it up

#

revert commits

grand garnet
#

should i just make a new branch?

boreal socket
#

yeah tha would be better

boreal socket
#

going to check it later

grand garnet
#

imma send in dm if you don't mind

boreal socket
grand garnet
#

what rank u in rl btw?

boreal socket
#

champ I right now

#

but kinda between dia/champ

grand garnet
#

what this mean

grand garnet
#

nice lmao

#

im still bad at the game lol

#

i can kinda wall to aerial

#

but not well

boreal socket
#

share the controller

#

do you modify the list while iterating?

grand garnet
#

no?

#
public class TestSimulationController extends Controller implements MouseAdapter {
    @FXML
    Canvas canvas;
    Simulation simulation;
    private boolean mouseHeld;
    private List<FluidInput> sourceQueue;
    private Instant startAdd;
    private int[] previousCoords;

    @Override
    public void initialize(final URL url, final ResourceBundle resourceBundle) {
        sourceQueue = new ArrayList<>();
        startAdd = Instant.now();
        simulation = new Simulation(this);
        simulation.startSimulation();
    }

    @Override
    @FXML
    public void mousePressed(MouseEvent e) {
        previousCoords = new int[] { (int) e.getX(), (int) e.getY() };
        mouseHeld = true;
        startAdd = Instant.now();
    }

    @Override
    @FXML
    public void mouseReleased() {
        mouseHeld = false;
    }

    @Override
    @FXML
    public void mouseDragged(MouseEvent e) {
        double velocityX = 0;
        double velocityY = 0;
        double dragScalar = 5.0;

        if (previousCoords != null) {
            velocityX = dragScalar * ((int) e.getX() - previousCoords[0]);
            velocityY = dragScalar * ((int) e.getY() - previousCoords[1]);
        }

        startAdd = Instant.now();
        previousCoords = new int[] { (int) e.getX(), (int) e.getY() };
        sourceQueue.add(new FluidInput(previousCoords[0], previousCoords[1], velocityX, velocityY,
                6.0 * hypot(velocityX, velocityY), simulation.CELL_LENGTH));
    }
#

    @Override
    public synchronized void consumeSources(Consumer<FluidInput> sourceConsumer) {
        if (mouseHeld) {
            long timeHeld = Duration.between(startAdd, Instant.now())
                    .toMillis();
            startAdd = Instant.now();
            sourceQueue.add(
                    new FluidInput(previousCoords[0], previousCoords[1], 0, 0, timeHeld * 20, simulation.CELL_LENGTH));
        }

        for (FluidInput source : sourceQueue) {
            sourceConsumer.accept(source);
        }
        sourceQueue.clear();
    }

    @Override
    public synchronized void render(DataProvider pixelStream) {
        PixelWriter pixelWriter = canvas.getGraphicsContext2D()
                .getPixelWriter();

        for (int y = 0; y < canvas.getHeight(); y++) {
            for (int x = 0; x < canvas.getWidth(); x++) {
                pixelWriter.setColor(x, y, Color.grayRgb(pixelStream.provideData(x, y)));
            }
        }
    }

}```
boreal socket
#

what is line 82?

#

ah you use threading in your application?

dense hare
#

mouseDragged adds to sourceQueue. mouseDragged is called by the FX Thread

consumeSources is iterating over sourceDragged. consumeSources is called by thread-3

#

you aren't synchronizing the use of sourceQueue between those 2 threads. there's a good chance FX thread is adding while thread-3 is iterating

boreal socket
#

but I doubt using synchronization is a good idea for mouseDragged though

#

because it could block the fx thread

dense hare
#

though that introduces a new problem, as squid mentioned

#

if the list is long, the FX thread will have to wait a while for thread-3 to finish iterating

#

while the FX thread is waiting, your GUI will be unresponsive, since the FX thread handles all other GUI events, including rendering

cedar tigerBOT
#

@grand garnet

Your question has been closed due to inactivity.

If it was not resolved yet, feel free to just post a message below
to reopen it, or create a new thread.

Note that usually the reason for nobody calling back is that your
question may have been not well asked and hence no one felt confident
enough answering.

When you reopen the thread, try to use your time to improve the quality
of the question by elaborating, providing details, context, all relevant code
snippets, any errors you are getting, concrete examples and perhaps also some
screenshots. Share your attempt, explain the expected results and compare
them to the current results.

Also try to make the information easily accessible by sharing code
or assignment descriptions directly on Discord, not behind a link or
PDF-file; provide some guidance for long code snippets and ensure
the code is well formatted and has syntax highlighting. Kindly read through
https://stackoverflow.com/help/how-to-ask for more.

With enough info, someone knows the answer for sure ๐Ÿ‘

grand garnet
#

ok

#

hi hello

#

can i hvae a longer time out?

grand garnet
#

Im so confused rn

#

@serene oak sorry for the ping but I remember you telling me something about this: What should I use when it comes to making a simulation in jfx, a custom game loop to split my update and render functionality or an animation timer?

#

I can't seem to find it

serene oak
#

no idea and im out of context.
its always a good idea to split logic and rendering

grand garnet
#

so you're suggesting an animation timer wouldn't be the best idea?

serene oak
#

no idea what ur referring to exactly

grand garnet
#

a grid based fluid simulation

serene oak
#

i got that

#

but what do u mean by animation timer

grand garnet
#
new AnimationTimer() {

    @Override
    public void handle(long now) {
      // rendering functionality
        }
        // ..
    }
}.start();```
cedar tigerBOT
serene oak
#

no idea what that class is

grand garnet
#

oh ok

serene oak
#

i have no javafx experience and hence i dont respond to ur javafx specific questions

grand garnet
#

i think there was a problem in my game loop when i switched from awt to jfx

serene oak
#

i cant tell u how to do animations in javafx

grand garnet
#

ahh okay

#

is creating scene based UI difficult in AWT?

#

because i've done the main simulation in it

boreal socket
#

you can first try to make the mouseDragged method to use synchronization, if you notice that it blocks fx thread heavily and thus the gui doesnt respond to other interactions in that time, you would need to use a different approach

#

like splitting the adding inside the mouseDragged method into another thread using ExecutorService and then make both usages synchronized

#

I have no idea if there is a better solution

grand garnet
#

all this synchronization stuff

#

I just wanna quit the project atp why didn't i use awt

boreal socket
#

because javafx is better

grand garnet
#

not for simulations ๐Ÿ˜ญ

boreal socket
boreal socket
#

though a game engine is also a good fit for physics simulations

grand garnet
#

like in awt i can have a mouse adapter class

#
public class MouseAdapter extends java.awt.event.MouseAdapter {
    private int[] previousCoords;
    private boolean mouseHeld = false;
    private List<FluidInput> sourceQueue;
    private Instant startAdd;

    public MouseAdapter() {
        sourceQueue = new ArrayList<>(); //TALK ABOUT LINKED LIST
        startAdd = Instant.now();
    }

    public void mousePressed(MouseEvent e) {
        previousCoords = new int[] { e.getX(), e.getY() };
        mouseHeld = true;
        startAdd = Instant.now();
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        mouseHeld = false;
    }

    public synchronized void mouseDragged(MouseEvent e) {
        double velocityX = 0;
        double velocityY = 0;
        double dragScalar = 5.0;

        if (previousCoords != null) {
            velocityX = dragScalar * ((double) e.getX() - previousCoords[0]);
            velocityY = dragScalar * ((double) e.getY() - previousCoords[1]);
        }

        startAdd = Instant.now();
        previousCoords = new int[] { e.getX(), e.getY() };
        sourceQueue.add(new FluidInput(previousCoords[0], previousCoords[1] - (30), velocityX, velocityY,
                6.0 * hypot(velocityX, velocityY)));
    }

    synchronized void consumeSources(Consumer<FluidInput> sourceConsumer) {
        if (mouseHeld) {
            long timeHeld = Duration.between(startAdd, Instant.now())
                    .toMillis();
            startAdd = Instant.now();
            sourceQueue.add(new FluidInput(previousCoords[0], previousCoords[1], 0, 0, timeHeld * 20.0));
        }

        for (FluidInput source : sourceQueue) {
            sourceConsumer.accept(source);
        }
        sourceQueue.clear();
    }
}```
cedar tigerBOT
grand garnet
#

but in jfx my code is all messy cos it's all within 1 controller that impelments a bunch of interfaces

boreal socket
#

you can do the same thing in javafx

#

but ig might cause problems

#

thats yours to find out

grand garnet
#

i don't know how to deal with that in jfx ๐Ÿ˜ญ

#

nioooooooooooo

#

have ytou seen my TestSimulationController

boreal socket
#

Just make the method synchronized

#

Whatโ€™s wrong with that

grand garnet
#

yeahh

#

it's very laggy ๐Ÿ˜ญ

dense hare
#

using synchronized on a method is similar to doing synchronized(this)

#

if the methods belong to different objects, then the methods will synchronize on different locks

boreal socket
#

what would you suggest instead?

#

I thought about moving the adding inside the mouseDragged into a different thread as well and then synchronize both usages

#

but that sounds meh

dense hare
#

so having a worker thread to handle the processing of the event methods would be the approach

boreal socket
#

@grand garnet

grand garnet
#

yess i will look at it tmrw when i focus on the project again

boreal socket
cedar tigerBOT
#

@grand garnet

Your question has been closed due to inactivity.

If it was not resolved yet, feel free to just post a message below
to reopen it, or create a new thread.

Note that usually the reason for nobody calling back is that your
question may have been not well asked and hence no one felt confident
enough answering.

When you reopen the thread, try to use your time to improve the quality
of the question by elaborating, providing details, context, all relevant code
snippets, any errors you are getting, concrete examples and perhaps also some
screenshots. Share your attempt, explain the expected results and compare
them to the current results.

Also try to make the information easily accessible by sharing code
or assignment descriptions directly on Discord, not behind a link or
PDF-file; provide some guidance for long code snippets and ensure
the code is well formatted and has syntax highlighting. Kindly read through
https://stackoverflow.com/help/how-to-ask for more.

With enough info, someone knows the answer for sure ๐Ÿ‘

boreal socket
#

.

grand garnet
#

hi hi hellow

#

time to start some project work

#

ok yep im so cclose to giving up ๐Ÿ˜ญ

#

I am so done for

boreal socket
#

why though

grand garnet
#

it isn't even rendering anything ๐Ÿ˜ญ

#

OK NAH

#

bro

#

it works but when it is like very very small

#

why is it lagging so mucchhh

boreal socket
#

hard to tell without seeing code

grand garnet
#

oh

#

lemme upload it to github

#

there we go

#

i know it's not the actual fluid making everything lag because the same exact fluid class works with AWT

boreal socket
#

going to check it later

grand garnet
#

okayy

#

tysm man

#

any rough idea on what it could be though?

boreal socket
#

not without looking at it lol

grand garnet
#

oh ok lmaoo

#

I have a feeling it's about how often these are being called

#

ok

#

it works

#

but it is veryyy laggy

#

i updatd the master2 branch

boreal socket
#

yeah let me test some stuff

grand garnet
#

sure

#

just gonna state what i think it is

#

the FPS is too low that there are too many inputs being added

boreal socket
#

can you explain me how to use the simulation?

grand garnet
#

umm

#

so clicking on the screen at a point adds denisty to that point

#

dragging essentially adds density whilst also moving the density in a given direction

#

that's prety much it

boreal socket
#

doesnt work somehow

grand garnet
#

what cpu you got?

boreal socket
#

uh how is that related?

grand garnet
#

i think it's a lag issue

#

because

boreal socket
#

but amd ryzen 7 5800x3d

grand garnet
#

ok yh nvm not lag issue

#

i have a 1700x

#

what happens when you start it uP?

boreal socket
#

wdym?

#

also do I need to do stuff here

grand garnet
#

oh nooo

#

ok

#

nvm

#

i think you downloaded the wrong branch

#

did you do master2?

boreal socket
#

yeah I am lol

#

๐Ÿ’€

#

mb

grand garnet
#

๐Ÿ˜ญ

boreal socket
grand garnet
#

the scene im simply testing out the simulation on is the TEST_SIMULATION

boreal socket
#

ok now it works

#

but where is the UI pepe_sad

grand garnet
#

im going to implement into UI later

#

but for me it doesn't run ๐Ÿ˜ญ

#

like it's just veyr laggy

#

whereas awt is a lot smoother

boreal socket
#

ok walk me through

#

which code should I look at

grand garnet
boreal socket
#

the problem lies here

#

and I think I know why

#

you iterate with:
outer loop -> WIDTH
inner loop -> HEIGHT

#

but instead it should be
outer loop -> HEIGHT
inner loop -> WIDTH

grand garnet
#

pretty sure that doesn't matter because it's a 1D array?

boreal socket
#

it kinda does

#

cpu does stuff under the hood

grand garnet
#

i changed it and it still lags and crashes

boreal socket
#

but it wont make such a big difference

#

not much difference

grand garnet
#

mhmmm

#

pretty sure the Fluid isn't the problem

#

because it works fine in awt with the exact same implementation

#

i think it's to do with the mouse listening

boreal socket
#

this is a big problem as well

grand garnet
#

is the thing on the left how long it takes to run?

boreal socket
#

yea

#

kinda

grand garnet
#

hmm

#

so updating takes too long

#
    public void update(double deltaTime) {
        addSourcesFromUI();
        fluid.step(deltaTime);
    }```
cedar tigerBOT
grand garnet
#

which one takes longer?

boreal socket
#

let me try some stuff

#

give me some time

grand garnet
#

ok sorry ๐Ÿ˜ญ

boreal socket
#

all good

grand garnet
#

ummm

boreal socket
#

bro ๐Ÿ’€

grand garnet
#

bro

#

hes in the chat

#

look

boreal socket
#

no need to ping him

grand garnet
#

๐Ÿ˜ญ

boreal socket
#
    @Override
    public synchronized void render(DataProvider pixelStream) {
        GraphicsContext gc = canvas.getGraphicsContext2D();
        PixelWriter pixelWriter = gc.getPixelWriter();

        for (int y = 0; y <  canvas.getHeight() ; y++) {
            for (int x = 0; x < canvas.getWidth(); x++) {
                byte pixelValue = pixelStream.provideData(x, y);

                int color = pixelValue & 0xFF;
                pixelWriter.setColor(x, y, Color.grayRgb(color));
            }
        }
    }
#

this works a lot better for me

grand garnet
#

yeahh it does

#

but

#

for me it freezes and crashes after like 10 seconds lol

boreal socket
#

yeah needs more investigation

#

I also think synchronization is bad here

grand garnet
#

hmm

boreal socket
grand garnet
#

so i should just use public void?

boreal socket
#

16gb ๐Ÿ’€

grand garnet
#

WHAT THE FUCK

#

how is it using so much ๐Ÿ˜ญ

boreal socket
#

time to find it out

#

would be a cool experience for you to learn about intellijs profiler

grand garnet
#

only using 133mb for me

boreal socket
#

even after spamming "fluid"?

grand garnet
#

wdym spamming fluid

#

it says 140mb heap memory

boreal socket
#

like using the simulation lol

grand garnet
#

tbh the awt one was worse

boreal socket
#

the problem why its crashing is because of memory

#

one problem I see is your step method

grand garnet
#

hmm

boreal socket
#

it creates multiple double array using size which in this case is 302 * 302

#

for me it seems like all of this can be fixed using streams

#

maybe

#

maybe not actually

#

damn

grand garnet
#

but then why does this work in awt with no lag

#

the array creations should be fine

boreal socket
#

there must be a difference

grand garnet
#

no difference in the fluid class

#

i can say that

grand garnet
# boreal socket

most the memory problems are coming from this render method no?

boreal socket
#

yea

#

25gb

#

but I cant tell why

grand garnet
#

ohh

#

i think i know why

#

is it because i am passing in the class as a parameter every single time

#

so it keeps settingit to a new parameter each time

boreal socket
#

but in which way is that a problem?

grand garnet
#

creating a new variable each time perhaps?

boreal socket
#

that doesnt case a problem

#

its weird because it looks more like an internal thing

#

for me it seems like its not clearing the old pixels

#

302 * 302 = 91204 pixels

grand garnet
#

maybe create a new canvas and replace the old one?

#

might do the job

grand garnet
#

how come

boreal socket
#

thats not how its supposed to be used

#

I just checked

#

the internal GraphicsContext uses some GrowableDataBuffer

#

so it seems like its not replacing bytes

#

but instead always appending

#

which lets me question the internal of javafx peepo_think

grand garnet
#

๐Ÿ˜ญ

#

could i chang ethat internal appending?

boreal socket
#

I am checking right now

#

@steep elbow you know smth about this? why is it storing all the pixels?

grand garnet
#

wot

boreal socket
#

?

grand garnet
#

bonk

#

๐Ÿ˜ˆ

boreal socket
#

can you stop pls

#

this is a question thread

upbeat narwhal
#

mb

grand garnet
#

it's ok

#

bonk make a request in #server-suggestions

dense hare
boreal socket
#

but its not pepe_sad

dense hare
#

how large is the image?

boreal socket
#

300x300

#

uh maybe 400x400 actually

grand garnet
#

it's 300

boreal socket
#

what about your .fxml file though?

<AnchorPane prefHeight="400.0" prefWidth="400.0" xmlns="http://javafx.com/javafx/17.0.2-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.fluidity.program.ui.controllers.TestSimulationController">
    <children>
        <Canvas fx:id="canvas" height="400.0" onMouseDragged="#mouseDragged" onMousePressed="#mousePressed" onMouseReleased="#mouseReleased" width="400.0" />
    </children>
</AnchorPane>
grand garnet
#

oh yeah

#

it was for a test anyways

boreal socket
#

problems I can already tell:

  • you call render from a different thread than the FX Thread
  • you always draw each pixel even though many didnt change
boreal socket
#

all rendering happens on the fx thread

#

and if you do changes then you should also do that on the fx thread

#

my guess would be that changing the canvas from a different thread fucks up the clearing of the buffer somehow

#

let me try to create my own solution about the threading stuff

#

but thats going to take longer than just 10min

#

I probably wont even be able to finish it today, because I am gone later

#

also you should really make your simulation thread a daemon thread

#

or terminate it manually if someone closes the ui

#

otherwise the application continues running

#

what is the use of TPS btw?

dense hare
#

ill take a look when i get home too

boreal socket
#

I am trying to fix it by letting the Simulation (drawing) extends AnimationTimer and then making another thread to handle all the calculation and updating the fluid stuff

#

the handle method provided by AnimationTimer is providing the delta time as an argument

#

and the handle method runs on the FX Thread

#

handled by javafx itself

boreal socket
#

ok I think I fixed it

#

it still uses a lot of memory because of Fluid.java which I didnt touch at all

#

but it doesnt crash

#

and doesnt lag

#

I am not sure about the synchronization of Fluid though

#

I dont know how to properly make a thread safe usage of the double array

#

dioxin might know

#

otherwise I think this is fine

#

also you might want to make the static variables CELL_LENGTH and FPS non static instead

#

just for the simplicity made them static

#

hope this helps

#

really need to go now

#

cant improve it further

#

@grand garnet @dense hare

#

you might dont even need to use another thread

#

and put everything into the handle of the AnimationTimer

#

but not sure how heavy the fluid calculations will be

#

I am not that much of a pro of concurrency and threading

#

like using synchronization might block the handle method anyways

#

so why not directly doing the fluid calculations inside the handle method

#

needs testing

#

and the calculation needs like 5ms or smth

#

which probably can be improved a lot

#

internally

#

back in like 3h

grand garnet
#

ok

#

i will have a look

#

but i had a cool brainy moment

#

why not combine the buffered image from awt with javafx?

#

and then use jfx for scene switching only

steep elbow
#

@grand garnet why can't you just fillRect on the graphics context ?

grand garnet
#

im ngl i don't know whta you mean lol

steep elbow
#

?

#

look at its methods

#

it's the same as awt or swing

#

you can use it to draw stuff

#

so just draw rectangles

grand garnet
#

and i can still use the delta time I originally made?

boreal socket
steep elbow
boreal socket
#

It worked

#

Try the branch

steep elbow
#

?

boreal socket
#

Whatever the solution I shared works

#

But maybe needs some improvements

steep elbow
#

You are really overcomplicating things

#

you just need to draw rect in a loop

#

that's all

grand garnet
#

ahh so instead of calculating for each pixel, I work out for one pixel and then apply to every cell

boreal socket
#

And if you use threading you also need to use Platform.runLater for drawing

steep elbow
boreal socket
#

The struggle wasnโ€™t the displaying itself

#

But that there was a memory leak

#

Check the chat above

boreal socket
#

My guess is that the leak comes from threading

#

Because this code executed outside the fx thread

grand garnet
#

how does this look ala

@Override
    public void render(DataProvider pixelStream) {
        GraphicsContext gc = canvas.getGraphicsContext2D();

        for (int y = 0; y <  canvas.getHeight() ; y += pixelStream.getCellLength()) {
            for (int x = 0; x < canvas.getWidth(); x += pixelStream.getCellLength()) {
                byte pixelValue = pixelStream.provideData(x, y);
                int color = pixelValue & 0xFF;
                gc.setFill(Paint.valueOf(Color.grayRgb(color).toString()));
                gc.fillRect(x, y, pixelStream.getCellLength(), pixelStream.getCellLength());
            }
        }
    }
cedar tigerBOT
boreal socket
#

Why Paint.valueOf

#

Also this wonโ€™t logically work

#

Because thatโ€™s not what you want

grand garnet
#

wut

boreal socket
#

Try it out, idk

grand garnet
#

oioooh

#

it does run

#

but then it says this after a while

boreal socket
#

Your structure for the simulation is wrong in the first place

grand garnet
#

wut

#

wdym by that

boreal socket
#

You would want to use AnimationTimer, the official non threaded way of a continuous loop (animation)

#

Itโ€™s literally made for this

#

Let me further improve the code when I get home

grand garnet
#

how do i view memory capackty?

steep elbow
grand garnet
steep elbow
#

what

#

concurrency problem ?

grand garnet
#

so do i have to do what squid said

#

because my simulation is running in this thread

#
private void startSimulationThread() {
        simulationThread = new Thread(this);
        simulationThread.start();
    }

    @Override
    public void run() {
        double deltaTimeSeconds = 1.0 / TPS;
        double lastFrameTime = nanosToSeconds(System.nanoTime());
        double secondsToConsume = 0.0;

        while (simulationThread != null) {
            double currentFrameTime = nanosToSeconds(System.nanoTime());
            double lastFrameNeeded = currentFrameTime - lastFrameTime;
            lastFrameTime = currentFrameTime;

            secondsToConsume += lastFrameNeeded;
            while (secondsToConsume >= deltaTimeSeconds) {
                update(deltaTimeSeconds);
                secondsToConsume -= deltaTimeSeconds;
            }

            render();

            double currentFPS = 1.0 / lastFrameNeeded;
            if (currentFPS > FPS) {
                double targetSecondsPerFrame = 1.0 / FPS;
                double secondsToWaste = Math.abs(targetSecondsPerFrame - lastFrameNeeded) / 1000000;
                try {
                    TimeUnit.SECONDS.sleep(secondsToMillis(secondsToWaste));
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }```
grand garnet
#

it's a handler method within the same class:

    public void render() {
        mouseAdapter.render(this);
    }```

within the mouse adapter:
```java
@Override
    public void render(DataProvider pixelStream) {
        GraphicsContext gc = canvas.getGraphicsContext2D();

        for (int y = 0; y <  canvas.getHeight() ; y += pixelStream.getCellLength()) {
            for (int x = 0; x < canvas.getWidth(); x += pixelStream.getCellLength()) {
                byte pixelValue = pixelStream.provideData(x, y);
                int color = pixelValue & 0xFF;
                gc.setFill(Color.grayRgb(color));
                gc.fillRect(x, y, pixelStream.getCellLength(), pixelStream.getCellLength());
            }
        }
    }```
cedar tigerBOT
boreal socket
#

its called in the run method (in a different thread)

steep elbow
boreal socket
#

there is none

#

thats what I think caused the memory leak

steep elbow
#

this is definitelly wrong

boreal socket
#

ik that it makes no sense

#

but I cant look into javafx internals

steep elbow
#

you need to copy the whole grid and pass it in runlater

#

and then display it

boreal socket
#

idk why it would cause a memory leak though

#

but it clearly did

steep elbow
#

cause concurrency problems

boreal socket
#

yeah but that wouldnt explain it entirely right?

steep elbow
#

I have no idea how javafx didn't detect that tho

boreal socket
#

thats what kinda confused me

steep elbow
#

normally javafx would detect that it is the wrong thread and crash

boreal socket
#

but it clearly runs in a different thread

steep elbow
steep elbow
#

so this is your priority to fix

boreal socket
#

I checked, canvas uses some growable data buffer internally

#

ig it couldnt properly clear it

#

because of concurrency problems

#

and thus it continued to grow and grow

#

and ended up filling my whole memory

#

in 10sec

#

and then crash

grand garnet
#

lemme check docs rq

#

wait

#

what should i search up ๐Ÿ˜ญ

boreal socket
#

javafx is single threaded

#

that means that all UI stuff etc is handled on the FX Thread

#

and if you do UI stuff outside that it will break your javafx application

grand garnet
#

o

#

h

#

noooo

steep elbow
#

same for awt and swing

#

or any gui framework in any language btw

#

so what you have to do is simple

#
  1. copy the data to display
  2. call runlater
  3. display it
#

also, how are you storing the data to display ?

boreal socket
grand garnet
#

in an array

boreal socket
#

Fluid.java

#

which also needs improvements

grand garnet
#

BRUH

steep elbow
grand garnet
#

i dropped my lego

grand garnet
boreal socket
#

I just get to 2 GB ram for 300x300 simulation

grand garnet
#

and it's a 1D array

steep elbow
boreal socket
boreal socket
#

but the canvas is 300x300

#

dont ask me lol

steep elbow
grand garnet
#

double

steep elbow
grand garnet
#

@boreal socket the padding is for borders of the fluid

steep elbow
#

yea this is nothing to copy

#

so you can afford to array.clone() this

#

once per frame

steep elbow
boreal socket
#

the thing is he creates additional arrays each time step:

double[] u_prev = new double[size];
double[] v_prev = new double[size];
double[] dens_prev = new double[size];

// this 2 times (because project() is called twice)
        double[] pressure = new double[size];
        double[] divergenceField = new double[size];
#

seems like many arrays for this

#

I think you can improve here

#

but didnt look much into the logic yet

#

302 * 302 * 8 * 7 = 5 107 424
hm ok but thats like only 5 MB

#

not sure where the other ram stuff is coming from

#

going to look in a second

boreal socket
#

8 Bytes per double

#

7 double arrays with 302 x 302 in one time step

steep elbow
#

7???

steep elbow
boreal socket
#

But yeah if that runs 30 times a second you end up with 150 MB

#

But still not really much

#

GC will kick in

#

Everything gone

steep elbow
#

do you copy the arrays each time ?

#

?

#

@boreal socket

boreal socket
#

idk

#

not my code

#

lol

steep elbow
boreal socket
#

because I know that

#

lol

steep elbow
boreal socket
#

not like I am saying there will be 150 MB at once

steep elbow
#

????

boreal socket
steep elbow
#

why are you saying

#

But yeah if that runs 30 times a second you end up with 150 MB

#

??

boreal socket
#

and the simulation is running at 30 fps

#

so 30 time steps

steep elbow
#

where does the 150MB come from ?

boreal socket
#

which 30 MB?

grand garnet
#

im still lost

steep elbow
#

150

#

what are you talking about ?

#

what 150mb are you talking about ?

boreal socket
# steep elbow 150

5 MB per time step * 30 time steps per second will end up with 150 MB per second

steep elbow
boreal socket
#

they are just newly created arrays

steep elbow
#

if you don't do copy

#

it's 5mb period

steep elbow
steep elbow
#

but

#

I don't understand

#

those arrays

grand garnet
steep elbow
#

are they ever assigned to the fields ?

boreal socket
#

I am just saying what gets created in one second

grand garnet
#

ahh

#

but

#

it doesn't matter if it's getting destroyed?

boreal socket
#

no it doesnt

steep elbow
#

you could go way faster

boreal socket
#

but I am wondering because I have 2 GB usage

steep elbow
boreal socket
#

and that code takes like 5ms per time step

grand garnet
boreal socket
#

but there are additional 3 * 302 x 302 double arrays

#

as fields

steep elbow
boreal socket
steep elbow
#

-_-

boreal socket
#

they are probably used for the simulation logic

steep elbow
#

anyway

#

pentium

grand garnet
#

it's for storing the densities and velocities before different fluid steps such as diffusion

steep elbow
#

fix the concurrency problems first

boreal socket
#
        this.dt = deltaTime;
        double[] u_prev = new double[size];
        double[] v_prev = new double[size];
        double[] dens_prev = new double[size];

        diffuse(1, u_prev, u, viscosity);
        diffuse(2, v_prev, v, viscosity);

        project(u_prev, v_prev);

        advect(1, u, u_prev, u_prev, v_prev);
        advect(2, v, v_prev, u_prev, v_prev);
        project(u, v);

        diffuse(0, dens_prev, dens, diffusionRate);
        advect(0, dens, dens_prev, u, v);
grand garnet
#

im using chat gpt to help ๐Ÿ˜ญ

steep elbow
grand garnet
#

i don't want to annoy you guys too much lmao

steep elbow
grand garnet
#

yeah true

#

lol

#

got me there

#

ok

steep elbow
#

and pretty sure you are going to do wrong things

#

that we will have to fix anyway

grand garnet
#

so from what I understand

#

rendering works in 3 steps

#
  1. having that data to display
boreal socket
steep elbow
#

well yea

grand garnet
#
  1. call runlater
  2. display it
steep elbow
#

i gave the solution

grand garnet
#

it's because

#

wait

#

basically

#

you know how my teacher

#

is very teachery

#

doesn't like me using all the fancy stuff

boreal socket
grand garnet
steep elbow
grand garnet
boreal socket
#

using the standard provided javafx library is not fancy pepe_sad

grand garnet
#

and I have an interface for which any class that implements it can provide that data

steep elbow
grand garnet
#

hmm

#

yeah ok

steep elbow
#
Platform.runLater(() -> render(density.clone()));

it's basically as simple as this

#

you just do that

grand garnet
#

oh

steep elbow
#

and render only use density copy (and graphics context), nothing else

#

NOTHING

#

ELSE

grand garnet
#

Ok ๐Ÿ˜ญ

#

but

grand garnet
#

im gonna have to somehow get this to my rendering class no?

steep elbow
#

wdym