Skip to content

Commit

Permalink
Merge pull request #70 from ArtifactForms/working2
Browse files Browse the repository at this point in the history
Working2
  • Loading branch information
ArtifactForms authored Jan 16, 2025
2 parents 21be82f + 647b448 commit 1dc5fa9
Show file tree
Hide file tree
Showing 24 changed files with 1,617 additions and 249 deletions.
147 changes: 147 additions & 0 deletions src/main/java/engine/animation/skeleton/Bone.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
package engine.animation.skeleton;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import math.Matrix4;

public class Bone {

private final String name;
private Bone parent;
private final List<Bone> children;
private Matrix4 localTransform;
private Matrix4 globalTransform;
private Matrix4 inverseBindPose;
private boolean transformDirty = true;
private float weight;
private int index;

public Bone(String name) {
if (name == null) {
throw new IllegalArgumentException("Name cannot be null.");
}
this.name = name;
this.children = new ArrayList<>();
this.localTransform = new Matrix4().identity();
this.globalTransform = new Matrix4().identity();
this.weight = 1.0f;
}

public void updateGlobalTransform() {
if (!transformDirty) return;
globalTransform =
(parent != null) ? parent.globalTransform.multiply(localTransform) : localTransform;
transformDirty = false;
}

public void updateChildrenTransforms() {
for (Bone child : children) {
child.markDirty();
child.updateGlobalTransform();
child.updateChildrenTransforms();
}
}

public void markDirty() {
transformDirty = true;
}

public void addChild(Bone child) {
if (child == null) {
throw new IllegalArgumentException("Child bone cannot be null.");
}
if (isAncestorOf(child)) {
throw new IllegalArgumentException("Cannot add a child that would create a cycle.");
}
if (child.getParent() != null) {
child.getParent().removeChild(child);
}
children.add(child);
child.setParent(this);
}

private boolean isAncestorOf(Bone bone) {
Bone current = this;
while (current != null) {
if (current == bone) {
return true;
}
current = current.getParent();
}
return false;
}

public void removeChild(Bone child) {
if (children.remove(child)) {
child.setParent(null);
}
}

private void setParent(Bone parent) {
if (this.parent == parent) return;
this.parent = parent;
}

public String getName() {
return name;
}

public Bone getParent() {
return parent;
}

public List<Bone> getChildren() {
return Collections.unmodifiableList(children);
}

public Matrix4 getLocalTransform() {
return new Matrix4(localTransform);
}

public void setLocalTransform(Matrix4 localTransform) {
if (localTransform == null) {
throw new IllegalArgumentException("LocalTransform cannot be null.");
}
this.localTransform = localTransform;
markDirty();
}

public Matrix4 getGlobalTransform() {
return new Matrix4(globalTransform);
}

public Matrix4 getInverseBindPose() {
return new Matrix4(inverseBindPose);
}

public void setInverseBindPose(Matrix4 bindPose) {
this.inverseBindPose = bindPose.invert();
}

public float getWeight() {
return weight;
}

public void setWeight(float weight) {
if (weight < 0.0f || weight > 1.0f) {
throw new IllegalArgumentException("Weight must be between 0.0 and 1.0.");
}
this.weight = weight;
}

public int getIndex() {
return index;
}

public void setIndex(int index) {
this.index = index;
}

public void printHierarchy(int depth) {
System.out.println(" ".repeat(depth) + name);
for (Bone child : children) {
child.printHierarchy(depth + 1);
}
}
}
64 changes: 64 additions & 0 deletions src/main/java/engine/animation/skeleton/Skeleton.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package engine.animation.skeleton;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Skeleton {

private Bone rootBone;

private final Map<String, Bone> allBones;

public Skeleton(Bone rootBone) {
this.rootBone = rootBone;
this.allBones = new HashMap<>();
collectBones(rootBone);
}

private void collectBones(Bone bone) {
allBones.put(bone.getName(), bone);
for (Bone child : bone.getChildren()) {
collectBones(child);
}
}

public Bone getBone(String name) {
return allBones.get(name);
}

public void update() {
if (rootBone != null) {
rootBone.updateGlobalTransform();
}
}

public Bone getRootBone() {
return rootBone;
}

public void setRootBone(Bone rootBone) {
this.rootBone = rootBone;
allBones.clear();
collectBones(rootBone);
}

public List<Bone> getAllBones() {
return new ArrayList<>(allBones.values());
}

public void printHierarchy() {
printHierarchy(rootBone, 0);
}

private void printHierarchy(Bone bone, int level) {
for (int i = 0; i < level; i++) {
System.out.print(" ");
}
System.out.println(bone.getName());
for (Bone child : bone.getChildren()) {
printHierarchy(child, level + 1);
}
}
}
5 changes: 4 additions & 1 deletion src/main/java/engine/application/BasicApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@

import engine.Timer;
import engine.components.FlyByCameraControl;
import engine.components.SmoothFlyByCameraControl;
import engine.debug.DebugInfoUpdater;
import engine.debug.DebugOverlay;
import engine.debug.FpsGraph;
import engine.debug.FpsHistory;
import engine.input.Input;
import engine.input.Key;
import engine.processing.ProcessingApplication;
import engine.resources.Font;
import engine.scene.Scene;
import engine.scene.SceneNode;
import engine.scene.camera.PerspectiveCamera;
Expand Down Expand Up @@ -86,7 +88,7 @@ private void setupDefaultCamera() {
PerspectiveCamera defaultCamera = new PerspectiveCamera();
activeScene.setActiveCamera(defaultCamera);
SceneNode cameraNode = new SceneNode("DefaultCamera");
cameraNode.addComponent(new FlyByCameraControl(input, defaultCamera));
cameraNode.addComponent(new SmoothFlyByCameraControl(input, defaultCamera));
activeScene.addNode(cameraNode);
}

Expand Down Expand Up @@ -148,6 +150,7 @@ private void renderUi(Graphics g) {

private void renderDebugUi(Graphics g) {
if (!displayInfo) return;
g.setFont(new Font("Lucida Sans", 12, Font.PLAIN));
debugOverlay.render(g);
fpsGraph.render(g);
}
Expand Down
121 changes: 121 additions & 0 deletions src/main/java/engine/components/CrossLineReticle.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/**
* The CrossLineReticle class represents a visual reticle consisting of cross lines rendered on a
* plane. It is designed to be part of a 3D scene and implements the {@link RenderableComponent}
* interface for rendering capabilities.
*
* <p>The reticle is created as a textured plane using a {@link Mesh3D} and is configurable with
* parameters like radius, thickness, and color. The texture is generated dynamically.
*/
package engine.components;

import java.awt.Graphics2D;
import java.awt.image.BufferedImage;

import engine.resources.FilterMode;
import engine.resources.Texture;
import engine.resources.TextureManager;
import math.Color;
import math.Mathf;
import mesh.Mesh3D;
import mesh.creator.primitives.PlaneCreatorUV;
import mesh.modifier.RotateXModifier;
import workspace.ui.Graphics;

public class CrossLineReticle extends AbstractComponent implements RenderableComponent {

/** The radius of the reticle, defining its size. */
private int radius;

/** The thickness of the cross lines. */
private int thickness;

/** The color of the cross lines. */
private Color color;

/** The mesh used to represent the plane of the reticle. */
private Mesh3D mesh;

/** The texture used for rendering the reticle. */
private Texture texture;

/** Creates a default CrossLineReticle with a radius of 9, thickness of 2, and white color. */
public CrossLineReticle() {
this(9, 2, Color.WHITE);
}

/**
* Creates a CrossLineReticle with the specified radius, thickness, and color.
*
* @param radius The radius of the reticle.
* @param thickness The thickness of the cross lines.
* @param color The color of the cross lines.
*/
public CrossLineReticle(int radius, int thickness, Color color) {
this.radius = radius;
this.color = color;
this.thickness = thickness;
this.mesh = new PlaneCreatorUV(radius).create();
this.mesh.apply(new RotateXModifier(-Mathf.HALF_PI));
this.texture = createTexture();
}

/**
* Renders the reticle onto the provided {@link Graphics} context.
*
* @param g The graphics context used for rendering.
*/
@Override
public void render(Graphics g) {
float centerX = g.getWidth() / 2.0f;
float centerY = g.getHeight() / 2.0f;
g.pushMatrix();
g.translate(centerX, centerY);
g.bindTexture(texture, 0);
g.fillFaces(mesh);
g.unbindTexture(0);
g.popMatrix();
}

/**
* Creates a {@link Texture} for the reticle using a dynamically generated {@link BufferedImage}.
*
* @return The generated texture.
*/
private Texture createTexture() {
BufferedImage image = createTextureImage();
Texture texture = TextureManager.getInstance().createTexture(image);
texture.setFilterMode(FilterMode.POINT);
return texture;
}

/**
* Generates a {@link BufferedImage} containing the cross lines of the reticle.
*
* @return The generated image.
*/
private BufferedImage createTextureImage() {
int size = radius + radius;
BufferedImage image = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = (Graphics2D) image.getGraphics();
g2d.setColor(new java.awt.Color(this.color.getRGBA()));
g2d.fillRect(radius - (thickness / 2), 0, thickness, size);
g2d.fillRect(0, radius - (thickness / 2), size, thickness);
return image;
}

/**
* Called during each update cycle. This reticle does not require updates.
*
* @param tpf The time per frame in seconds.
*/
@Override
public void onUpdate(float tpf) {}

/** Called when the component is attached to a {@link engine.SceneNode}. */
@Override
public void onAttach() {}

/** Called when the component is detached from a {@link engine.SceneNode}. */
@Override
public void onDetach() {}
}
3 changes: 2 additions & 1 deletion src/main/java/engine/demos/landmass/NoiseMapDisplay.java
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ private void createPlaneMesh() {
*/
public void setPixels(int[] pixels) {
texture.setPixels(pixels);
Material material = new Material.Builder().setDiffuseTexture(texture).build();
Material material = new Material();
material.setDiffuseTexture(texture);
planeGeometry = new Geometry(planeMesh, material);
}

Expand Down
Loading

0 comments on commit 1dc5fa9

Please sign in to comment.