mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2024-11-10 12:34:11 +01:00
Shiver me timbers
- Use arrrays in the trees - MeshTree tracks parallel arrays of children and keys - InstanceTree tracks which mesh tree it came from for lookup purposes - Remove walker object - Make RecyclingPoseStack use add/removeLast instead of push/pop
This commit is contained in:
parent
5ffddeb221
commit
6f2b8fd3fb
@ -1,10 +1,6 @@
|
||||
package dev.engine_room.flywheel.lib.model.part;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.ObjIntConsumer;
|
||||
@ -32,11 +28,12 @@ import net.minecraft.client.model.geom.PartPose;
|
||||
public final class InstanceTree {
|
||||
private static final ModelCache<Model.ConfiguredMesh> MODEL_CACHE = new ModelCache<>(entry -> new SingleMeshModel(entry.mesh(), entry.material()));
|
||||
|
||||
private final MeshTree source;
|
||||
@Nullable
|
||||
private final TransformedInstance instance;
|
||||
private final PartPose initialPose;
|
||||
@Unmodifiable
|
||||
private final Map<String, InstanceTree> children;
|
||||
private final InstanceTree[] children;
|
||||
|
||||
private final Quaternionf rotation = new Quaternionf();
|
||||
|
||||
@ -52,7 +49,8 @@ public final class InstanceTree {
|
||||
public boolean visible = true;
|
||||
public boolean skipDraw;
|
||||
|
||||
private InstanceTree(@Nullable TransformedInstance instance, PartPose initialPose, @Unmodifiable Map<String, InstanceTree> children) {
|
||||
private InstanceTree(MeshTree source, @Nullable TransformedInstance instance, PartPose initialPose, InstanceTree[] children) {
|
||||
this.source = source;
|
||||
this.instance = instance;
|
||||
this.initialPose = initialPose;
|
||||
this.children = children;
|
||||
@ -60,12 +58,15 @@ public final class InstanceTree {
|
||||
}
|
||||
|
||||
private static InstanceTree create(InstancerProvider provider, MeshTree meshTree, BiFunction<String, Mesh, Model.ConfiguredMesh> meshFinalizerFunc, String path) {
|
||||
Map<String, InstanceTree> children = new HashMap<>();
|
||||
InstanceTree[] children = new InstanceTree[meshTree.childCount()];
|
||||
String pathSlash = path + "/";
|
||||
|
||||
meshTree.children().forEach((name, meshTreeChild) -> {
|
||||
children.put(name, InstanceTree.create(provider, meshTreeChild, meshFinalizerFunc, pathSlash + name));
|
||||
});
|
||||
for (int i = 0; i < meshTree.childCount(); i++) {
|
||||
var meshTreeChild = meshTree.child(i);
|
||||
String name = meshTree.childName(i);
|
||||
children[i] = InstanceTree.create(provider, meshTreeChild, meshFinalizerFunc, pathSlash + name);
|
||||
|
||||
}
|
||||
|
||||
Mesh mesh = meshTree.mesh();
|
||||
TransformedInstance instance;
|
||||
@ -77,7 +78,7 @@ public final class InstanceTree {
|
||||
instance = null;
|
||||
}
|
||||
|
||||
return new InstanceTree(instance, meshTree.initialPose(), Collections.unmodifiableMap(children));
|
||||
return new InstanceTree(meshTree, instance, meshTree.initialPose(), children);
|
||||
}
|
||||
|
||||
public static InstanceTree create(InstancerProvider provider, MeshTree meshTree, BiFunction<String, Mesh, Model.ConfiguredMesh> meshFinalizerFunc) {
|
||||
@ -105,18 +106,17 @@ public final class InstanceTree {
|
||||
return initialPose;
|
||||
}
|
||||
|
||||
@Unmodifiable
|
||||
public Map<String, InstanceTree> children() {
|
||||
return children;
|
||||
}
|
||||
|
||||
public boolean hasChild(String name) {
|
||||
return children.containsKey(name);
|
||||
@Nullable
|
||||
public InstanceTree child(int index) {
|
||||
if (index < 0 || index >= children.length) {
|
||||
return null;
|
||||
}
|
||||
return children[index];
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public InstanceTree child(String name) {
|
||||
return children.get(name);
|
||||
return child(source.childIndex(name));
|
||||
}
|
||||
|
||||
public InstanceTree childOrThrow(String name) {
|
||||
@ -133,7 +133,7 @@ public final class InstanceTree {
|
||||
if (instance != null) {
|
||||
consumer.accept(instance);
|
||||
}
|
||||
for (InstanceTree child : children.values()) {
|
||||
for (InstanceTree child : children) {
|
||||
child.traverse(consumer);
|
||||
}
|
||||
}
|
||||
@ -143,7 +143,7 @@ public final class InstanceTree {
|
||||
if (instance != null) {
|
||||
consumer.accept(instance, i);
|
||||
}
|
||||
for (InstanceTree child : children.values()) {
|
||||
for (InstanceTree child : children) {
|
||||
child.traverse(i, consumer);
|
||||
}
|
||||
}
|
||||
@ -153,7 +153,7 @@ public final class InstanceTree {
|
||||
if (instance != null) {
|
||||
consumer.accept(instance, i, j);
|
||||
}
|
||||
for (InstanceTree child : children.values()) {
|
||||
for (InstanceTree child : children) {
|
||||
child.traverse(i, j, consumer);
|
||||
}
|
||||
}
|
||||
@ -171,16 +171,6 @@ public final class InstanceTree {
|
||||
}
|
||||
|
||||
public void updateInstances(PoseStack poseStack) {
|
||||
// Need to use an anonymous class so it can reference this.
|
||||
updateInstancesInner(poseStack, new Walker() {
|
||||
@Override
|
||||
public void accept(InstanceTree child) {
|
||||
child.updateInstancesInner(poseStack, this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void updateInstancesInner(PoseStack poseStack, Walker walker) {
|
||||
if (visible) {
|
||||
poseStack.pushPose();
|
||||
translateAndRotate(poseStack);
|
||||
@ -192,7 +182,9 @@ public final class InstanceTree {
|
||||
|
||||
// Use the bare HashMap.forEach because .values() always allocates a new collection.
|
||||
// We also don't want to store an array of children because that would statically use a lot more memory.
|
||||
children.forEach(walker);
|
||||
for (InstanceTree child : children) {
|
||||
child.updateInstances(poseStack);
|
||||
}
|
||||
|
||||
poseStack.popPose();
|
||||
}
|
||||
@ -294,8 +286,9 @@ public final class InstanceTree {
|
||||
if (instance != null) {
|
||||
instance.delete();
|
||||
}
|
||||
children.values()
|
||||
.forEach(InstanceTree::delete);
|
||||
for (InstanceTree child : children) {
|
||||
child.delete();
|
||||
}
|
||||
}
|
||||
|
||||
@ApiStatus.Experimental
|
||||
@ -303,14 +296,4 @@ public final class InstanceTree {
|
||||
public interface ObjIntIntConsumer<T> {
|
||||
void accept(T t, int i, int j);
|
||||
}
|
||||
|
||||
// Helper interface for writing walking classes.
|
||||
private interface Walker extends BiConsumer<String, InstanceTree> {
|
||||
void accept(InstanceTree child);
|
||||
|
||||
@Override
|
||||
default void accept(String name, InstanceTree child) {
|
||||
accept(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
package dev.engine_room.flywheel.lib.model.part;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
@ -9,7 +8,6 @@ import java.util.function.Consumer;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.Unmodifiable;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
|
||||
@ -35,12 +33,13 @@ public final class MeshTree {
|
||||
@Nullable
|
||||
private final Mesh mesh;
|
||||
private final PartPose initialPose;
|
||||
@Unmodifiable
|
||||
private final Map<String, MeshTree> children;
|
||||
private final MeshTree[] children;
|
||||
private final String[] childKeys;
|
||||
|
||||
private MeshTree(@Nullable Mesh mesh, PartPose initialPose, @Unmodifiable Map<String, MeshTree> children) {
|
||||
private MeshTree(@Nullable Mesh mesh, PartPose initialPose, MeshTree[] children, String[] childKeys) {
|
||||
this.mesh = mesh;
|
||||
this.initialPose = initialPose;
|
||||
this.childKeys = childKeys;
|
||||
this.children = children;
|
||||
}
|
||||
|
||||
@ -58,13 +57,17 @@ public final class MeshTree {
|
||||
|
||||
private static MeshTree convert(ModelPart modelPart, ThreadLocalObjects objects) {
|
||||
var modelPartChildren = FlwLibLink.INSTANCE.getModelPartChildren(modelPart);
|
||||
Map<String, MeshTree> children = new HashMap<>();
|
||||
|
||||
modelPartChildren.forEach((name, modelPartChild) -> {
|
||||
children.put(name, convert(modelPartChild, objects));
|
||||
});
|
||||
// Freeze the ordering here. Maybe we want to sort this?
|
||||
String[] childKeys = modelPartChildren.keySet()
|
||||
.toArray(new String[0]);
|
||||
|
||||
return new MeshTree(compile(modelPart, objects), modelPart.getInitialPose(), Collections.unmodifiableMap(children));
|
||||
MeshTree[] children = new MeshTree[modelPartChildren.size()];
|
||||
for (int i = 0; i < childKeys.length; i++) {
|
||||
children[i] = convert(modelPartChildren.get(childKeys[i]), objects);
|
||||
}
|
||||
|
||||
return new MeshTree(compile(modelPart, objects), modelPart.getInitialPose(), children, childKeys);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@ -91,18 +94,35 @@ public final class MeshTree {
|
||||
return initialPose;
|
||||
}
|
||||
|
||||
@Unmodifiable
|
||||
public Map<String, MeshTree> children() {
|
||||
return children;
|
||||
public int childCount() {
|
||||
return children.length;
|
||||
}
|
||||
|
||||
public MeshTree child(int index) {
|
||||
return children[index];
|
||||
}
|
||||
|
||||
public String childName(int index) {
|
||||
return childKeys[index];
|
||||
}
|
||||
|
||||
public int childIndex(String name) {
|
||||
return Arrays.binarySearch(childKeys, name);
|
||||
}
|
||||
|
||||
public boolean hasChild(String name) {
|
||||
return children.containsKey(name);
|
||||
return childIndex(name) >= 0;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public MeshTree child(String name) {
|
||||
return children.get(name);
|
||||
int index = childIndex(name);
|
||||
|
||||
if (index < 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return child(index);
|
||||
}
|
||||
|
||||
public MeshTree childOrThrow(String name) {
|
||||
@ -119,7 +139,7 @@ public final class MeshTree {
|
||||
if (mesh != null) {
|
||||
consumer.accept(mesh);
|
||||
}
|
||||
for (MeshTree child : children.values()) {
|
||||
for (MeshTree child : children) {
|
||||
child.traverse(consumer);
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ public class RecyclingPoseStack extends PoseStack {
|
||||
super.pushPose();
|
||||
} else {
|
||||
var last = last();
|
||||
var recycle = recycleBin.pop();
|
||||
var recycle = recycleBin.removeLast();
|
||||
recycle.pose()
|
||||
.set(last.pose());
|
||||
recycle.normal()
|
||||
@ -36,7 +36,7 @@ public class RecyclingPoseStack extends PoseStack {
|
||||
|
||||
@Override
|
||||
public void popPose() {
|
||||
recycleBin.push(FlwLibLink.INSTANCE.getPoseStack(this)
|
||||
recycleBin.addLast(FlwLibLink.INSTANCE.getPoseStack(this)
|
||||
.removeLast());
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user