diff --git a/src/main/java/ru/dbotthepony/mc/otm/client/render/BlackHoleRenderer.kt b/src/main/java/ru/dbotthepony/mc/otm/client/render/BlackHoleRenderer.kt index a7cfc993f..e55625787 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/client/render/BlackHoleRenderer.kt +++ b/src/main/java/ru/dbotthepony/mc/otm/client/render/BlackHoleRenderer.kt @@ -1,55 +1,155 @@ -package ru.dbotthepony.mc.otm.client.render; +package ru.dbotthepony.mc.otm.client.render -import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.PoseStack; -import net.minecraft.client.renderer.GameRenderer; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.world.phys.Vec3; -import ru.dbotthepony.mc.otm.block.entity.blackhole.BlockEntityBlackHole; +import com.mojang.blaze3d.systems.RenderSystem +import com.mojang.blaze3d.vertex.* +import com.mojang.math.Matrix4f +import net.minecraft.client.Minecraft +import net.minecraft.client.renderer.GameRenderer +import net.minecraft.client.renderer.MultiBufferSource +import net.minecraft.client.renderer.blockentity.BlockEntityRenderer +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider +import net.minecraft.resources.ResourceLocation +import net.minecraft.world.phys.Vec3 +import org.lwjgl.opengl.GL30 +import ru.dbotthepony.mc.otm.Registry +import ru.dbotthepony.mc.otm.block.entity.blackhole.BlockEntityBlackHole +import ru.dbotthepony.mc.otm.core.* -import static org.lwjgl.opengl.GL33.*; +private const val BEAM_WIDTH = 0.2 -public class BlackHoleRenderer implements BlockEntityRenderer { - @Override - public void render(BlockEntityBlackHole blockEntityBlackHole, float v, PoseStack poseStack, MultiBufferSource multiBufferSource, int i, int i1) { - RenderHelper.setDrawColor(RGBAColor.BLACK); +private fun pushQuad(matrix4f: Matrix4f, builder: BufferBuilder, quad: Array, fwdRotation: Double, rightRotation: Double, topRotation: Double, anim: Float) { + var a = quad[0] + var b = quad[1] + var c = quad[2] + var d = quad[3] - RenderSystem.setShader(GameRenderer::getPositionColorShader); - RenderSystem.depthFunc(GL_LESS); - RenderSystem.depthMask(true); - - RenderSystem.enableDepthTest(); - RenderSystem.disableCull(); - - poseStack.pushPose(); - poseStack.translate(0.5, -blockEntityBlackHole.getGravitationStrength() / 2 + 0.5, 0.5); - - RenderHelper.colorSphere(poseStack, (float) blockEntityBlackHole.getGravitationStrength()); - - poseStack.popPose(); - - RenderSystem.enableCull(); - RenderSystem.enableTexture(); + if (fwdRotation != 0.0) { + a = a.rotateAroundAxis(VECTOR_FORWARD, fwdRotation) + b = b.rotateAroundAxis(VECTOR_FORWARD, fwdRotation) + c = c.rotateAroundAxis(VECTOR_FORWARD, fwdRotation) + d = d.rotateAroundAxis(VECTOR_FORWARD, fwdRotation) } - @Override - public boolean shouldRenderOffScreen(BlockEntityBlackHole p_112306_) { - return true; + if (rightRotation != 0.0) { + a = a.rotateAroundAxis(VECTOR_RIGHT, rightRotation) + b = b.rotateAroundAxis(VECTOR_RIGHT, rightRotation) + c = c.rotateAroundAxis(VECTOR_RIGHT, rightRotation) + d = d.rotateAroundAxis(VECTOR_RIGHT, rightRotation) + } else if (topRotation != 0.0) { + a = a.rotateAroundAxis(VECTOR_UP, topRotation) + b = b.rotateAroundAxis(VECTOR_UP, topRotation) + c = c.rotateAroundAxis(VECTOR_UP, topRotation) + d = d.rotateAroundAxis(VECTOR_UP, topRotation) } - @Override - public boolean shouldRender(BlockEntityBlackHole p_173568_, Vec3 p_173569_) { - return true; - } - - @Override - public int getViewDistance() { - return 512; - } - - public BlackHoleRenderer(BlockEntityRendererProvider.Context context) { - - } + builder.vertex(matrix4f, b.x.toFloat(), b.y.toFloat(), b.z.toFloat()).uv(0f, anim).endVertex() + builder.vertex(matrix4f, c.x.toFloat(), c.y.toFloat(), c.z.toFloat()).uv(1f, anim).endVertex() + builder.vertex(matrix4f, d.x.toFloat(), d.y.toFloat(), d.z.toFloat()).uv(1f, anim + 64f).endVertex() + builder.vertex(matrix4f, a.x.toFloat(), a.y.toFloat(), a.z.toFloat()).uv(0f, anim + 64f).endVertex() } + +private val quadA = quadY(-BEAM_WIDTH) +private val quadB = quadY(BEAM_WIDTH) +private val quadC = quadZ(-BEAM_WIDTH) +private val quadD = quadZ(BEAM_WIDTH) + +private fun beam(matrix4f: Matrix4f, builder: BufferBuilder, fwdRotation: Double, rightRotation: Double, topRotation: Double, anim: Float) { + pushQuad(matrix4f, builder, quadA, fwdRotation, rightRotation, topRotation, anim) + pushQuad(matrix4f, builder, quadB, fwdRotation, rightRotation, topRotation, anim) + pushQuad(matrix4f, builder, quadC, fwdRotation, rightRotation, topRotation, anim) + pushQuad(matrix4f, builder, quadD, fwdRotation, rightRotation, topRotation, anim) +} + +private fun quadY(z: Double): Array { + return arrayOf( + Vector(0.0, -BEAM_WIDTH, z), + Vector(64.0, -BEAM_WIDTH, z), + Vector(64.0, BEAM_WIDTH, z), + Vector(0.0, BEAM_WIDTH, z) + ) +} + +private fun quadZ(y: Double): Array { + return arrayOf( + Vector(0.0, y, -BEAM_WIDTH), + Vector(64.0, y, -BEAM_WIDTH), + Vector(64.0, y, BEAM_WIDTH), + Vector(0.0, y, BEAM_WIDTH) + ) +} + +class BlackHoleRenderer(private val context: BlockEntityRendererProvider.Context) : BlockEntityRenderer { + override fun render( + blockEntityBlackHole: BlockEntityBlackHole, + v: Float, + poseStack: PoseStack, + multiBufferSource: MultiBufferSource, + i: Int, + i1: Int + ) { + RenderHelper.setDrawColor(RGBAColor.BLACK) + RenderSystem.setShader(GameRenderer::getPositionColorShader) + + RenderSystem.depthFunc(GL30.GL_LESS) + RenderSystem.depthMask(true) + RenderSystem.enableDepthTest() + RenderSystem.disableCull() + + poseStack.pushPose() + poseStack.translate(0.5, -blockEntityBlackHole.gravitationStrength / 2 + 0.5, 0.5) + RenderHelper.colorSphere(poseStack, blockEntityBlackHole.gravitationStrength.toFloat()) + + RenderSystem.enableCull() + RenderSystem.enableTexture() + + poseStack.popPose() + + val ply = Minecraft.getInstance().player + + if (ply != null && ply.mainHandItem.item == Registry.Items.GRAVITATION_STABILIZER) { + RenderSystem.setShader(GameRenderer::getPositionTexShader) + RenderSystem.setShaderTexture(0, ResourceLocation("minecraft", "textures/entity/beacon_beam.png")) + RenderSystem.disableCull() + + val builder = Tesselator.getInstance().builder + builder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX) + + val anim = (((System.currentTimeMillis().toDouble() / 100.0) % 100.0).toFloat() / 100f) * 64f + val rotation = System.currentTimeMillis().toDouble() / 1000.0 + + poseStack.pushPose() + poseStack.translate(0.5, 0.5, 0.5) + val matrix = poseStack.last().pose() + + beam(matrix, builder, rotation, 0.0, 0.0, anim) + beam(matrix, builder, rotation, 0.0, Math.PI / 2, anim) + beam(matrix, builder, rotation, 0.0, -Math.PI / 2, anim) + beam(matrix, builder, rotation, 0.0, Math.PI, anim) + beam(matrix, builder, rotation, Math.PI / 2, 0.0, anim) + beam(matrix, builder, rotation, -Math.PI / 2, 0.0, anim) + beam(matrix, builder, rotation, Math.PI, 0.0, anim) + + poseStack.popPose() + + builder.end() + BufferUploader.end(builder) + RenderSystem.enableCull() + } + } + + override fun shouldRenderOffScreen(p_112306_: BlockEntityBlackHole): Boolean { + return true + } + + override fun shouldRender(p_173568_: BlockEntityBlackHole, p_173569_: Vec3): Boolean { + return true + } + + override fun getViewDistance(): Int { + return 512 + } + + companion object { + private val BEACON_BEAM = ResourceLocation("minecraft", "textures/entity/beacon_beam") + } +} \ No newline at end of file diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/Math.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/EuclidMath.kt similarity index 61% rename from src/main/kotlin/ru/dbotthepony/mc/otm/core/Math.kt rename to src/main/kotlin/ru/dbotthepony/mc/otm/core/EuclidMath.kt index 4882e5dda..b00ec28dd 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/Math.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/EuclidMath.kt @@ -1,49 +1,42 @@ package ru.dbotthepony.mc.otm.core -import net.minecraft.core.BlockPos -import net.minecraft.core.Direction -import net.minecraft.core.Vec3i +import com.mojang.math.Quaternion +import com.mojang.math.Vector3f import net.minecraft.world.phys.Vec3 -import kotlin.math.sin -import kotlin.math.cos import kotlin.math.acos +import kotlin.math.cos +import kotlin.math.sin typealias Vector = Vec3 val VECTOR_UP = Vector(0.0, 1.0, 0.0) +val VECTOR_FORWARD = Vector(1.0, 0.0, 0.0) +val VECTOR_BACKWARD = Vector(1.0, 0.0, 0.0) val VECTOR_DOWN = Vector(0.0, -1.0, 0.0) -val VECTOR_BACK = Vector(0.0, 0.0, 1.0) - -fun BlockPos.asVector(): Vector { - return Vector(x + 0.5, y + 0.5, z + 0.5) -} +val VECTOR_RIGHT = Vector(0.0, 0.0, 1.0) +val VECTOR_LEFT = Vector(0.0, 0.0, -1.0) fun Vector.asAngle(): Angle { val norm = normalize() if (norm.x < 0) { - return Angle(acos(norm.dot(VECTOR_UP)) - Angle.PI_HALF, -acos(Vector(norm.x, 0.0, norm.z).normalize().dot(VECTOR_BACK))) + return Angle(acos(norm.dot(VECTOR_UP)) - Angle.PI_HALF, -acos(Vector(norm.x, 0.0, norm.z).normalize().dot(VECTOR_RIGHT))) } - return Angle(acos(norm.dot(VECTOR_UP)) - Angle.PI_HALF, acos(Vector(norm.x, 0.0, norm.z).normalize().dot(VECTOR_BACK))) + return Angle(acos(norm.dot(VECTOR_UP)) - Angle.PI_HALF, acos(Vector(norm.x, 0.0, norm.z).normalize().dot(VECTOR_RIGHT))) } -operator fun BlockPos.plus(direction: Vec3i): BlockPos = this.offset(direction) -operator fun BlockPos.plus(direction: Direction): BlockPos = this.offset(direction.normal) -operator fun BlockPos.minus(direction: Vec3i): BlockPos = this.subtract(direction) -operator fun BlockPos.minus(direction: Direction): BlockPos = this.subtract(direction.normal) - -operator fun Vec3i.plus(direction: Vec3i): Vec3i = this.offset(direction) -operator fun Vec3i.plus(direction: Direction): Vec3i = this.offset(direction.normal) -operator fun Vec3i.minus(direction: Vec3i): Vec3i = this.subtract(direction) -operator fun Vec3i.minus(direction: Direction): Vec3i = this.subtract(direction.normal) - -operator fun Vec3i.times(int: Int): Vec3i = this.multiply(int) - operator fun Vector.plus(direction: Vector): Vector = this.add(direction) operator fun Vector.minus(direction: Vector): Vector = this.subtract(direction) - +operator fun Vector.unaryMinus(): Vector = Vector(-x, -y, -z) +operator fun Vector.component1() = x +operator fun Vector.component2() = y +operator fun Vector.component3() = z operator fun Vector.times(v: Double): Vector = this.multiply(v, v, v) +operator fun Vector.div(v: Double): Vector { + val inv = 1.0 / v + return this.multiply(inv, inv, inv) +} fun Vector.left() = asAngle().left() * this.length() fun Vector.right() = asAngle().right() * this.length() @@ -54,22 +47,39 @@ fun Vector.rotateAroundAxis(axis: Vector, rotation: Double): Vector { return this * cos(rotation) + axis.cross(this) * sin(rotation) + axis * axis.dot(this) * (1 - cos(rotation)) } -operator fun Vector.component1() = x -operator fun Vector.component2() = y -operator fun Vector.component3() = z +fun Vector.rotate(angle: Angle): Vector { + val rotatedYaw = this.rotateAroundAxis(VECTOR_UP, angle.yaw) + return rotatedYaw.rotateAroundAxis(rotatedYaw.asAngle().left(), angle.pitch) +} + +fun Vector.asVector3f(): Vector3f { + return Vector3f(x.toFloat(), y.toFloat(), z.toFloat()) +} + +fun Quaternion(vec: Vector, rotation: Float, isDegrees: Boolean): Quaternion { + return Quaternion(vec.asVector3f(), rotation, isDegrees) +} + +fun Vector(x: Double): Vector { + return Vector(x, 0.0, 0.0) +} + +fun Vector(x: Double, y: Double): Vector { + return Vector(x, y, 0.0) +} + +fun Vector.rotate(q: Quaternion): Vector { + val quaternion = Quaternion(q) + quaternion.mul(Quaternion(x.toFloat(), y.toFloat(), z.toFloat(), 0.0f)) + val quaternion1 = Quaternion(q) + quaternion1.conj() + quaternion.mul(quaternion1) + return Vector(quaternion.i().toDouble(), quaternion.j().toDouble(), quaternion.k().toDouble()) +} data class Angle(val pitch: Double = 0.0, val yaw: Double = 0.0, val roll: Double = 0.0) { fun forward(): Vector { - val yaw = yaw - PI_HALF - val x = cos(yaw) * cos(pitch) - val y = -sin(pitch) - val z = sin(yaw) * cos(pitch) - - return Vector(x, y, z) - } - - fun right(): Vector { - val pitch = 0.0 + val yaw = yaw val x = cos(yaw) * cos(pitch) val y = -sin(pitch) val z = sin(yaw) * cos(pitch) @@ -78,6 +88,10 @@ data class Angle(val pitch: Double = 0.0, val yaw: Double = 0.0, val roll: Doubl } fun left(): Vector { + return -right() + } + + fun right(): Vector { val yaw = yaw + PI_HALF val pitch = 0.0 val x = cos(yaw) * cos(pitch) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/Ext.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/Ext.kt new file mode 100644 index 000000000..946e10c5b --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/Ext.kt @@ -0,0 +1,21 @@ +package ru.dbotthepony.mc.otm.core + +import net.minecraft.core.BlockPos +import net.minecraft.core.Direction +import net.minecraft.core.Vec3i + +operator fun BlockPos.plus(direction: Vec3i): BlockPos = this.offset(direction) +operator fun BlockPos.plus(direction: Direction): BlockPos = this.offset(direction.normal) +operator fun BlockPos.minus(direction: Vec3i): BlockPos = this.subtract(direction) +operator fun BlockPos.minus(direction: Direction): BlockPos = this.subtract(direction.normal) + +operator fun Vec3i.plus(direction: Vec3i): Vec3i = this.offset(direction) +operator fun Vec3i.plus(direction: Direction): Vec3i = this.offset(direction.normal) +operator fun Vec3i.minus(direction: Vec3i): Vec3i = this.subtract(direction) +operator fun Vec3i.minus(direction: Direction): Vec3i = this.subtract(direction.normal) + +operator fun Vec3i.times(int: Int): Vec3i = this.multiply(int) + +fun BlockPos.asVector(): Vector { + return Vector(x + 0.5, y + 0.5, z + 0.5) +}