unsure on how to Load multiply objects at run time

I’m having difficulties figuring out how to load in objects at runtime. I’ve tried a lot of methods but I need assistance. here’s the code its a small engine I threw into itself to form itself in like a few hours this is like my 1st real java project so I don’t have much skill and have been riding online forums for the algorithms a lot.

here is ALL the code starting with the three important files:

Main.java:

package neptunian_engine;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Main {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame frame = new JFrame("3D Engine");
            Scene scene = new Scene();
            Camera camera = new Camera(new Vector3D(0, 0, 5), new Vector3D(0, 0, 0));
            Renderer renderer = new Renderer(scene, camera);
            SoundBox soundbox = new SoundBox(); // Initialize your SoundBox and load sounds
            
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setSize(800, 600);
            frame.add(renderer);
            frame.setVisible(true);

            // Add a sample object
            try {
                Object3D object = ObjLoader.loadObj("Guard_torso.obj"); // Ensure the file path is correct
                Object3D object2 = ObjLoader.loadObj("test1.obj"); // Ensure the file path is correct
                scene.addObject(object);
                scene.addObject(object2);
            } catch (Exception e) {
                e.printStackTrace();
            }
            
            
              
            

            // Camera controls
            CameraController cameraController = new CameraController(camera, soundbox);
            MouseController mouseController = new MouseController(camera);

            renderer.addKeyListener(cameraController);
            renderer.addMouseMotionListener(mouseController);
            renderer.setFocusable(true);
            renderer.requestFocusInWindow();

            // Timer to update the scene
            Timer timer = new Timer(16, e -> {
                cameraController.updateCameraMovement();
                renderer.repaint();
            });
            timer.start();
        });
    }
}

ObjLoader.java:

package neptunian_engine;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class ObjLoader {
    public static Object3D loadObj(String filename) throws IOException {
        List<Vector3D> vertices = new ArrayList<>();
        List<int[]> faces = new ArrayList<>();
        BufferedReader reader = new BufferedReader(new FileReader(filename));
        String line;
        while ((line = reader.readLine()) != null) {
            if (line.startsWith("v ")) {
                String[] parts = line.split(" ");
                float x = Float.parseFloat(parts[1]);
                float y = Float.parseFloat(parts[2]);
                float z = Float.parseFloat(parts[3]);
                vertices.add(new Vector3D(x, y, z));
            } else if (line.startsWith("f ")) {
                String[] parts = line.split(" ");
                int[] face = new int[parts.length - 1];
                for (int i = 1; i < parts.length; i++) {
                    face[i - 1] = Integer.parseInt(parts[i].split("/")[0]) - 1; // assuming faces are 1-indexed
                }
                faces.add(face);
            }
        }
        reader.close();
        return new Object3D(vertices, faces);
    }
}

Object3D.java:

package neptunian_engine;


import java.util.List;

public class Object3D {
    private List<Vector3D> vertices;
    private List<int[]> faces;
    private Vector3D position;

    public Object3D(List<Vector3D> vertices, List<int[]> faces) {
        this.vertices = vertices;
        this.faces = faces;
        this.position = new Vector3D(0, 0, 0);
    }

    public List<Vector3D> getVertices() {
        return vertices;
    }

    public List<int[]> getFaces() {
        return faces;
    }

    public Vector3D getPosition() {
        return position;
    }

    public void setPosition(Vector3D position) {
        this.position = position;
    }
}

here is the rest of the codebase

Vector3D.java:

package neptunian_engine;

public class Vector3D {
    public float x, y, z;

    public Vector3D(float x, float y, float z) {
        this.x = x;
        this.y = y;
        this.z = z;
    }

    public void add(Vector3D other) {
        this.x += other.x;
        this.y += other.y;
        this.z += other.z;
    }

    public void scale(float scalar) {
        this.x *= scalar;
        this.y *= scalar;
        this.z *= scalar;
    }
}

Camera.java:

package neptunian_engine;

public class Camera {
    private Vector3D position;
    private Vector3D rotation;

    public Camera(Vector3D position, Vector3D rotation) {
        this.position = position;
        this.rotation = rotation;
    }

    public Vector3D getPosition() {
        return position;
    }

    public void setPosition(Vector3D position) {
        this.position = position;
    }

    public Vector3D getRotation() {
        return rotation;
    }

    public void setRotation(Vector3D rotation) {
        this.rotation = rotation;
    }

    public void move(Vector3D delta) {
        this.position.x += delta.x;
        this.position.y += delta.y;
        this.position.z += delta.z;
    }

    public void rotate(Vector3D delta) {
        this.rotation.x += delta.x;
        this.rotation.y += delta.y;
        this.rotation.z += delta.z;
    }

    public Vector3D getForwardVector() {
        return new Vector3D(
                (float) Math.cos(Math.toRadians(rotation.y)),
                0,
                (float) Math.sin(Math.toRadians(rotation.y))
        );
    }

    public Vector3D getRightVector() {
        return new Vector3D(
                (float) Math.sin(Math.toRadians(rotation.y)),
                0,
                (float) -Math.cos(Math.toRadians(rotation.y))
        );
    }
}

Renderer.java:

package neptunian_engine;

import javax.swing.*;
import java.awt.*;
import java.util.List;
import java.util.Random;

public class Renderer extends JPanel {
    private Scene scene;
    private Camera camera;

    public Renderer(Scene scene, Camera camera) {
        this.scene = scene;
        this.camera = camera;
        this.setFocusable(true);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        renderScene(g);
    }

    private void renderScene(Graphics g) {
        for (Object3D object : scene.getObjects()) {
            drawObject(g, object);
        }
    }

    private void drawObject(Graphics g, Object3D object) {
        List<Vector3D> vertices = object.getVertices();
        List<int[]> faces = object.getFaces();
        Random rand = new Random();

        for (int[] face : faces) {
            Polygon polygon = new Polygon();
            for (int vertexIndex : face) {
                Vector3D vertex = vertices.get(vertexIndex);
                int x = (int) ((vertex.x + object.getPosition().x) * 100 + getWidth() / 2);
                int y = (int) ((-vertex.y - object.getPosition().y) * 100 + getHeight() / 2);
                polygon.addPoint(x, y);
            }
            g.setColor(new Color(rand.nextFloat(), rand.nextFloat(), rand.nextFloat()));
            g.fillPolygon(polygon);
        }
    }
}

Scene.java:

package neptunian_engine;

import java.util.ArrayList;
import java.util.List;

public class Scene {
    private List<Object3D> objects;

    public Scene() {
        objects = new ArrayList<>();
    }

    public void addObject(Object3D object) {
        objects.add(object);
    }

    public List<Object3D> getObjects() {
        return objects;
    }
}

CameraController:

package neptunian_engine;

import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

public class CameraController extends KeyAdapter {
    private Camera camera;
    private boolean[] keys = new boolean[256];
    private SoundBox soundbox;

    public CameraController(Camera camera, SoundBox soundbox) {
        this.camera = camera;
        this.soundbox = soundbox;
    }

    @Override
    public void keyPressed(KeyEvent e) {
        int key = e.getKeyCode();
        if (key >= 0 && key < keys.length) {
            keys[key] = true;
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {
        int key = e.getKeyCode();
        if (key >= 0 && key < keys.length) {
            keys[key] = false;
        }
    }

    public void updateCameraMovement() {
        Vector3D forward = camera.getForwardVector();
        Vector3D right = camera.getRightVector();

        Vector3D movement = new Vector3D(0, 0, 0);
        float speed = 0.1f;

        if (keys[KeyEvent.VK_W]) {
            movement.add(forward);
        }
        if (keys[KeyEvent.VK_S]) {
            movement.add(new Vector3D(-forward.x, -forward.y, -forward.z));
        }
        if (keys[KeyEvent.VK_A]) {
            movement.add(new Vector3D(-right.x, -right.y, -right.z));
        }
        if (keys[KeyEvent.VK_D]) {
            movement.add(right);
            soundbox.play("Gunfire"); // Play sound when moving right
        }
        if (keys[KeyEvent.VK_SPACE]) {
            movement.y += speed;
        }
        if (keys[KeyEvent.VK_SHIFT]) {
            movement.y -= speed;
        }

        movement.scale(speed);
        camera.move(movement);
    }
}

MouseController:

package neptunian_engine;

import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

public class MouseController extends MouseAdapter {
    private Camera camera;
    private int lastX, lastY;

    public MouseController(Camera camera) {
        this.camera = camera;
    }

    @Override
    public void mouseDragged(MouseEvent e) {
        int x = e.getX();
        int y = e.getY();

        int deltaX = x - lastX;
        int deltaY = y - lastY;

        camera.rotate(new Vector3D(deltaY * 0.1f, deltaX * 0.1f, 0));

        lastX = x;
        lastY = y;
    }

    @Override
    public void mousePressed(MouseEvent e) {
        lastX = e.getX();
        lastY = e.getY();
    }
}

SoundBox.java:

package neptunian_engine;

import javax.sound.sampled.*;
import java.io.*;
import java.util.HashMap;
import java.util.Map;

public class SoundBox {
    private Map<String, Clip> soundMap;

    public SoundBox() {
        this.soundMap = new HashMap<>();
        // Initialize sound loaders here
        loadSound("Gunfire", "sound_effects/Beefy-custom-rife.wav"); // guns
        //loadSound("Gunfire2", "sound_effects/Beefy-custom-rife.wav"); // Example sound
        // Add more sounds here in a list
    }

    private void loadSound(String soundName, String filePath) {
        try {
            File soundFile = new File(filePath);
            if (!soundFile.exists()) {
                throw new FileNotFoundException("File not found: " + filePath);
            }

            AudioInputStream audioIn = AudioSystem.getAudioInputStream(soundFile);
            Clip clip = AudioSystem.getClip();
            clip.open(audioIn);
            soundMap.put(soundName, clip);

        } catch (UnsupportedAudioFileException | LineUnavailableException | IOException e) {
            e.printStackTrace();
        }
    }

    public void play(String soundName) {
        Clip clip = soundMap.get(soundName);
        if (clip != null) {
            clip.setFramePosition(0); // Rewind to the beginning
            clip.start();
        }
    }

    // Optional: Stop a specific sound
    public void stop(String soundName) {
        Clip clip = soundMap.get(soundName);
        if (clip != null && clip.isRunning()) {
            clip.stop();
        }
    }

    // Optional: Stop all sounds
    public void stopAll() {
        for (Clip clip : soundMap.values()) {
            if (clip.isRunning()) {
                clip.stop();
            }
        }
    }
}

SkeletonBox.java:

package neptunian_engine;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class SkeletonBox {
    private Map<String, Animation> animations = new HashMap<>();
    private Skeleton skeleton;
    private float animationTime = 0;

    // Class definitions for supporting classes (Matrix4x4, Vector3D, Quaternion, Bone, Skeleton, Keyframe, Animation) here

    public SkeletonBox() {
        // Constructor: Initialize necessary data
    }

    public void loadSkeleton(String filePath) {
        List<Bone> bones = new ArrayList<>();

        try (BufferedReader br = new BufferedReader(new FileReader(filePath))) {
            String line;
            while ((line = br.readLine()) != null) {
                String[] tokens = line.split(" ");
                if (tokens[0].equals("bone")) {
                    String name = tokens[1];
                    int parentIndex = Integer.parseInt(tokens[2]);
                    float px = Float.parseFloat(tokens[3]);
                    float py = Float.parseFloat(tokens[4]);
                    float pz = Float.parseFloat(tokens[5]);
                    float qx = Float.parseFloat(tokens[6]);
                    float qy = Float.parseFloat(tokens[7]);
                    float qz = Float.parseFloat(tokens[8]);
                    float qw = Float.parseFloat(tokens[9]);
                    Vector3D position = new Vector3D(px, py, pz);
                    Quaternion rotation = new Quaternion(qx, qy, qz, qw);
                    bones.add(new Bone(name, parentIndex, position, rotation));
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        this.skeleton = new Skeleton(bones);
    }

    public void loadAnimation(String name, String filePath) {
        List<Keyframe> keyframes = new ArrayList<>();
        float duration = 0;
        float ticksPerSecond = 24;
        List<Matrix4x4> transforms = new ArrayList<>();

        try (BufferedReader br = new BufferedReader(new FileReader(filePath))) {
            String line;
            while ((line = br.readLine()) != null) {
                String[] tokens = line.split(" ");
                switch (tokens[0]) {
                    case "duration":
                        duration = Float.parseFloat(tokens[1]);
                        break;
                    case "ticks_per_second":
                        ticksPerSecond = Float.parseFloat(tokens[1]);
                        break;
                    case "bone":
                        // No operation, handled below in keyframe
                        break;
                    case "keyframe":
                        float time = Float.parseFloat(tokens[1]);
                        float px = Float.parseFloat(tokens[2]);
                        float py = Float.parseFloat(tokens[3]);
                        float pz = Float.parseFloat(tokens[4]);
                        float qx = Float.parseFloat(tokens[5]);
                        float qy = Float.parseFloat(tokens[6]);
                        float qz = Float.parseFloat(tokens[7]);
                        float qw = Float.parseFloat(tokens[8]);
                        Vector3D position = new Vector3D(px, py, pz);
                        Quaternion rotation = new Quaternion(qx, qy, qz, qw);
                        transforms.add(Matrix4x4.fromPositionRotation(position, rotation));
                        keyframes.add(new Keyframe(time, new ArrayList<>(transforms)));
                        transforms.clear();
                        break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        Animation animation = new Animation(name, keyframes, duration);
        animations.put(name, animation);
    }

    public void play(String animationName, float deltaTime) {
        Animation animation = animations.get(animationName);
        if (animation == null) {
            System.out.println("Animation not found: " + animationName);
            return;
        }

        animationTime += deltaTime;
        if (animationTime > animation.duration) {
            animationTime = 0; // Loop the animation
        }

        List<Matrix4x4> boneTransforms = animation.getTransformsAtTime(animationTime);
        skeleton.applyPose(boneTransforms);
    }

    // Class definitions
    public static class Matrix4x4 {
        // Placeholder for matrix data and operations
        public static Matrix4x4 identity() {
            return new Matrix4x4();
        }

        public static Matrix4x4 fromPositionRotation(Vector3D position, Quaternion rotation) {
            return new Matrix4x4();
        }

        public Matrix4x4 multiply(Matrix4x4 other) {
            return new Matrix4x4();
        }

        public void set(Matrix4x4 other) {
            // Set this matrix to the values of the other matrix
        }
    }

    public static class Vector3D {
        public float x, y, z;

        public Vector3D(float x, float y, float z) {
            this.x = x;
            this.y = y;
            this.z = z;
        }
    }

    public static class Quaternion {
        public float x, y, z, w;

        public Quaternion(float x, float y, float z, float w) {
            this.x = x;
            this.y = y;
            this.z = z;
            this.w = w;
        }
    }

    public static class Bone {
        public String name;
        public int parentIndex;
        public Vector3D position;
        public Quaternion rotation;

        public Bone(String name, int parentIndex, Vector3D position, Quaternion rotation) {
            this.name = name;
            this.parentIndex = parentIndex;
            this.position = position;
            this.rotation = rotation;
        }
    }

    public static class Skeleton {
        public List<Bone> bones;

        public Skeleton(List<Bone> bones) {
            this.bones = bones;
        }

        public void applyPose(List<Matrix4x4> boneTransforms) {
            for (int i = 0; i < bones.size(); i++) {
                Bone bone = bones.get(i);
                if (bone.parentIndex >= 0) {
                    boneTransforms.get(i).set(boneTransforms.get(bone.parentIndex).multiply(Matrix4x4.fromPositionRotation(bone.position, bone.rotation)));
                } else {
                    boneTransforms.get(i).set(Matrix4x4.fromPositionRotation(bone.position, bone.rotation));
                }
            }
        }
    }

    public static class Keyframe {
        public float time;
        public List<Matrix4x4> transforms;

        public Keyframe(float time, List<Matrix4x4> transforms) {
            this.time = time;
            this.transforms = transforms;
        }
    }

    public static class Animation {
        public String name;
        public List<Keyframe> keyframes;
        public float duration;

        public Animation(String name, List<Keyframe> keyframes, float duration) {
            this.name = name;
            this.keyframes = keyframes;
            this.duration = duration;
        }

        public List<Matrix4x4> getTransformsAtTime(float time) {
            // Interpolate between keyframes to get bone transforms at the given time
            // This is a simplified example, actual interpolation logic should be implemented
            Keyframe current = keyframes.get(0);
            for (Keyframe kf : keyframes) {
                if (kf.time > time) break;
                current = kf;
            }
            return current.transforms;
        }
    }
}

Physics.java:

package neptunian_engine;

import java.util.Vector;

public class Physics {

    public void velocity3D (){
        
        // add all the junk so I can have my HEADCRABS idk
        
    }
    
    
}
    
}

I tried so many things

hashmap layers
File reader but I couldn’t figure anything out, and I refuse to stain my code with chatgpt
also the camera doesn’t work.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật