Skip to content

Commit

Permalink
Fixed #60
Browse files Browse the repository at this point in the history
  • Loading branch information
xTracr committed Mar 9, 2024
1 parent 43f495f commit bba7c5c
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 94 deletions.
13 changes: 6 additions & 7 deletions common/src/main/java/com/xtracr/realcamera/RealCameraCore.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
public class RealCameraCore {
private static final VertexRecorder recorder = new VertexRecorder();
public static BindingTarget currentTarget = new BindingTarget();
private static Vec3d pos = Vec3d.ZERO, cameraPos = Vec3d.ZERO;
private static Vec3d pos = Vec3d.ZERO, cameraPos = Vec3d.ZERO, offset = Vec3d.ZERO;
private static boolean active = false;
private static float pitch, yaw, roll;

Expand Down Expand Up @@ -74,10 +74,10 @@ public static void updateModel(MinecraftClient client, float tickDelta) {
entity.lastRenderZ = entity.getZ();
}
// WorldRenderer.renderEntity
dispatcher.render(entity, MathHelper.lerp(tickDelta, entity.lastRenderX, entity.getX()),
offset = new Vec3d(MathHelper.lerp(tickDelta, entity.lastRenderX, entity.getX()),
MathHelper.lerp(tickDelta, entity.lastRenderY, entity.getY()),
MathHelper.lerp(tickDelta, entity.lastRenderZ, entity.getZ()),
MathHelper.lerp(tickDelta, entity.prevYaw, entity.getYaw()),
MathHelper.lerp(tickDelta, entity.lastRenderZ, entity.getZ()));
dispatcher.render(entity, 0, 0, 0, MathHelper.lerp(tickDelta, entity.prevYaw, entity.getYaw()),
tickDelta, new MatrixStack(), recorder, dispatcher.getLight(entity, tickDelta));
recorder.buildLastRecord();
}
Expand All @@ -87,7 +87,7 @@ public static void renderCameraEntity(VertexConsumerProvider vertexConsumers) {
.rotate(RotationAxis.POSITIVE_X.rotationDegrees(pitch))
.rotate(RotationAxis.POSITIVE_Y.rotationDegrees(yaw + 180.0f))
.transpose().invert();
Matrix4f positionMatrix = new Matrix4f(normalMatrix).translate((float) -pos.getX(), (float) -pos.getY(), (float) -pos.getZ());
Matrix4f positionMatrix = new Matrix4f(normalMatrix).translate(offset.subtract(pos).toVector3f());
BiFunction<RenderLayer, VertexRecorder.Vertex[], VertexRecorder.Vertex[]> function = (renderLayer, vertices) -> {
double depth = currentTarget.disablingDepth;
int count = vertices.length;
Expand All @@ -103,9 +103,8 @@ public static void computeCamera() {
currentTarget = new BindingTarget();
Matrix3f normal = new Matrix3f();
for (BindingTarget target : config().getTargetList()) {
if (!recorder.setCurrent(renderLayer -> renderLayer.toString().contains(target.textureId))) continue;
try {
pos = recorder.getTargetPosAndRot(target, normal);
pos = recorder.getTargetPosAndRot(target, normal).add(offset);
currentTarget = target;
break;
} catch (Exception ignored) {
Expand Down
127 changes: 72 additions & 55 deletions common/src/main/java/com/xtracr/realcamera/gui/ModelAnalyser.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,26 @@
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.util.math.Vec2f;
import net.minecraft.util.math.Vec3d;
import org.jetbrains.annotations.Nullable;
import org.joml.Matrix3f;
import org.joml.Vector3f;

import java.awt.*;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

public class ModelAnalyser extends VertexRecorder {
private BuiltRecord focusedRecord;
private final BindingTarget target;
private final Matrix3f normal = new Matrix3f();
private final Vector3f position = new Vector3f();
@Nullable
private BuiltRecord focusedRecord, currentRecord;
private int focusedIndex = -1;

public ModelAnalyser(BindingTarget target) {
this.target = target;
}

private static boolean intersects(Vertex[] quad, List<Vertex[]> quads) {
final float precision = 1.0E-05f;
Expand All @@ -42,23 +53,9 @@ private static void drawNormal(DrawContext context, Vec3d start, Vec3d normal, i
context.draw();
}

public String focusedTextureId() {
if (focusedRecord == null) return null;
return getTextureId(focusedRecord);
}

public Vec2f getCenterUV(int quadIndex) {
if (quadIndex == -1 || focusedRecord == null || quadIndex >= focusedRecord.quadCount()) return null;
float u = 0, v = 0;
Vertex[] quad = focusedRecord.vertices()[quadIndex];
for (Vertex vertex : quad) {
u += vertex.u();
v += vertex.v();
}
return new Vec2f(u / quad.length, v / quad.length);
}
public void initialize(int entitySize, int mouseX, int mouseY, int layers) {
buildLastRecord();

public int getFocusedIndex(int mouseX, int mouseY, int layers) {
List<Triple> sortByDepth = new ArrayList<>();
records.forEach(record -> {
Vertex[][] vertices = record.vertices();
Expand All @@ -69,48 +66,74 @@ public int getFocusedIndex(int mouseX, int mouseY, int layers) {
if (!polygon.contains(mouseX, mouseY)) continue;
Vertex point = quad[0];
double deltaZ = 0;
if (point.normalZ() != 0) deltaZ = (point.normalX() * (mouseX - point.x()) + point.normalY() * (mouseY - point.y())) / point.normalZ();
if (point.normalZ() != 0)
deltaZ = (point.normalX() * (mouseX - point.x()) + point.normalY() * (mouseY - point.y())) / point.normalZ();
sortByDepth.add(new Triple(point.z() + deltaZ, record, i));
}
});
if (sortByDepth.isEmpty()) return -1;
sortByDepth.sort(Comparator.comparingDouble(triple -> -triple.depth));
Triple result = sortByDepth.get(Math.min(sortByDepth.size() - 1, layers));
focusedRecord = result.record;
return result.index;
}
if (!sortByDepth.isEmpty()) {
sortByDepth.sort(Comparator.comparingDouble(triple -> -triple.depth));
Triple result = sortByDepth.get(Math.min(sortByDepth.size() - 1, layers));
focusedRecord = result.record;
focusedIndex = result.index;
}

public void preview(DrawContext context, BindingTarget target, int entitySize, int forwardArgb, int upwardArgb, int leftArgb) {
drawByAnother(context.getVertexConsumers());
context.draw();
target.scale *= entitySize;
Matrix3f normal = new Matrix3f();
Vec3d pos;
try {
pos = getTargetPosAndRot(target, normal);
} catch (Exception exception) {
return;
currentRecord = checkAndGetTarget(target, normal, position);
normal.rotateLocal((float) Math.toRadians(target.yaw()), normal.m10, normal.m11, normal.m12);
normal.rotateLocal((float) Math.toRadians(target.pitch()), normal.m00, normal.m01, normal.m02);
normal.rotateLocal((float) Math.toRadians(target.roll()), normal.m20, normal.m21, normal.m22);
} catch (Exception ignored) {
}
}

public String focusedTextureId() {
if (focusedRecord == null) return null;
return getTextureId(focusedRecord);
}

public Vec2f getFocusedUV() {
if (focusedIndex == -1 || focusedRecord == null) return null;
float u = 0, v = 0;
Vertex[] quad = focusedRecord.vertices()[focusedIndex];
for (Vertex vertex : quad) {
u += vertex.u();
v += vertex.v();
}
normal.rotateLocal((float) Math.toRadians(target.yaw()), normal.m10, normal.m11, normal.m12);
normal.rotateLocal((float) Math.toRadians(target.pitch()), normal.m00, normal.m01, normal.m02);
normal.rotateLocal((float) Math.toRadians(target.roll()), normal.m20, normal.m21, normal.m22);
drawNormal(context, pos, new Vec3d(normal.m20(), normal.m21(), -normal.m22()), entitySize / 3, forwardArgb);
drawNormal(context, pos, new Vec3d(normal.m10(), normal.m11(), -normal.m12()), entitySize / 6, upwardArgb);
drawNormal(context, pos, new Vec3d(normal.m00(), normal.m01(), -normal.m02()), entitySize / 6, leftArgb);
return new Vec2f(u / quad.length, v / quad.length);
}

public void previewEffect(DrawContext context, int entitySize, int forwardArgb, int upwardArgb, int leftArgb) {
drawByAnother(context.getVertexConsumers());
context.draw();
if (normal.m00() == 0 && normal.m11() == 0 && normal.m22() == 0) return;
Vec3d start = new Vec3d(position);
drawNormal(context, start, new Vec3d(normal.m20(), normal.m21(), -normal.m22()), entitySize / 3, forwardArgb);
drawNormal(context, start, new Vec3d(normal.m10(), normal.m11(), -normal.m12()), entitySize / 6, upwardArgb);
drawNormal(context, start, new Vec3d(normal.m00(), normal.m01(), -normal.m02()), entitySize / 6, leftArgb);
}

public void drawQuad(DrawContext context, float u, float v, int argb) {
public void drawModelWithNormals(DrawContext context, int entitySize, int quadArgb, int forwardArgb, int upwardArgb, int faceArgb, int sideArgb) {
drawByAnother(context.getVertexConsumers());
context.draw();
drawPolyhedron(context, faceArgb, sideArgb);
if (currentRecord == null) return;
Vertex[] quad;
if ((quad = getQuad(u, v)) == null) return;
drawQuad(context, quad, argb, 1000);
if ((quad = getQuad(currentRecord, target.posU, target.posV)) != null)
drawQuad(context, quad, quadArgb, 1000);
if ((quad = getQuad(currentRecord, target.forwardU, target.forwardV)) != null)
drawNormal(context, getPos(quad, target.forwardU, target.forwardV), quad[0].normal(), entitySize / 2, forwardArgb);
if ((quad = getQuad(currentRecord, target.upwardU, target.upwardV)) != null)
drawNormal(context, getPos(quad, target.upwardU, target.upwardV), quad[0].normal(), entitySize / 2, upwardArgb);
}

public void drawPolyhedron(DrawContext context, int quadIndex, int argb1, int argb2) {
if (focusedRecord == null || quadIndex >= focusedRecord.quadCount()) return;
Vertex[] highlight = focusedRecord.vertices()[quadIndex];
private void drawPolyhedron(DrawContext context, int argb1, int argb2) {
if (focusedIndex == -1 || focusedRecord == null) return;
Vertex[] highlight = focusedRecord.vertices()[focusedIndex];
List<Vertex[]> polyhedron = new ArrayList<>();
polyhedron.add(highlight);
List<Integer> indexes = new ArrayList<>(List.of(quadIndex));
List<Integer> indexes = new ArrayList<>(List.of(focusedIndex));
Vertex[][] vertices = focusedRecord.vertices();
boolean added;
int size = focusedRecord.quadCount();
Expand All @@ -124,12 +147,12 @@ public void drawPolyhedron(DrawContext context, int quadIndex, int argb1, int ar
added = true;
}
} while (added);
List<Integer> resultIndexes = new ArrayList<>(List.of(quadIndex));
for (int i = quadIndex + 1; i < size; i++) {
List<Integer> resultIndexes = new ArrayList<>(List.of(focusedIndex));
for (int i = focusedIndex + 1; i < size; i++) {
if (!indexes.contains(i)) break;
resultIndexes.add(i);
}
for (int i = quadIndex - 1; i >= 0; i--) {
for (int i = focusedIndex - 1; i >= 0; i--) {
if (!indexes.contains(i)) break;
resultIndexes.add(i);
}
Expand All @@ -141,11 +164,5 @@ public void drawPolyhedron(DrawContext context, int quadIndex, int argb1, int ar
drawQuad(context, reversed, argb1, 1100);
}

public void drawNormal(DrawContext context, float u, float v, int length, int argb) {
Vertex[] quad;
if ((quad = getQuad(u, v)) == null) return;
drawNormal(context, getPos(quad, u, v), quad[0].normal(), length, argb);
}

record Triple(double depth, BuiltRecord record, int index) {}
record Triple(double depth, BuiltRecord record, int index) { }
}
Original file line number Diff line number Diff line change
Expand Up @@ -232,21 +232,13 @@ protected void drawEntity(DrawContext context, float x, float y, int mouseX, int
DiffuseLighting.method_34742();
EntityRenderDispatcher entityRenderDispatcher = MinecraftClient.getInstance().getEntityRenderDispatcher();
entityRenderDispatcher.setRenderShadows(false);
ModelAnalyser analyser = new ModelAnalyser();
ModelAnalyser analyser = new ModelAnalyser(generateBindingTarget());
entityRenderDispatcher.render(entity, 0, -entity.getHeight() / 2.0f, 0, 0.0f, 1.0f, context.getMatrices(), analyser, 0xF000f0);
analyser.buildLastRecord();
analyser.setCurrent(renderLayer -> renderLayer.toString().contains(textureIdField.getText()));
int focusedIndex = analyser.getFocusedIndex(mouseX, mouseY, layers);
focusedUV = analyser.getCenterUV(focusedIndex);
analyser.initialize(entitySize, mouseX, mouseY, layers);
focusedUV = analyser.getFocusedUV();
focusedTextureId = analyser.focusedTextureId();
if (category == 0) {
analyser.drawByAnother(context.getVertexConsumers());
context.draw();
analyser.drawQuad(context, posUField.getValue(), posVField.getValue(), 0x6F3333CC);
if (focusedIndex != -1) analyser.drawPolyhedron(context, focusedIndex, 0x7FFFFFFF, 0x3FFFFFFF);
analyser.drawNormal(context, forwardUField.getValue(), forwardVField.getValue(), entitySize / 2, 0xFF00CC00);
analyser.drawNormal(context, upwardUField.getValue(), upwardVField.getValue(), entitySize / 2, 0xFFCC0000);
} else analyser.preview(context, generateBindingTarget(), entitySize, 0xFF00CC00, 0xFFCC0000, 0xFF0000CC);
if (category == 1) analyser.previewEffect(context, entitySize, 0xFF00CC00, 0xFFCC0000, 0xFF0000CC);
else analyser.drawModelWithNormals(context, entitySize, 0x6F3333CC, 0xFF00CC00, 0xFFCC0000, 0x7FFFFFFF, 0x3FFFFFFF);
entityRenderDispatcher.setRenderShadows(true);
context.getMatrices().pop();
DiffuseLighting.enableGuiDepthLighting();
Expand Down
51 changes: 33 additions & 18 deletions common/src/main/java/com/xtracr/realcamera/util/VertexRecorder.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,24 @@
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.util.math.Vec3d;
import org.jetbrains.annotations.Nullable;
import org.joml.Matrix3f;
import org.joml.Matrix4f;
import org.joml.Vector3f;

import java.awt.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.*;
import java.util.Objects;
import java.util.function.BiFunction;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class VertexRecorder implements VertexConsumerProvider {
protected final List<BuiltRecord> records = new ArrayList<>();
private BuiltRecord currentRecord;
@Nullable
private VertexRecord lastRecord;

protected static Vec3d getPos(Vertex[] quad, float u, float v) {
Expand All @@ -38,19 +41,40 @@ protected static String getTextureId(BuiltRecord record) {
return name;
}

protected Vertex[] getQuad(float u, float v) {
if (currentRecord == null) return null;
protected static Vertex[] getQuad(BuiltRecord record, float u, float v) {
final int resolution = 1000000;
return Arrays.stream(currentRecord.vertices).filter(quad -> {
return Arrays.stream(record.vertices).filter(quad -> {
Polygon polygon = new Polygon();
for (Vertex vertex : quad) polygon.addPoint((int) (resolution * vertex.u), (int) (resolution * vertex.v));
return polygon.contains(resolution * u, resolution * v);
}).findAny().orElse(null);
}

protected BuiltRecord checkAndGetTarget(BindingTarget target, Matrix3f normal, Vector3f position) throws NullPointerException, ArithmeticException {
Vertex[] forwardQuad = null, upwardQuad = null, positionQuad = null;
BuiltRecord retRecord = null;
for (BuiltRecord record : records) {
if (!record.renderLayer.toString().contains(target.textureId)) continue;
forwardQuad = getQuad(record, target.forwardU, target.forwardV);
upwardQuad = getQuad(record, target.upwardU, target.upwardV);
positionQuad = getQuad(record, target.posU, target.posV);
if (forwardQuad != null && upwardQuad != null && positionQuad != null) {
retRecord = record;
break;
}
}
if (forwardQuad == null || upwardQuad == null || positionQuad == null) throw new NullPointerException();
Vec3d forward = forwardQuad[0].normal().normalize();
Vec3d left = upwardQuad[0].normal().crossProduct(forward).normalize();
Vec3d center = getPos(positionQuad, target.posU, target.posV);
if (!MathUtil.isFinite(forward) || !MathUtil.isFinite(left) || !MathUtil.isFinite(center)) throw new ArithmeticException();
normal.set(left.toVector3f(), forward.crossProduct(left).toVector3f(), forward.toVector3f());
position.set((float) target.offsetZ(), (float) target.offsetY(), (float) target.offsetX()).mul(normal).add(center.toVector3f());
return retRecord;
}

public void clear() {
records.clear();
currentRecord = null;
lastRecord = null;
}

Expand All @@ -59,19 +83,10 @@ public void buildLastRecord() {
lastRecord = null;
}

public boolean setCurrent(Predicate<RenderLayer> predicate) {
currentRecord = records.stream().filter(record -> predicate.test(record.renderLayer)).max(Comparator.comparingInt(BuiltRecord::quadCount)).orElse(null);
return currentRecord != null;
}

public Vec3d getTargetPosAndRot(BindingTarget target, Matrix3f normal) throws NullPointerException, ArithmeticException {
Vec3d forward = Objects.requireNonNull(getQuad(target.forwardU, target.forwardV))[0].normal().normalize();
Vec3d left = Objects.requireNonNull(getQuad(target.upwardU, target.upwardV))[0].normal().crossProduct(forward).normalize();
Vec3d center = getPos(Objects.requireNonNull(getQuad(target.posU, target.posV)), target.posU, target.posV);
if (!MathUtil.isFinite(forward) || !MathUtil.isFinite(left) || !MathUtil.isFinite(center)) throw new ArithmeticException();
normal.set(left.toVector3f(), forward.crossProduct(left).toVector3f(), forward.toVector3f());
Vector3f offset = new Vector3f((float) target.offsetZ(), (float) target.offsetY(), (float) target.offsetX()).mul(normal);
return center.add(offset.x(), offset.y(), offset.z());
Vector3f offset = new Vector3f();
checkAndGetTarget(target, normal, offset);
return new Vec3d(offset);
}

public void drawByAnother(VertexConsumerProvider anotherProvider) {
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ forge_version=1.20.1-47.2.20
fabric_loader_version=0.15.7
yarn_mappings=1.20.1+build.10
# Mod Properties
mod_version=0.6.0-beta
mod_version=0.6.0-alpha.5
maven_group=com.xtracr.realcamera
archives_base_name=realcamera
# Dependencies
Expand Down

0 comments on commit bba7c5c

Please sign in to comment.