From f52880e52772204af237e7443be0cf57b1363824 Mon Sep 17 00:00:00 2001 From: gamma-delta <29877714+gamma-delta@users.noreply.github.com> Date: Sat, 25 Dec 2021 12:41:07 -0600 Subject: [PATCH] push to get help with matrix-based look->screen calcs --- LICENSE.txt | 17 ++++ .../at/petrak/hex/casting/CastingHarness.kt | 78 +++++++++++++++---- .../java/at/petrak/hex/casting/SpellDatum.kt | 11 ++- .../hex/casting/operators/spells/OpPrint.kt | 2 +- .../petrak/hex/client/HexRenderOverlays.java | 7 +- .../java/at/petrak/hex/hexes/HexPattern.kt | 2 +- .../java/at/petrak/hex/items/ItemWand.java | 8 +- 7 files changed, 102 insertions(+), 23 deletions(-) create mode 100644 LICENSE.txt diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 00000000..32fe9352 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,17 @@ +The MIT License (MIT) +Copyright © 2021 gamma-delta + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software +and associated documentation files (the “Software”), to deal in the Software without +restriction, including without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/src/main/java/at/petrak/hex/casting/CastingHarness.kt b/src/main/java/at/petrak/hex/casting/CastingHarness.kt index 46720de9..88dc69d1 100644 --- a/src/main/java/at/petrak/hex/casting/CastingHarness.kt +++ b/src/main/java/at/petrak/hex/casting/CastingHarness.kt @@ -7,10 +7,14 @@ import at.petrak.hex.HexUtils.deserializeVec3FromNBT import at.petrak.hex.HexUtils.serializeToNBT import at.petrak.hex.casting.operators.SpellOperator import at.petrak.hex.hexes.HexAngle +import at.petrak.hex.hexes.HexCoord import at.petrak.hex.hexes.HexDir import at.petrak.hex.hexes.HexPattern +import com.mojang.math.Matrix3f +import com.mojang.math.Vector3f import net.minecraft.nbt.* import net.minecraft.server.level.ServerPlayer +import net.minecraft.world.phys.Vec2 import net.minecraft.world.phys.Vec3 import java.util.* import kotlin.math.* @@ -35,10 +39,8 @@ class CastingHarness private constructor( HexMod.LOGGER.info("Started drawing new pattern") this.patternDrawState = PatternDrawState.JustStarted(caster.lookAngle) worldPoints.add(mutableListOf(caster.lookAngle.add(caster.position()))) - CastResult.Nothing - } else { - CastResult.QuitCasting } + CastResult.Nothing } is PatternDrawState.JustStarted -> { val (anchor) = patternDrawState as PatternDrawState.JustStarted @@ -74,8 +76,8 @@ class CastingHarness private constructor( // Finish the current pattern! patternDrawState = PatternDrawState.BetweenPatterns try { - val operator = SpellOperator.fromPattern(pat) + HexMod.LOGGER.info("Executing operator: $operator") // now execute the operator if (operator.argc > this.stack.size) throw CastException(CastException.Reason.NOT_ENOUGH_ARGS, operator.argc, this.stack.size) @@ -86,6 +88,8 @@ class CastingHarness private constructor( val newData = operator.execute(args, this.ctx) this.stack.addAll(newData) + HexMod.LOGGER.info("Added new data to stack: ${this.stack}") + if (this.stack.isEmpty()) { return CastResult.QuitCasting } @@ -156,7 +160,7 @@ class CastingHarness private constructor( CastingHarness(stack, pds, points, ctx) } catch (exn: Exception) { - HexMod.LOGGER.warn("Couldn't load harness from nbt tag, falling back to default: ${exn.message}") + HexMod.LOGGER.warn("Couldn't load harness from nbt tag, falling back to default: $nbt: $exn") CastingHarness(mutableListOf(), PatternDrawState.BetweenPatterns, mutableListOf(), ctx) } } @@ -164,12 +168,51 @@ class CastingHarness private constructor( // this is on a unit sphere, where 0 is straight ahead and 1 is straight up (or similar) const val HEX_GRID_SPACING = 1.0 / 8.0 - /** Check if the two vectors are far enough apart to be more than one hex coord apart */ - private fun Vec3.hexDirBetween(look: Vec3): Optional { + private fun screenToLookMat(look: Vec3): Matrix3f { + val towardsZenith = Vec3(0.0, 1.0, 0.0).subtract(look).normalize() + val towardsRight = look.cross(towardsZenith).normalize() + + val ihatPrime = Vector3f(look.add(towardsRight)) + val jhatPrime = Vector3f(look.add(towardsZenith)) + val khatPrime = Vector3f(look) + + val neo = Matrix3f() + neo.set(0, 0, ihatPrime.x()) + neo.set(0, 1, ihatPrime.y()) + neo.set(0, 2, ihatPrime.z()) + neo.set(1, 0, jhatPrime.x()) + neo.set(1, 1, jhatPrime.y()) + neo.set(1, 2, jhatPrime.z()) + neo.set(2, 0, khatPrime.x()) + neo.set(2, 1, khatPrime.y()) + neo.set(2, 2, khatPrime.z()) + return neo + } + + private fun Vec3.screenAngle(offset: Vec3): Double { // https://gist.github.com/Alwinfy/d6f3e9b22e4432f4446a58ace8812a3c // no idea how any of this works fun pythag(x: Double, y: Double): Double = sqrt(x * x + y * y) + val yaw = atan2(this.x, this.z) + val pitch = atan2(this.y, pythag(this.x, this.z)) + val zeroYaw = offset.yRot(-yaw.toFloat()) + val zeroPitch = zeroYaw.xRot(-pitch.toFloat()).normalize() + + return atan2(asin(zeroPitch.y), asin(-zeroPitch.x)) + } + + private fun Vec3.screenVec(offset: Vec3): Vec2 { + val angle = this.screenAngle(offset) + val dy = sin(angle) + val dx = cos(angle) + + val dist = (this.normalize().subtract(offset.normalize())).length() + return Vec2((dx * dist).toFloat(), (dy * dist).toFloat()) + } + + /** Check if the two vectors are far enough apart to be more than one hex coord apart */ + private fun Vec3.hexDirBetween(look: Vec3): Optional { if (look.x.absoluteValue <= 1e-30 || look.z.absoluteValue <= 1e-30) return Optional.empty() @@ -177,16 +220,25 @@ class CastingHarness private constructor( if (dist < HEX_GRID_SPACING) return Optional.empty() - val yaw = atan2(this.x, this.z) - val pitch = atan2(this.y, pythag(this.x, this.z)) - val zeroYaw = look.yRot(-yaw.toFloat()) - val zeroPitch = zeroYaw.xRot(-pitch.toFloat()).normalize() - - val angle = atan2(asin(zeroPitch.y), asin(-zeroPitch.x)) + // val angle = this.screenAngle(look) + val neo = screenToLookMat(this) + neo.invert() + val lookScreen = Vector3f(look) + lookScreen.transform(neo) + HexMod.LOGGER.info(lookScreen) + val angle = atan2(lookScreen.y(), lookScreen.x()) // 0 is right, increases clockwise(?) val snappedAngle = angle.div(TAU).mod(6.0).times(6).roundToInt() return Optional.of(HexDir.values()[(-snappedAngle + 1).mod(6)]) } + + /** + * Taking this as a look vector, get the look vector that is this vector offset + * by the given coordinate in draw-space. + */ + private fun Vec3.hexOffsetFrom(offset: HexCoord): Vec3 { + TODO() + } } sealed class PatternDrawState { diff --git a/src/main/java/at/petrak/hex/casting/SpellDatum.kt b/src/main/java/at/petrak/hex/casting/SpellDatum.kt index bbbd5d81..470683b1 100644 --- a/src/main/java/at/petrak/hex/casting/SpellDatum.kt +++ b/src/main/java/at/petrak/hex/casting/SpellDatum.kt @@ -13,6 +13,7 @@ import net.minecraft.world.phys.Vec3 * * [Entity] * * [Double] * * [Vec3][net.minecraft.world.phys.Vec3] as both position and (when normalized) direction + * * [RenderedSpell] * * [Unit] as our type-safe null * * [ArrayList>][ArrayList] * The constructor guarantees we won't pass a type that isn't one of those types. @@ -30,7 +31,7 @@ class SpellDatum private constructor(val payload: T) { else payload } else { - throw CastException(CastException.Reason.OP_WRONG_TYPE, U::class.java, clazz) + throw CastException(CastException.Reason.OP_WRONG_TYPE, U::class.java, this.payload) } fun serializeToNBT(): CompoundTag { @@ -61,6 +62,13 @@ class SpellDatum private constructor(val payload: T) { return out } + override fun toString(): String = + buildString { + append("SpellDatum[") + append(this@SpellDatum.payload.toString()) + append(']') + } + companion object { fun make(payload: T): SpellDatum = if (!IsValidType(payload)) { @@ -102,6 +110,7 @@ class SpellDatum private constructor(val payload: T) { Entity::class.java, Double::class.java, Vec3::class.java, + RenderedSpell::class.java, Unit::class.java, ArrayList::class.java, ) diff --git a/src/main/java/at/petrak/hex/casting/operators/spells/OpPrint.kt b/src/main/java/at/petrak/hex/casting/operators/spells/OpPrint.kt index 050e6587..eabf1ccf 100644 --- a/src/main/java/at/petrak/hex/casting/operators/spells/OpPrint.kt +++ b/src/main/java/at/petrak/hex/casting/operators/spells/OpPrint.kt @@ -17,7 +17,7 @@ object OpPrint : SpellOperator { class Spell(private val datum: SpellDatum<*>) : RenderedSpell { override fun cast(ctx: CastingContext) { ctx.caster.sendMessage( - TextComponent(datum.toString()), + TextComponent(if (datum.payload is Unit) "null" else datum.payload.toString()), Util.NIL_UUID ) } diff --git a/src/main/java/at/petrak/hex/client/HexRenderOverlays.java b/src/main/java/at/petrak/hex/client/HexRenderOverlays.java index 852f8adf..3616700f 100644 --- a/src/main/java/at/petrak/hex/client/HexRenderOverlays.java +++ b/src/main/java/at/petrak/hex/client/HexRenderOverlays.java @@ -36,8 +36,7 @@ public class HexRenderOverlays { if (tag.contains(CastingHarness.TAG_POINTS)) { PoseStack ps = e.getMatrixStack(); Minecraft mc = Minecraft.getInstance(); - MultiBufferSource buffers = mc.renderBuffers().bufferSource(); - + MultiBufferSource.BufferSource buffers = mc.renderBuffers().bufferSource(); Vec3 camPos = mc.gameRenderer.getMainCamera().getPosition(); Vec3 eyePos = player.getEyePosition(e.getPartialTicks()); @@ -70,10 +69,11 @@ public class HexRenderOverlays { VertexConsumer buf1 = buffers.getBuffer(RenderType.LINES); addVertex(ps, buf1, player.position().add(player.getLookAngle())); } - } } ps.popPose(); + buffers.endBatch(); + } } @@ -82,6 +82,7 @@ public class HexRenderOverlays { private static void addVertex(PoseStack ps, VertexConsumer buf, Vec3 vert) { buf.vertex(ps.last().pose(), (float) vert.x, (float) vert.y, (float) vert.z) .color(128, 128, 255, 255) + .normal(0.0f, 1.0f, 0.0f) .endVertex(); } } diff --git a/src/main/java/at/petrak/hex/hexes/HexPattern.kt b/src/main/java/at/petrak/hex/hexes/HexPattern.kt index 49086cc2..bc24bd2b 100644 --- a/src/main/java/at/petrak/hex/hexes/HexPattern.kt +++ b/src/main/java/at/petrak/hex/hexes/HexPattern.kt @@ -65,7 +65,7 @@ data class HexPattern(val startDir: HexDir, val angles: MutableList = } override fun toString(): String = buildString { - append("[HexPattern ") + append("HexPattern[") append(this@HexPattern.startDir) append(", ") append(this@HexPattern.anglesSignature()) diff --git a/src/main/java/at/petrak/hex/items/ItemWand.java b/src/main/java/at/petrak/hex/items/ItemWand.java index 6d213f3c..2b5cc98e 100644 --- a/src/main/java/at/petrak/hex/items/ItemWand.java +++ b/src/main/java/at/petrak/hex/items/ItemWand.java @@ -34,7 +34,10 @@ public class ItemWand extends Item { CastingHarness harness = CastingHarness.DeserializeFromNBT(stack.getOrCreateTag(), player); CastResult res = harness.update(); - if (!(res instanceof CastResult.Nothing)) { + if (res instanceof CastResult.Nothing) { + // Save back the context + stack.setTag(harness.serializeToNBT()); + } else { if (res instanceof CastResult.Success) { CastResult.Success success = (CastResult.Success) res; success.getSpell().cast(harness.getCtx()); @@ -44,9 +47,6 @@ public class ItemWand extends Item { } // In any case clear the tag, we're through stack.setTag(new CompoundTag()); - } else { - // Save back the context - stack.setTag(harness.serializeToNBT()); } } }