Skip to content

Commit 31f5147

Browse files
committed
Add proper uv-lock counter-rotation calculation, and fix default uvs for a proper cube-mapping
1 parent 017ce33 commit 31f5147

File tree

4 files changed

+101
-38
lines changed

4 files changed

+101
-38
lines changed

core/src/main/java/de/bluecolored/bluemap/core/map/hires/block/ResourceModelRenderer.java

Lines changed: 41 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
import de.bluecolored.bluemap.core.world.block.ExtendedBlock;
5252
import lombok.Getter;
5353

54+
import java.util.EnumMap;
5455
import java.util.function.Function;
5556

5657
/**
@@ -71,6 +72,7 @@ public class ResourceModelRenderer implements BlockRenderer {
7172
private final VectorM2f[] uvs = new VectorM2f[4];
7273
private final Color tintColor = new Color();
7374
private final Color mapColor = new Color();
75+
private final EnumMap<Direction, Float> uvLockRotationCache = new EnumMap<>(Direction.class);
7476

7577
private BlockNeighborhood block;
7678
private Variant variant;
@@ -195,11 +197,7 @@ private void createElementFace(Element element, Direction faceDir, VectorM3f c0,
195197
) return;
196198

197199
// calculate faceRotationVector
198-
faceRotationVector.set(
199-
faceDirVector.getX(),
200-
faceDirVector.getY(),
201-
faceDirVector.getZ()
202-
);
200+
faceRotationVector.set(faceDirVector);
203201
faceRotationVector.rotateAndScale(element.getRotation().getMatrix());
204202
makeRotationRelative(faceRotationVector);
205203

@@ -258,19 +256,10 @@ private void createElementFace(Element element, Direction faceDir, VectorM3f c0,
258256
uvs[i] = rawUvs[(rotationSteps + i) % 4];
259257

260258
// UV-Lock counter-rotation
261-
float uvRotation = 0f;
262259
if (variant.isUvlock() && variant.isTransformed()) {
263-
float xRotSin = TrigMath.sin(variant.getX() * TrigMath.DEG_TO_RAD);
264-
float xRotCos = TrigMath.cos(variant.getX() * TrigMath.DEG_TO_RAD);
265-
266-
uvRotation =
267-
variant.getY() * (faceDirVector.getY() * xRotCos + faceDirVector.getZ() * xRotSin) +
268-
variant.getX() * (1 - faceDirVector.getY());
269-
}
260+
float uvRotation = uvLockRotation(faceDir);
270261

271-
// rotate uv's
272-
if (uvRotation != 0){
273-
uvRotation = (float)(uvRotation * TrigMath.DEG_TO_RAD);
262+
// rotate uv's
274263
float cx = TrigMath.cos(uvRotation), cy = TrigMath.sin(uvRotation);
275264
for (VectorM2f uv : uvs) {
276265
uv.translate(-0.5f, -0.5f);
@@ -351,6 +340,42 @@ private void createElementFace(Element element, Direction faceDir, VectorM3f c0,
351340
}
352341
}
353342

343+
private final VectorM3f rotatedNormal = new VectorM3f(0, 0, 0);
344+
private final VectorM3f rotatedUp = new VectorM3f(0, 0, 0);
345+
private final VectorM3f projectedWorldUp = new VectorM3f(0, 0, 0);
346+
private float uvLockRotation(Direction direction) {
347+
if (!variant.isTransformed()) return 0f;
348+
349+
makeRotationRelative(rotatedNormal.set(direction.toVector()));
350+
makeRotationRelative(rotatedUp.set(direction.getLocalUp().toVector()));
351+
352+
// project world-up (0, 1, 0) onto rotated face
353+
projectedWorldUp.set(0f, 1f, 0f);
354+
float dot = projectedWorldUp.dot(rotatedNormal);
355+
projectedWorldUp.set(rotatedNormal);
356+
projectedWorldUp.mul(dot);
357+
projectedWorldUp.set(
358+
0f - projectedWorldUp.x,
359+
1f - projectedWorldUp.y,
360+
0f - projectedWorldUp.z
361+
);
362+
363+
// special case, if we are close to up or down, the rotation should be locked to NORTH/SOUTH (localUp)
364+
if (projectedWorldUp.lengthSquared() < 0.01) {
365+
Direction upDown = rotatedNormal.y > 0f ? Direction.UP : Direction.DOWN;
366+
projectedWorldUp.set(upDown.getLocalUp().toVector());
367+
} else {
368+
projectedWorldUp.normalize();
369+
}
370+
371+
// compute angle between rotatedUp and projectedWorldUp around rotatedNormal
372+
dot = rotatedUp.dot(projectedWorldUp);
373+
return (float) TrigMath.atan2(
374+
rotatedUp.cross(projectedWorldUp).dot(rotatedNormal),
375+
dot
376+
);
377+
}
378+
354379
private ExtendedBlock getRotationRelativeBlock(Direction direction){
355380
return getRotationRelativeBlock(direction.toVector());
356381
}

core/src/main/java/de/bluecolored/bluemap/core/resources/pack/resourcepack/model/Element.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,15 +100,27 @@ private void init() {
100100

101101
private Vector4f calculateDefaultUV(Direction face) {
102102
return switch (face) {
103-
case DOWN, UP -> new Vector4f(
103+
case UP -> new Vector4f(
104104
from.getX(), from.getZ(),
105105
to.getX(), to.getZ()
106106
);
107-
case NORTH, SOUTH -> new Vector4f(
107+
case DOWN -> new Vector4f(
108+
from.getX(), 16 - to.getZ(),
109+
to.getX(), 16 - from.getZ()
110+
);
111+
case NORTH -> new Vector4f(
112+
16 - to.getX(), 16 - to.getY(),
113+
16 - from.getX(), 16 - from.getY()
114+
);
115+
case SOUTH -> new Vector4f(
108116
from.getX(), 16 - to.getY(),
109117
to.getX(), 16 - from.getY()
110118
);
111-
case WEST, EAST -> new Vector4f(
119+
case EAST -> new Vector4f(
120+
16 - to.getZ(), 16 - to.getY(),
121+
16 - from.getZ(), 16 - from.getY()
122+
);
123+
case WEST -> new Vector4f(
112124
from.getZ(), 16 - to.getY(),
113125
to.getZ(), 16 - from.getY()
114126
);

core/src/main/java/de/bluecolored/bluemap/core/util/Direction.java

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@
2626

2727
import com.flowpowered.math.vector.Vector3i;
2828
import de.bluecolored.bluemap.core.util.math.Axis;
29+
import lombok.Getter;
2930

3031
import java.util.Objects;
3132

32-
3333
public enum Direction {
3434

3535
UP ( 0, 1, 0, Axis.Y),
@@ -60,11 +60,18 @@ public enum Direction {
6060
SOUTH.right = WEST;
6161
WEST.right = NORTH;
6262
EAST.right = SOUTH;
63+
64+
UP.localUp = NORTH;
65+
DOWN.localUp = SOUTH;
66+
NORTH.localUp = UP;
67+
SOUTH.localUp = UP;
68+
WEST.localUp = UP;
69+
EAST.localUp = UP;
6370
}
6471

6572
private final Vector3i dir;
66-
private final Axis axis;
67-
private Direction opposite, left, right;
73+
@Getter private final Axis axis;
74+
@Getter private Direction opposite, left, right, localUp;
6875

6976
Direction(int x, int y, int z, Axis axis) {
7077
this.dir = new Vector3i(x, y, z);
@@ -76,25 +83,10 @@ public Vector3i toVector(){
7683
return dir;
7784
}
7885

79-
public Direction opposite() {
80-
return opposite;
81-
}
82-
83-
public Direction left() {
84-
return left;
85-
}
86-
87-
public Direction right() {
88-
return right;
89-
}
90-
91-
public Axis getAxis() {
92-
return axis;
93-
}
94-
9586
public static Direction fromString(String name){
9687
Objects.requireNonNull(name);
9788

9889
return valueOf(name.toUpperCase());
9990
}
91+
10092
}

core/src/main/java/de/bluecolored/bluemap/core/util/math/VectorM3f.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
*/
2525
package de.bluecolored.bluemap.core.util.math;
2626

27+
import com.flowpowered.math.vector.Vector3i;
28+
2729
public class VectorM3f {
2830

2931
public float x, y, z;
@@ -41,6 +43,35 @@ public VectorM3f set(float x, float y, float z) {
4143
return this;
4244
}
4345

46+
public VectorM3f set(Vector3i v) {
47+
this.x = v.getX();
48+
this.y = v.getY();
49+
this.z = v.getZ();
50+
return this;
51+
}
52+
53+
public VectorM3f set(VectorM3f v) {
54+
this.x = v.x;
55+
this.y = v.y;
56+
this.z = v.z;
57+
return this;
58+
}
59+
60+
public VectorM3f mul(float a) {
61+
this.x *= a;
62+
this.y *= a;
63+
this.z *= a;
64+
return this;
65+
}
66+
67+
public VectorM3f cross(VectorM3f v) {
68+
return set(
69+
y * v.z - z * v.y,
70+
z * v.x - x * v.z,
71+
x * v.y - y * v.x
72+
);
73+
}
74+
4475
public VectorM3f transform(MatrixM3f t) {
4576
return set(
4677
t.m00 * x + t.m01 * y + t.m02 * z,
@@ -81,4 +112,7 @@ public double lengthSquared() {
81112
return x * x + y * y + z * z;
82113
}
83114

115+
public float dot(VectorM3f v) {
116+
return x * v.x + y * v.y + z * v.z;
117+
}
84118
}

0 commit comments

Comments
 (0)