Create a world-to-screen projection helper
We also grab the view matrix and set up a world rendering hook I needed to use LWJGL 2's util for GLU, but I can probably switch to JOML or somethingmain
parent
d11f3e0927
commit
0d831078a8
|
@ -49,6 +49,8 @@ dependencies {
|
||||||
}
|
}
|
||||||
implementation("io.github.spair:imgui-java-natives-windows-ft:$imguiVersion")
|
implementation("io.github.spair:imgui-java-natives-windows-ft:$imguiVersion")
|
||||||
|
|
||||||
|
implementation(files("vendor/lwjgl-util.jar"))
|
||||||
|
|
||||||
runtimeOnly("org.joml:joml:1.10.2")
|
runtimeOnly("org.joml:joml:1.10.2")
|
||||||
runtimeOnly("org.anarres:jcpp:1.4.14")
|
runtimeOnly("org.anarres:jcpp:1.4.14")
|
||||||
modRuntimeOnly(files("vendor/iris-mc1.18.1-1.2.0-pre.jar"))
|
modRuntimeOnly(files("vendor/iris-mc1.18.1-1.2.0-pre.jar"))
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
package codes.som.hibiscus.mixins;
|
||||||
|
|
||||||
|
import codes.som.hibiscus.HibiscusMod;
|
||||||
|
import codes.som.hibiscus.events.RenderWorldEvent;
|
||||||
|
import codes.som.hibiscus.util.graphics.WorldToScreenProjection;
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.client.render.Camera;
|
||||||
|
import net.minecraft.client.render.GameRenderer;
|
||||||
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
|
import net.minecraft.util.math.Matrix4f;
|
||||||
|
import org.spongepowered.asm.mixin.Final;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
@Mixin(GameRenderer.class)
|
||||||
|
public abstract class MixinGameRenderer {
|
||||||
|
@Shadow
|
||||||
|
@Final
|
||||||
|
private MinecraftClient client;
|
||||||
|
|
||||||
|
@Shadow
|
||||||
|
@Final
|
||||||
|
private Camera camera;
|
||||||
|
|
||||||
|
@Inject(
|
||||||
|
method = "renderWorld(FJLnet/minecraft/client/util/math/MatrixStack;)V",
|
||||||
|
at = @At(
|
||||||
|
value = "INVOKE_STRING",
|
||||||
|
target = "Lnet/minecraft/util/profiler/Profiler;swap(Ljava/lang/String;)V",
|
||||||
|
args = "ldc=hand",
|
||||||
|
shift = At.Shift.BEFORE))
|
||||||
|
private void preRenderHand(float tickDelta, long limitTime, MatrixStack matrices, CallbackInfo ci) {
|
||||||
|
Matrix4f modelView = matrices.peek().getModel();
|
||||||
|
|
||||||
|
WorldToScreenProjection.INSTANCE.updateViewport(client.getWindow(), modelView);
|
||||||
|
|
||||||
|
matrices.push();
|
||||||
|
RenderSystem.applyModelViewMatrix();
|
||||||
|
HibiscusMod.bus().fire(new RenderWorldEvent(tickDelta, this.camera, matrices));
|
||||||
|
matrices.pop();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,8 @@
|
||||||
package codes.som.hibiscus.events
|
package codes.som.hibiscus.events
|
||||||
|
|
||||||
import codes.som.hibiscus.api.event.Event
|
import codes.som.hibiscus.api.event.Event
|
||||||
|
import net.minecraft.client.render.Camera
|
||||||
|
import net.minecraft.client.util.math.MatrixStack
|
||||||
|
|
||||||
class PostRenderAllEvent(val delta: Float) : Event
|
class PostRenderAllEvent(val delta: Float) : Event
|
||||||
|
class RenderWorldEvent(val delta: Float, val camera: Camera, val matrices: MatrixStack) : Event
|
||||||
|
|
|
@ -0,0 +1,105 @@
|
||||||
|
package codes.som.hibiscus.util.graphics
|
||||||
|
|
||||||
|
import codes.som.hibiscus.mc
|
||||||
|
import net.minecraft.client.util.GlAllocationUtils
|
||||||
|
import net.minecraft.client.util.Window
|
||||||
|
import net.minecraft.util.math.MathHelper
|
||||||
|
import net.minecraft.util.math.Matrix4f
|
||||||
|
import net.minecraft.util.math.Vec3d
|
||||||
|
import org.lwjgl.opengl.GL11
|
||||||
|
import org.lwjgl.util.glu.Project.gluProject
|
||||||
|
import kotlin.math.absoluteValue
|
||||||
|
import kotlin.math.sign
|
||||||
|
|
||||||
|
object WorldToScreenProjection {
|
||||||
|
private const val PROJECTION_MATRIX_PLANE_RATIO_INDEX = 10
|
||||||
|
private const val PROJECTION_MATRIX_FAR_PLANE_INDEX = 14
|
||||||
|
private const val VIEWPORT_MATRIX_Y_OFFSET_INDEX = 1
|
||||||
|
private const val VIEWPORT_MATRIX_WIDTH_INDEX = 2
|
||||||
|
private const val VIEWPORT_MATRIX_HEIGHT_INDEX = 3
|
||||||
|
private const val PLANE_RATIO = -1.0f
|
||||||
|
|
||||||
|
private val FAR_PLANE_DISTANCE = -6.0E7f * MathHelper.SQUARE_ROOT_OF_TWO * 2.0f
|
||||||
|
|
||||||
|
private const val WINDOW_POSITION_VECTOR_DIMENSIONALITY = 3
|
||||||
|
private const val WINDOW_POSITION_VECTOR_X_INDEX = 0
|
||||||
|
private const val WINDOW_POSITION_VECTOR_Y_INDEX = 1
|
||||||
|
private const val WINDOW_POSITION_VECTOR_Z_INDEX = 2
|
||||||
|
|
||||||
|
private val VIEWPORT_MATRIX =
|
||||||
|
GlAllocationUtils.allocateByteBuffer(4 * Int.SIZE_BYTES).asIntBuffer() // 4x1 matrix of integers
|
||||||
|
private val MODEL_MATRIX =
|
||||||
|
GlAllocationUtils.allocateByteBuffer(16 * Float.SIZE_BYTES).asFloatBuffer() // 4x4 matrix of floats
|
||||||
|
private val PROJECTION_MATRIX =
|
||||||
|
GlAllocationUtils.allocateByteBuffer(16 * Float.SIZE_BYTES).asFloatBuffer() // 4x4 matrix of floats
|
||||||
|
private val WINDOW_POSITION_VECTOR =
|
||||||
|
GlAllocationUtils.allocateByteBuffer(WINDOW_POSITION_VECTOR_DIMENSIONALITY * Float.SIZE_BYTES).asFloatBuffer()
|
||||||
|
|
||||||
|
private var scaledWidth = 0
|
||||||
|
private var scaledHeight = 0
|
||||||
|
|
||||||
|
private var cameraX = 0.0
|
||||||
|
private var cameraY = 0.0
|
||||||
|
private var cameraZ = 0.0
|
||||||
|
|
||||||
|
fun updateViewport(window: Window, modelView: Matrix4f) {
|
||||||
|
scaledWidth = window.scaledWidth
|
||||||
|
scaledHeight = window.scaledHeight
|
||||||
|
val camera = mc.gameRenderer.camera
|
||||||
|
val cameraPos = if (camera == null) Vec3d.ZERO else camera.pos
|
||||||
|
cameraX = cameraPos.x
|
||||||
|
cameraY = cameraPos.y
|
||||||
|
cameraZ = cameraPos.z
|
||||||
|
modelView.writeRowMajor(MODEL_MATRIX)
|
||||||
|
GL11.glGetFloatv(GL11.GL_PROJECTION_MATRIX, PROJECTION_MATRIX)
|
||||||
|
PROJECTION_MATRIX.put(PROJECTION_MATRIX_PLANE_RATIO_INDEX, PLANE_RATIO)
|
||||||
|
PROJECTION_MATRIX.put(PROJECTION_MATRIX_FAR_PLANE_INDEX, FAR_PLANE_DISTANCE)
|
||||||
|
VIEWPORT_MATRIX.put(VIEWPORT_MATRIX_Y_OFFSET_INDEX, scaledHeight)
|
||||||
|
VIEWPORT_MATRIX.put(VIEWPORT_MATRIX_WIDTH_INDEX, scaledWidth)
|
||||||
|
VIEWPORT_MATRIX.put(VIEWPORT_MATRIX_HEIGHT_INDEX, -scaledHeight)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun project(x: Double, y: Double, z: Double, offScreen: Boolean): Vec3d? {
|
||||||
|
gluProject(
|
||||||
|
(x - cameraX).toFloat(),
|
||||||
|
(y - cameraY).toFloat(),
|
||||||
|
(z - cameraZ).toFloat(),
|
||||||
|
MODEL_MATRIX,
|
||||||
|
PROJECTION_MATRIX,
|
||||||
|
VIEWPORT_MATRIX,
|
||||||
|
WINDOW_POSITION_VECTOR
|
||||||
|
)
|
||||||
|
|
||||||
|
var windowX = WINDOW_POSITION_VECTOR[WINDOW_POSITION_VECTOR_X_INDEX]
|
||||||
|
var windowY = WINDOW_POSITION_VECTOR[WINDOW_POSITION_VECTOR_Y_INDEX]
|
||||||
|
val windowZ = WINDOW_POSITION_VECTOR[WINDOW_POSITION_VECTOR_Z_INDEX]
|
||||||
|
if (windowZ > 0) {
|
||||||
|
if (!offScreen) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
windowX = scaledWidth - windowX
|
||||||
|
windowY = scaledHeight - windowY
|
||||||
|
|
||||||
|
var offsetFromCentreWindowX = windowX - scaledWidth / 2
|
||||||
|
var offsetFromCentreWindowY = windowY - scaledWidth / 2
|
||||||
|
|
||||||
|
if (offsetFromCentreWindowX.absoluteValue < offsetFromCentreWindowY.absoluteValue) {
|
||||||
|
val newWindowXOffset = scaledWidth * offsetFromCentreWindowX.sign
|
||||||
|
|
||||||
|
offsetFromCentreWindowY *= newWindowXOffset / offsetFromCentreWindowX
|
||||||
|
offsetFromCentreWindowX = newWindowXOffset
|
||||||
|
} else {
|
||||||
|
val newWindowYOffset = scaledHeight * offsetFromCentreWindowY.sign
|
||||||
|
|
||||||
|
offsetFromCentreWindowX *= newWindowYOffset / offsetFromCentreWindowY
|
||||||
|
offsetFromCentreWindowY = newWindowYOffset
|
||||||
|
}
|
||||||
|
|
||||||
|
windowX = scaledWidth / 2 + offsetFromCentreWindowX
|
||||||
|
windowY = scaledHeight / 2 + offsetFromCentreWindowY
|
||||||
|
}
|
||||||
|
|
||||||
|
return Vec3d(windowX.toDouble(), windowY.toDouble(), windowZ.toDouble())
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue