Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,9 @@ public List<Keyframe> getCurrentKeyframes(String boneName) {
}

//Bone name, transformations
Map<String, Triplet<Vector3f, Vector3f, Vector3f>> currentTransformations = new HashMap<>();
Map<String, TransformationSnapshot> currentTransformations = new HashMap<>();
List<Pair<Float, Keyframe>> progressKeyframes = new ArrayList<>();
public Map<String, Triplet<Vector3f, Vector3f, Vector3f>> getCurrentTransformations() {
public Map<String, TransformationSnapshot> getCurrentTransformations() {
currentTransformations.clear();
progressKeyframes.clear();
for (String boneName : keyframes.keySet()) {
Expand Down Expand Up @@ -150,7 +150,7 @@ float getKeyframeProgress(Keyframe keyframe) {
return (currentTime - keyframe.startTime) / (keyframe.endTime - keyframe.startTime);
}

Triplet<Vector3f, Vector3f, Vector3f> getCurrentTransforms(List<Pair<Float, Keyframe>> keyframes) {
TransformationSnapshot getCurrentTransforms(List<Pair<Float, Keyframe>> keyframes) {

//combine all keyframe transformations into one
Vector3f position = new Vector3f();
Expand All @@ -167,7 +167,7 @@ Triplet<Vector3f, Vector3f, Vector3f> getCurrentTransforms(List<Pair<Float, Keyf
}
}

return new Triplet<>(position, rotation, scale);
return new TransformationSnapshot(position, rotation, scale);
}

void interpolateComponent(Vector3f transformation, float progress, Keyframe keyframe) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.terminalvelocitycabbage.engine.client.renderer.animation;

import com.terminalvelocitycabbage.engine.util.tuples.Triplet;
import com.terminalvelocitycabbage.engine.client.renderer.model.Model;
import org.joml.Matrix4f;
import org.joml.Quaternionf;
import org.joml.Vector3f;
Expand All @@ -11,26 +11,31 @@
public class AnimationController {

//TODO replace string with identifier once animation registry exists
Map<String, Animation> animations;
private final Map<String, Integer> boneIndexMap;
Map<Integer, Triplet<Vector3f, Vector3f, Vector3f>> boneTransformations; //Pos, Rot, Scale
Map<Integer, Matrix4f> boneTransformationMatrices;
private final Map<String, Animation> animations;
private final Map<String, Model.Bone> bonesMap;
private final Map<Integer, Model.Bone> boneIndexMap;
private final Map<Integer, TransformationSnapshot> boneTransformations;
private final Map<Integer, Matrix4f> boneTransformationMatrices;

public AnimationController(Map<String, Animation> animations, Map<String, Integer> boneIndexMap) {
public AnimationController(Map<String, Animation> animations, Map<String, Model.Bone> bonesMap) {
this.animations = animations;
this.boneIndexMap = boneIndexMap;
this.bonesMap = bonesMap;
boneIndexMap = new HashMap<>();
boneTransformations = new HashMap<>();
boneTransformationMatrices = new HashMap<>();
boneIndexMap.values().forEach(boneIndex -> boneTransformations.put(boneIndex, new Triplet<>(new Vector3f(), new Vector3f(), new Vector3f(1))));
boneIndexMap.values().forEach(boneIndex -> boneTransformationMatrices.put(boneIndex, new Matrix4f()));
bonesMap.values().forEach(bone -> {
boneIndexMap.put(bone.getBoneIndex(), bone);
boneTransformations.put(bone.getBoneIndex(), new TransformationSnapshot(new Vector3f(), new Vector3f(), new Vector3f(1)));
boneTransformationMatrices.put(bone.getBoneIndex(), new Matrix4f());
});
}

public void update(long deltaTime) {
public void update(long deltaTime, Model model) {
//Reset all transformations from last frame
boneTransformations.values().forEach(vector3fVector3fVector3fTriplet -> {
vector3fVector3fVector3fTriplet.getValue0().zero();
vector3fVector3fVector3fTriplet.getValue1().zero();
vector3fVector3fVector3fTriplet.getValue2().set(1);
boneTransformations.values().forEach(transformationSnapshot -> {
transformationSnapshot.position().zero();
transformationSnapshot.rotation().zero();
transformationSnapshot.scale().set(1);
});
boneTransformationMatrices.values().forEach(Matrix4f::identity);

Expand All @@ -40,20 +45,30 @@ public void update(long deltaTime) {
//Get this animation's transformations add them together
animation.getCurrentTransformations().forEach(
(boneName, boneTransformation) -> {
boneTransformations.get(boneIndexMap.get(boneName)).getValue0().add(boneTransformation.getValue0());
boneTransformations.get(boneIndexMap.get(boneName)).getValue1().add(boneTransformation.getValue1());
boneTransformations.get(boneIndexMap.get(boneName)).getValue2().mul(boneTransformation.getValue2());
var transformation = boneTransformations.get(bonesMap.get(boneName).getBoneIndex());
transformation.position().add(boneTransformation.position());
transformation.rotation().add(boneTransformation.rotation());
transformation.scale().mul(boneTransformation.scale());
}
);
}
//Convert all of these updated and combined transformations into a single transformation matrix for each bone
for (int i = 0; i < boneTransformationMatrices.size(); i++) {
var boneTransformation = boneTransformations.get(i);
var eulerRotation = boneTransformation.getValue1();
var rotation = new Quaternionf().rotateXYZ((float) Math.toRadians(eulerRotation.x), (float) Math.toRadians(eulerRotation.y), (float) Math.toRadians(eulerRotation.z));
boneTransformationMatrices.get(i)
for (Map.Entry<Integer, Model.Bone> entry : boneIndexMap.entrySet()) {

var index = entry.getKey();
var bone = entry.getValue();

var boneTransformation = boneTransformations.get(index);
var eulerRotation = boneTransformation.rotation();
var rotation = new Quaternionf().rotateXYZ(
(float) Math.toRadians(eulerRotation.x),
(float) Math.toRadians(eulerRotation.y),
(float) Math.toRadians(eulerRotation.z)
);
boneTransformationMatrices.get(index)
.identity()
.translationRotateScale(boneTransformation.getValue0(), rotation, boneTransformation.getValue2());
.translationRotateScale(boneTransformation.position(), rotation, boneTransformation.scale());
//.translate(bone.getOffset());
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.terminalvelocitycabbage.engine.client.renderer.animation;

import org.joml.Vector3f;

public record TransformationSnapshot(Vector3f position, Vector3f rotation, Vector3f scale) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public AnimationController toAnimationController(Model model) {
convertedAnimations.put(animationName, animation);
}

return new AnimationController(convertedAnimations, model.getBoneIndexMap());
return new AnimationController(convertedAnimations, model.getBones());
}

public record AnimationData (
Expand Down Expand Up @@ -173,7 +173,7 @@ private static List<Keyframe> parseTransformationData(Keyframe.Component compone
previousKeyframeEndTransformation = previousKeyframe.getEndTransformation();
previousKeyframeEndTime = previousKeyframe.getEndTime();
}
var endTimeMillis = Float.parseFloat(endTimeSeconds) * 1000;
var endTimeMillis = Float.parseFloat(endTimeSeconds) * 1000f;

//Create the keyframes
if (keyframeConfigOrTransformation.toString().startsWith("[")) { //linear is simplified out in bbmodel
Expand Down
Original file line number Diff line number Diff line change
@@ -1,127 +1,96 @@
package com.terminalvelocitycabbage.engine.client.renderer.model;

import com.terminalvelocitycabbage.engine.client.renderer.elements.VertexFormat;
import com.terminalvelocitycabbage.engine.debug.Log;
import org.joml.Quaternionf;
import org.joml.Vector3f;

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

public class Model {

VertexFormat format;
List<Part> parts;
Map<String, Integer> boneIndexMap;
boolean compiledMesh;
Map<String, Bone> parts;
Mesh mesh;

public Model(VertexFormat format, List<Part> parts, Map<String, Integer> boneIndexMap, Mesh mesh) {
this(format, parts, boneIndexMap);
this.mesh = mesh;
this.compiledMesh = true;
}

public Model(VertexFormat format, List<Part> parts, Map<String, Integer> boneIndexMap) {
public Model(VertexFormat format, Map<String, Bone> bones, Mesh mesh) {
this.format = format;
this.parts = parts;
this.boneIndexMap = boneIndexMap;
this.compiledMesh = false;
this.parts = bones;
this.parts.values().forEach(bone -> bone.model = this);
this.mesh = mesh;
}

public void render() {
if (compiledMesh) {
mesh.render();
} else {
for (Part part : parts) {
part.render();
}
}
mesh.render();
}

public void cleanup() {
for (Part part : parts) {
part.cleanup();
}
mesh.cleanup();
}

public VertexFormat getFormat() {
return format;
}

public List<Part> getParts() {
public Bone getBone(String partName) {
return parts.get(partName);
}

public Map<String, Bone> getBones() {
return parts;
}

public Mesh getMesh() {
return mesh;
}

public Map<String, Integer> getBoneIndexMap() {
return boneIndexMap;
}
public static class Bone {

public static class Part {
Model model;

String name;
Part parent;
List<Part> children;
Mesh mesh;
String parentName;
int boneIndex;

boolean dirty;

Vector3f pivotPoint;
Vector3f origin;
Vector3f offset;
Quaternionf rotation;
Vector3f scale;

public Part(String name, Part parent, Mesh mesh, Vector3f pivotPoint, Quaternionf rotation, int boneIndex) {
public Bone(String name, String parentName, Vector3f pivotPoint, Quaternionf rotation, Vector3f scale, int boneIndex) {
this.name = name;
this.parent = parent;
this.children = new ArrayList<>();
this.mesh = mesh;
this.parentName = parentName;

this.dirty = true;

this.pivotPoint = pivotPoint;
this.offset = pivotPoint;
this.rotation = rotation;
this.scale = scale;

this.boneIndex = boneIndex;
}

public void render() {
if (mesh != null) mesh.render();
for (Part child : children) {
child.render();
}
public String getParentName() {
return parentName;
}

public void cleanup() {
mesh.cleanup();
for (Part child : children) {
child.cleanup();
}
}

public void addChild(Part child) {
children.add(child);
}

public Part getParent() {
return parent;
}

public List<Part> getChildren() {
return children;
public String getName() {
return name;
}

public Mesh getMesh() {
return mesh;
//TODO cache this offset so we don't query every frame, do this on model instantiation
public Vector3f getOffset() {
Vector3f retOffset = new Vector3f(offset);
var parent = model.getBone(parentName);
if (parent != null) {
retOffset.add(parent.getOffset(), retOffset);
}
return retOffset;
}

public String getName() {
return name;
public int getBoneIndex() {
return boneIndex;
}
}

Expand Down
Loading