A lot of math stuff and text rendering in gmod api style
This commit is contained in:
parent
bb3da639b0
commit
1ce4578336
@ -9,13 +9,15 @@ import net.minecraft.client.renderer.MultiBufferSource
|
|||||||
import net.minecraft.client.renderer.blockentity.BeaconRenderer
|
import net.minecraft.client.renderer.blockentity.BeaconRenderer
|
||||||
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer
|
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer
|
||||||
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider
|
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider
|
||||||
import net.minecraft.resources.ResourceLocation
|
import net.minecraft.network.chat.TranslatableComponent
|
||||||
import net.minecraft.world.phys.Vec3
|
import net.minecraft.world.phys.Vec3
|
||||||
import org.lwjgl.opengl.GL30
|
import org.lwjgl.opengl.GL30
|
||||||
import ru.dbotthepony.mc.otm.Registry
|
import ru.dbotthepony.mc.otm.Registry
|
||||||
import ru.dbotthepony.mc.otm.block.entity.BlockEntityGravitationStabilizer
|
import ru.dbotthepony.mc.otm.block.entity.BlockEntityGravitationStabilizer
|
||||||
import ru.dbotthepony.mc.otm.block.entity.blackhole.BlockEntityBlackHole
|
import ru.dbotthepony.mc.otm.block.entity.blackhole.BlockEntityBlackHole
|
||||||
|
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
||||||
import ru.dbotthepony.mc.otm.core.*
|
import ru.dbotthepony.mc.otm.core.*
|
||||||
|
import kotlin.math.PI
|
||||||
|
|
||||||
private const val BEAM_WIDTH = 0.2
|
private const val BEAM_WIDTH = 0.2
|
||||||
|
|
||||||
@ -82,7 +84,7 @@ private fun quadZ(y: Double): Array<Vector> {
|
|||||||
|
|
||||||
class BlackHoleRenderer(private val context: BlockEntityRendererProvider.Context) : BlockEntityRenderer<BlockEntityBlackHole> {
|
class BlackHoleRenderer(private val context: BlockEntityRendererProvider.Context) : BlockEntityRenderer<BlockEntityBlackHole> {
|
||||||
override fun render(
|
override fun render(
|
||||||
blockEntityBlackHole: BlockEntityBlackHole,
|
tile: BlockEntityBlackHole,
|
||||||
v: Float,
|
v: Float,
|
||||||
poseStack: PoseStack,
|
poseStack: PoseStack,
|
||||||
multiBufferSource: MultiBufferSource,
|
multiBufferSource: MultiBufferSource,
|
||||||
@ -98,8 +100,8 @@ class BlackHoleRenderer(private val context: BlockEntityRendererProvider.Context
|
|||||||
RenderSystem.disableCull()
|
RenderSystem.disableCull()
|
||||||
|
|
||||||
poseStack.pushPose()
|
poseStack.pushPose()
|
||||||
poseStack.translate(0.5, -blockEntityBlackHole.gravitationStrength / 2 + 0.5, 0.5)
|
poseStack.translate(0.5, -tile.gravitationStrength / 2 + 0.5, 0.5)
|
||||||
RenderHelper.colorSphere(poseStack, blockEntityBlackHole.gravitationStrength.toFloat())
|
RenderHelper.colorSphere(poseStack, tile.gravitationStrength.toFloat())
|
||||||
|
|
||||||
RenderSystem.enableCull()
|
RenderSystem.enableCull()
|
||||||
RenderSystem.enableTexture()
|
RenderSystem.enableTexture()
|
||||||
@ -137,6 +139,40 @@ class BlackHoleRenderer(private val context: BlockEntityRendererProvider.Context
|
|||||||
BufferUploader.end(builder)
|
BufferUploader.end(builder)
|
||||||
RenderSystem.enableCull()
|
RenderSystem.enableCull()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
ply != null &&
|
||||||
|
ply.getCapability(MatteryCapability.ANDROID).isPresent &&
|
||||||
|
ply.getCapability(MatteryCapability.ANDROID).resolve().get().isAndroid() &&
|
||||||
|
poseStack.translation().length() < tile.gravitationStrength * 16.0
|
||||||
|
) {
|
||||||
|
val facing = tile.blockPos.asVector() - Minecraft.getInstance().gameRenderer.mainCamera.position
|
||||||
|
val normal = facing.normalize()
|
||||||
|
|
||||||
|
val ang = normal.asMutableAngle()
|
||||||
|
ang.roll = ang.pitch - PI
|
||||||
|
ang.yaw = ang.yaw - PI * 1.1
|
||||||
|
ang.pitch = 0.0
|
||||||
|
|
||||||
|
poseStack.pushPose()
|
||||||
|
poseStack.translate(0.5, 0.75, 0.5)
|
||||||
|
poseStack.translate(ang.forward() * tile.gravitationStrength * 1.1)
|
||||||
|
|
||||||
|
poseStack.rotateAroundPoint(poseStack.translation(), ang)
|
||||||
|
poseStack.scale(0.05f, 0.05f, 0.05f)
|
||||||
|
|
||||||
|
val font = Minecraft.getInstance().font
|
||||||
|
val text1 = TranslatableComponent("otm.3d2d.gravitation_stabilizer.mass", tile.mass.decimalString(2))
|
||||||
|
val text2 = TranslatableComponent("otm.3d2d.gravitation_stabilizer.strength", "%.2f".format(tile.gravitationStrength))
|
||||||
|
|
||||||
|
font.drawAligned(poseStack, text1, TextAlign.TOP_LEFT, 0.8f, 0.8f - font.lineHeight.toFloat() / 2f, 0x0)
|
||||||
|
font.drawAligned(poseStack, text2, TextAlign.TOP_LEFT, 0.8f, 0.8f + font.lineHeight.toFloat() / 2f, 0x0)
|
||||||
|
poseStack.translate(0.0, 0.0, -1.0)
|
||||||
|
font.drawAligned(poseStack, text1, TextAlign.TOP_LEFT, 0f, -font.lineHeight.toFloat() / 2f, 0xFFFFFF)
|
||||||
|
font.drawAligned(poseStack, text2, TextAlign.TOP_LEFT, 0f, font.lineHeight.toFloat() / 2f, 0xFFFFFF)
|
||||||
|
|
||||||
|
poseStack.popPose()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun shouldRenderOffScreen(p_112306_: BlockEntityBlackHole): Boolean {
|
override fun shouldRenderOffScreen(p_112306_: BlockEntityBlackHole): Boolean {
|
||||||
|
@ -1,9 +1,119 @@
|
|||||||
package ru.dbotthepony.mc.otm.client.render
|
package ru.dbotthepony.mc.otm.client.render
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack
|
||||||
import com.mojang.blaze3d.vertex.VertexConsumer
|
import com.mojang.blaze3d.vertex.VertexConsumer
|
||||||
import com.mojang.math.Matrix4f
|
import com.mojang.math.Matrix4f
|
||||||
import ru.dbotthepony.mc.otm.core.Vector
|
import com.mojang.math.Vector3f
|
||||||
|
import net.minecraft.client.gui.Font
|
||||||
|
import net.minecraft.network.chat.Component
|
||||||
|
import net.minecraft.util.FormattedCharSequence
|
||||||
|
import ru.dbotthepony.mc.otm.core.*
|
||||||
|
|
||||||
fun VertexConsumer.normal(vector: Vector) = normal(vector.x.toFloat(), vector.y.toFloat(), vector.z.toFloat())
|
fun VertexConsumer.normal(vector: Vector) = normal(vector.x.toFloat(), vector.y.toFloat(), vector.z.toFloat())
|
||||||
fun VertexConsumer.vertex(matrix4f: Matrix4f, vector: Vector) = vertex(matrix4f, vector.x.toFloat(), vector.y.toFloat(), vector.z.toFloat())
|
fun VertexConsumer.vertex(matrix4f: Matrix4f, vector: Vector) = vertex(matrix4f, vector.x.toFloat(), vector.y.toFloat(), vector.z.toFloat())
|
||||||
fun VertexConsumer.color(color: RGBAColor) = color(color.r, color.g, color.b, color.a)
|
fun VertexConsumer.color(color: RGBAColor) = color(color.r, color.g, color.b, color.a)
|
||||||
|
|
||||||
|
fun PoseStack.translate(vector: Vector) = translate(vector.x, vector.y, vector.z)
|
||||||
|
fun PoseStack.translate(vector: Vector3f) = last().pose().multiplyWithTranslation(vector.x(), vector.y(), vector.z())
|
||||||
|
|
||||||
|
fun PoseStack.rotateAroundPoint(point: Vector, axis: Vector, rotation: Float, isDegrees: Boolean = false) {
|
||||||
|
val last = last()
|
||||||
|
last.pose().rotateAroundPoint(point, axis, rotation, isDegrees)
|
||||||
|
last.normal().mul(axis.rotateAroundThis(rotation, isDegrees))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun PoseStack.rotateAroundPoint(point: Vector, rotation: IAngle) {
|
||||||
|
val last = last()
|
||||||
|
last.pose().rotateAroundPoint(point, rotation)
|
||||||
|
// last.normal().mul(rotation.forward().rotateAroundThis(rotation))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun PoseStack.rotateAroundPoint(point: Vector3f, axis: Vector, rotation: Float, isDegrees: Boolean = false) {
|
||||||
|
val last = last()
|
||||||
|
last.pose().rotateAroundPoint(point, axis, rotation, isDegrees)
|
||||||
|
last.normal().mul(axis.rotateAroundThis(rotation, isDegrees))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun PoseStack.rotateAroundPoint(point: Vector3f, rotation: IAngle) {
|
||||||
|
val last = last()
|
||||||
|
last.pose().rotateAroundPoint(point, rotation)
|
||||||
|
// last.normal().mul(rotation.forward().rotateAroundThis(rotation))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun PoseStack.translation(): Vector3f {
|
||||||
|
return last().pose().getTranslation()
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class TextAlign {
|
||||||
|
TOP_LEFT,
|
||||||
|
TOP_CENTER,
|
||||||
|
TOP_RIGHT,
|
||||||
|
|
||||||
|
CENTER_LEFT,
|
||||||
|
CENTER_CENTER,
|
||||||
|
CENTER_RIGHT,
|
||||||
|
|
||||||
|
BOTTOM_LEFT,
|
||||||
|
BOTTOM_CENTER,
|
||||||
|
BOTTOM_RIGHT,
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Font.drawAligned(poseStack: PoseStack, text: String, align: TextAlign, x: Float, y: Float, color: Int): Int {
|
||||||
|
return when (align) {
|
||||||
|
TextAlign.TOP_LEFT -> draw(poseStack, text, x, y, color)
|
||||||
|
TextAlign.TOP_CENTER -> draw(poseStack, text, x - width(text) / 2f, y, color)
|
||||||
|
TextAlign.TOP_RIGHT -> draw(poseStack, text, x - width(text), y, color)
|
||||||
|
|
||||||
|
TextAlign.CENTER_LEFT -> draw(poseStack, text, x, y - lineHeight / 2f, color)
|
||||||
|
TextAlign.CENTER_CENTER -> draw(poseStack, text, x - width(text) / 2f, y - lineHeight / 2f, color)
|
||||||
|
TextAlign.CENTER_RIGHT -> draw(poseStack, text, x - width(text), y - lineHeight / 2f, color)
|
||||||
|
|
||||||
|
TextAlign.BOTTOM_LEFT -> draw(poseStack, text, x, y - lineHeight, color)
|
||||||
|
TextAlign.BOTTOM_CENTER -> draw(poseStack, text, x - width(text) / 2f, y - lineHeight, color)
|
||||||
|
TextAlign.BOTTOM_RIGHT -> draw(poseStack, text, x - width(text), y - lineHeight, color)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Font.drawAligned(poseStack: PoseStack, text: Component, align: TextAlign, x: Float, y: Float, color: Int): Int {
|
||||||
|
return when (align) {
|
||||||
|
TextAlign.TOP_LEFT -> draw(poseStack, text, x, y, color)
|
||||||
|
TextAlign.TOP_CENTER -> draw(poseStack, text, x - width(text) / 2f, y, color)
|
||||||
|
TextAlign.TOP_RIGHT -> draw(poseStack, text, x - width(text), y, color)
|
||||||
|
|
||||||
|
TextAlign.CENTER_LEFT -> draw(poseStack, text, x, y - lineHeight / 2f, color)
|
||||||
|
TextAlign.CENTER_CENTER -> draw(poseStack, text, x - width(text) / 2f, y - lineHeight / 2f, color)
|
||||||
|
TextAlign.CENTER_RIGHT -> draw(poseStack, text, x - width(text), y - lineHeight / 2f, color)
|
||||||
|
|
||||||
|
TextAlign.BOTTOM_LEFT -> draw(poseStack, text, x, y - lineHeight, color)
|
||||||
|
TextAlign.BOTTOM_CENTER -> draw(poseStack, text, x - width(text) / 2f, y - lineHeight, color)
|
||||||
|
TextAlign.BOTTOM_RIGHT -> draw(poseStack, text, x - width(text), y - lineHeight, color)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Font.drawAligned(poseStack: PoseStack, text: FormattedCharSequence, align: TextAlign, x: Float, y: Float, color: Int): Int {
|
||||||
|
return when (align) {
|
||||||
|
TextAlign.TOP_LEFT -> draw(poseStack, text, x, y, color)
|
||||||
|
TextAlign.TOP_CENTER -> draw(poseStack, text, x - width(text) / 2f, y, color)
|
||||||
|
TextAlign.TOP_RIGHT -> draw(poseStack, text, x - width(text), y, color)
|
||||||
|
|
||||||
|
TextAlign.CENTER_LEFT -> draw(poseStack, text, x, y - lineHeight / 2f, color)
|
||||||
|
TextAlign.CENTER_CENTER -> draw(poseStack, text, x - width(text) / 2f, y - lineHeight / 2f, color)
|
||||||
|
TextAlign.CENTER_RIGHT -> draw(poseStack, text, x - width(text), y - lineHeight / 2f, color)
|
||||||
|
|
||||||
|
TextAlign.BOTTOM_LEFT -> draw(poseStack, text, x, y - lineHeight, color)
|
||||||
|
TextAlign.BOTTOM_CENTER -> draw(poseStack, text, x - width(text) / 2f, y - lineHeight, color)
|
||||||
|
TextAlign.BOTTOM_RIGHT -> draw(poseStack, text, x - width(text), y - lineHeight, color)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Font.drawAligned(poseStack: PoseStack, text: String, align: TextAlign, x: Float, y: Float, color: RGBAColor): Int {
|
||||||
|
return drawAligned(poseStack, text, align, x, y, color.toInt())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Font.drawAligned(poseStack: PoseStack, text: Component, align: TextAlign, x: Float, y: Float, color: RGBAColor): Int {
|
||||||
|
return drawAligned(poseStack, text, align, x, y, color.toInt())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Font.drawAligned(poseStack: PoseStack, text: FormattedCharSequence, align: TextAlign, x: Float, y: Float, color: RGBAColor): Int {
|
||||||
|
return drawAligned(poseStack, text, align, x, y, color.toInt())
|
||||||
|
}
|
||||||
|
@ -2,6 +2,9 @@ package ru.dbotthepony.mc.otm.client.render
|
|||||||
|
|
||||||
import com.mojang.blaze3d.vertex.*
|
import com.mojang.blaze3d.vertex.*
|
||||||
import com.mojang.math.Matrix4f
|
import com.mojang.math.Matrix4f
|
||||||
|
import com.mojang.math.Vector3f
|
||||||
|
import net.minecraft.client.Minecraft
|
||||||
|
import net.minecraft.client.gui.Font
|
||||||
import net.minecraft.client.renderer.MultiBufferSource
|
import net.minecraft.client.renderer.MultiBufferSource
|
||||||
import net.minecraft.client.renderer.RenderType
|
import net.minecraft.client.renderer.RenderType
|
||||||
import net.minecraft.client.renderer.blockentity.BeaconRenderer
|
import net.minecraft.client.renderer.blockentity.BeaconRenderer
|
||||||
@ -9,6 +12,8 @@ import net.minecraft.client.renderer.blockentity.BlockEntityRenderer
|
|||||||
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider
|
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider
|
||||||
import net.minecraft.client.renderer.texture.OverlayTexture
|
import net.minecraft.client.renderer.texture.OverlayTexture
|
||||||
import net.minecraft.core.Direction
|
import net.minecraft.core.Direction
|
||||||
|
import net.minecraft.network.chat.TextComponent
|
||||||
|
import net.minecraft.network.chat.TranslatableComponent
|
||||||
import ru.dbotthepony.mc.otm.block.BlockBlackHole
|
import ru.dbotthepony.mc.otm.block.BlockBlackHole
|
||||||
import ru.dbotthepony.mc.otm.block.BlockMatteryRotatable
|
import ru.dbotthepony.mc.otm.block.BlockMatteryRotatable
|
||||||
import ru.dbotthepony.mc.otm.block.entity.BlockEntityGravitationStabilizer
|
import ru.dbotthepony.mc.otm.block.entity.BlockEntityGravitationStabilizer
|
||||||
@ -35,13 +40,16 @@ class GravitationStabilizerRenderer(private val context: BlockEntityRendererProv
|
|||||||
var len = 64.0
|
var len = 64.0
|
||||||
val normal = tile.blockState.getValue(BlockMatteryRotatable.FACING_FULL).normal
|
val normal = tile.blockState.getValue(BlockMatteryRotatable.FACING_FULL).normal
|
||||||
val level = tile.level
|
val level = tile.level
|
||||||
|
var bhTile: BlockEntityBlackHole? = null
|
||||||
|
|
||||||
if (level != null) {
|
if (level != null) {
|
||||||
for (i in 1 .. BlockEntityGravitationStabilizer.RANGE) {
|
for (i in 1 .. BlockEntityGravitationStabilizer.RANGE) {
|
||||||
val pos = tile.blockPos + normal * i
|
val pos = tile.blockPos + normal * i
|
||||||
|
val getTile = level.getBlockEntity(pos) as? BlockEntityBlackHole
|
||||||
|
|
||||||
if (level.getBlockEntity(tile.blockPos + pos) is BlockEntityBlackHole || level.getBlockState(pos).block is BlockBlackHole) {
|
if (getTile != null || level.getBlockState(pos).block is BlockBlackHole) {
|
||||||
len = i.toDouble()
|
len = i.toDouble()
|
||||||
|
bhTile = getTile
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -51,12 +59,13 @@ class GravitationStabilizerRenderer(private val context: BlockEntityRendererProv
|
|||||||
poseStack.translate(0.5, 0.5, 0.5)
|
poseStack.translate(0.5, 0.5, 0.5)
|
||||||
|
|
||||||
val matrix = poseStack.last().pose()
|
val matrix = poseStack.last().pose()
|
||||||
|
val facing: Direction = tile.blockState.getValue(BlockMatteryRotatable.FACING_FULL)
|
||||||
|
|
||||||
run {
|
run {
|
||||||
val rotation = (System.currentTimeMillis().toDouble() / 1000.0) % (PI * 2)
|
val rotation = (System.currentTimeMillis().toDouble() / 1000.0) % (PI * 2)
|
||||||
val consumer = p_112310_.getBuffer(BEAM_RENDER_TYPE_INNER)
|
val consumer = p_112310_.getBuffer(BEAM_RENDER_TYPE_INNER)
|
||||||
|
|
||||||
when (tile.blockState.getValue(BlockMatteryRotatable.FACING_FULL)) {
|
when (facing) {
|
||||||
Direction.DOWN -> ray(matrix, consumer, len, rotation, -PI / 2, 0.0, RAY_RADIUS_INNER)
|
Direction.DOWN -> ray(matrix, consumer, len, rotation, -PI / 2, 0.0, RAY_RADIUS_INNER)
|
||||||
Direction.UP -> ray(matrix, consumer, len, rotation, PI / 2, 0.0, RAY_RADIUS_INNER)
|
Direction.UP -> ray(matrix, consumer, len, rotation, PI / 2, 0.0, RAY_RADIUS_INNER)
|
||||||
Direction.NORTH -> ray(matrix, consumer, len, rotation, 0.0, PI / 2, RAY_RADIUS_INNER)
|
Direction.NORTH -> ray(matrix, consumer, len, rotation, 0.0, PI / 2, RAY_RADIUS_INNER)
|
||||||
@ -70,7 +79,7 @@ class GravitationStabilizerRenderer(private val context: BlockEntityRendererProv
|
|||||||
val consumer = p_112310_.getBuffer(BEAM_RENDER_TYPE_OUTER)
|
val consumer = p_112310_.getBuffer(BEAM_RENDER_TYPE_OUTER)
|
||||||
val rotation = (-System.currentTimeMillis().toDouble() / 700.0) % (PI * 2)
|
val rotation = (-System.currentTimeMillis().toDouble() / 700.0) % (PI * 2)
|
||||||
|
|
||||||
when (tile.blockState.getValue(BlockMatteryRotatable.FACING_FULL)) {
|
when (facing) {
|
||||||
Direction.DOWN -> ray(matrix, consumer, len, rotation, -PI / 2, 0.0, RAY_RADIUS_OUTER, OUTER_COLOR)
|
Direction.DOWN -> ray(matrix, consumer, len, rotation, -PI / 2, 0.0, RAY_RADIUS_OUTER, OUTER_COLOR)
|
||||||
Direction.UP -> ray(matrix, consumer, len, rotation, PI / 2, 0.0, RAY_RADIUS_OUTER, OUTER_COLOR)
|
Direction.UP -> ray(matrix, consumer, len, rotation, PI / 2, 0.0, RAY_RADIUS_OUTER, OUTER_COLOR)
|
||||||
Direction.NORTH -> ray(matrix, consumer, len, rotation, 0.0, PI / 2, RAY_RADIUS_OUTER, OUTER_COLOR)
|
Direction.NORTH -> ray(matrix, consumer, len, rotation, 0.0, PI / 2, RAY_RADIUS_OUTER, OUTER_COLOR)
|
||||||
@ -81,6 +90,24 @@ class GravitationStabilizerRenderer(private val context: BlockEntityRendererProv
|
|||||||
}
|
}
|
||||||
|
|
||||||
poseStack.popPose()
|
poseStack.popPose()
|
||||||
|
|
||||||
|
if (bhTile != null) {
|
||||||
|
poseStack.pushPose()
|
||||||
|
poseStack.translate(0.5, 0.5, 0.5)
|
||||||
|
|
||||||
|
val translation = poseStack.translation()
|
||||||
|
|
||||||
|
poseStack.translate(facing.opposite.normal * 0.6)
|
||||||
|
poseStack.rotateAroundPoint(translation, facing.opposite.asAngle().copy(pitch = PI))
|
||||||
|
|
||||||
|
poseStack.scale(0.01f, 0.01f, 0.01f)
|
||||||
|
|
||||||
|
val font = Minecraft.getInstance().font
|
||||||
|
font.drawAligned(poseStack, TranslatableComponent("otm.3d2d.gravitation_stabilizer.mass", bhTile.mass.decimalString(2)), TextAlign.TOP_CENTER, 0f, -font.lineHeight.toFloat() / 2f, 0xFFFFFF)
|
||||||
|
font.drawAligned(poseStack, TranslatableComponent("otm.3d2d.gravitation_stabilizer.strength", "%.2f".format(bhTile.gravitationStrength)), TextAlign.TOP_CENTER, 0f, font.lineHeight.toFloat() / 2f, 0xFFFFFF)
|
||||||
|
|
||||||
|
poseStack.popPose()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun shouldRenderOffScreen(p_112306_: BlockEntityGravitationStabilizer) = true
|
override fun shouldRenderOffScreen(p_112306_: BlockEntityGravitationStabilizer) = true
|
||||||
|
@ -2,30 +2,68 @@ package ru.dbotthepony.mc.otm.core
|
|||||||
|
|
||||||
import com.mojang.math.Quaternion
|
import com.mojang.math.Quaternion
|
||||||
import com.mojang.math.Vector3f
|
import com.mojang.math.Vector3f
|
||||||
|
import net.minecraft.core.Direction
|
||||||
import net.minecraft.world.phys.Vec3
|
import net.minecraft.world.phys.Vec3
|
||||||
import kotlin.math.acos
|
import kotlin.math.*
|
||||||
import kotlin.math.cos
|
|
||||||
import kotlin.math.sin
|
|
||||||
|
|
||||||
typealias Vector = Vec3
|
typealias Vector = Vec3
|
||||||
|
|
||||||
val VECTOR_UP = Vector(0.0, 1.0, 0.0)
|
@JvmField val VECTOR_UP = Vector(0.0, 1.0, 0.0)
|
||||||
val VECTOR_FORWARD = Vector(1.0, 0.0, 0.0)
|
@JvmField val VECTOR_FORWARD = Vector(1.0, 0.0, 0.0)
|
||||||
val VECTOR_BACKWARD = Vector(1.0, 0.0, 0.0)
|
@JvmField val VECTOR_BACKWARD = Vector(-1.0, 0.0, 0.0)
|
||||||
val VECTOR_DOWN = Vector(0.0, -1.0, 0.0)
|
@JvmField val VECTOR_DOWN = Vector(0.0, -1.0, 0.0)
|
||||||
val VECTOR_RIGHT = Vector(0.0, 0.0, 1.0)
|
@JvmField val VECTOR_RIGHT = Vector(0.0, 0.0, 1.0)
|
||||||
val VECTOR_LEFT = Vector(0.0, 0.0, -1.0)
|
@JvmField val VECTOR_LEFT = Vector(0.0, 0.0, -1.0)
|
||||||
|
|
||||||
fun Vector.asAngle(): Angle {
|
fun Vector.asAngle(): Angle {
|
||||||
val norm = normalize()
|
val norm = normalize()
|
||||||
|
return Angle(asin(norm.y), atan2(norm.x, norm.z))
|
||||||
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_RIGHT)))
|
|
||||||
}
|
|
||||||
|
|
||||||
return Angle(acos(norm.dot(VECTOR_UP)) - Angle.PI_HALF, acos(Vector(norm.x, 0.0, norm.z).normalize().dot(VECTOR_RIGHT)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Vector.asMutableAngle(): MutableAngle {
|
||||||
|
val norm = normalize()
|
||||||
|
return MutableAngle(asin(norm.y), atan2(norm.x, norm.z))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Vector3f.asAngle(): Angle {
|
||||||
|
val len = length()
|
||||||
|
val norm = Vector(x() / len, y() / len, z() / len)
|
||||||
|
return Angle(asin(norm.y), atan2(norm.x, norm.z))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Vector3f.asMutableAngle(): MutableAngle {
|
||||||
|
val len = length()
|
||||||
|
val norm = Vector(x() / len, y() / len, z() / len)
|
||||||
|
return MutableAngle(asin(norm.y), atan2(norm.x, norm.z))
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun Vector3f.unaryMinus(): Vector3f {
|
||||||
|
setX(-x())
|
||||||
|
setY(-y())
|
||||||
|
setZ(-z())
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Vector3f.length() = sqrt(x().toDouble() * x() + y().toDouble() * y() + z().toDouble() * z())
|
||||||
|
|
||||||
|
operator fun Vector3f.times(v: Float): Vector3f {
|
||||||
|
setX(x() * v)
|
||||||
|
setY(y() * v)
|
||||||
|
setZ(z() * v)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun Vector3f.div(v: Float): Vector3f {
|
||||||
|
setX(x() / v)
|
||||||
|
setY(y() / v)
|
||||||
|
setZ(z() / v)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun Vector3f.component1() = x()
|
||||||
|
operator fun Vector3f.component2() = y()
|
||||||
|
operator fun Vector3f.component3() = z()
|
||||||
|
|
||||||
operator fun Vector.plus(direction: Vector): Vector = this.add(direction)
|
operator fun Vector.plus(direction: Vector): Vector = this.add(direction)
|
||||||
operator fun Vector.minus(direction: Vector): Vector = this.subtract(direction)
|
operator fun Vector.minus(direction: Vector): Vector = this.subtract(direction)
|
||||||
operator fun Vector.unaryMinus(): Vector = Vector(-x, -y, -z)
|
operator fun Vector.unaryMinus(): Vector = Vector(-x, -y, -z)
|
||||||
@ -44,19 +82,30 @@ fun Vector.up() = asAngle().up() * this.length()
|
|||||||
fun Vector.down() = asAngle().down() * this.length()
|
fun Vector.down() = asAngle().down() * this.length()
|
||||||
|
|
||||||
fun Vector.rotateAroundAxis(axis: Vector, rotation: Double): Vector {
|
fun Vector.rotateAroundAxis(axis: Vector, rotation: Double): Vector {
|
||||||
return this * cos(rotation) + axis.cross(this) * sin(rotation) + axis * axis.dot(this) * (1 - cos(rotation))
|
val cross = axis.cross(this)
|
||||||
|
val dot = axis.dot(this)
|
||||||
|
val cos = cos(rotation)
|
||||||
|
val sin = sin(rotation)
|
||||||
|
//return this * cos(rotation) + axis.cross(this) * sin(rotation) + axis * axis.dot(this) * (1 - cos(rotation))
|
||||||
|
|
||||||
|
return Vector(
|
||||||
|
this.x * cos + cross.x * sin + axis.x * dot * (1.0 - cos),
|
||||||
|
this.y * cos + cross.y * sin + axis.y * dot * (1.0 - cos),
|
||||||
|
this.z * cos + cross.z * sin + axis.z * dot * (1.0 - cos),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Vector.rotate(angle: Angle): Vector {
|
fun Vector.rotate(angle: IAngle): Vector {
|
||||||
val rotatedYaw = this.rotateAroundAxis(VECTOR_UP, angle.yaw)
|
val asMatrix = asMatrix()
|
||||||
return rotatedYaw.rotateAroundAxis(rotatedYaw.asAngle().left(), angle.pitch)
|
angle.rotationXYZ().multiply(asMatrix, inverse = true)
|
||||||
|
return Vector(asMatrix[0, 0], asMatrix[1, 0], asMatrix[2, 0])
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Vector.asVector3f(): Vector3f {
|
fun Vector.asVector3f(): Vector3f {
|
||||||
return Vector3f(x.toFloat(), y.toFloat(), z.toFloat())
|
return Vector3f(x.toFloat(), y.toFloat(), z.toFloat())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Quaternion(vec: Vector, rotation: Float, isDegrees: Boolean): Quaternion {
|
fun Quaternion(vec: Vector, rotation: Float, isDegrees: Boolean = false): Quaternion {
|
||||||
return Quaternion(vec.asVector3f(), rotation, isDegrees)
|
return Quaternion(vec.asVector3f(), rotation, isDegrees)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,55 +126,138 @@ fun Vector.rotate(q: Quaternion): Vector {
|
|||||||
return Vector(quaternion.i().toDouble(), quaternion.j().toDouble(), quaternion.k().toDouble())
|
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 Vector.rotateAroundThis(rotation: Float, isDegrees: Boolean = false): Quaternion {
|
||||||
fun forward(): Vector {
|
return Quaternion(this, rotation, isDegrees)
|
||||||
val yaw = yaw
|
}
|
||||||
val x = cos(yaw) * cos(pitch)
|
|
||||||
val y = -sin(pitch)
|
|
||||||
val z = sin(yaw) * cos(pitch)
|
|
||||||
|
|
||||||
return Vector(x, y, z)
|
fun Vector.asMatrix(): MutableMatrix {
|
||||||
|
return MutableMatrix(3, 1).also {
|
||||||
|
it[0, 0] = x
|
||||||
|
it[1, 0] = y
|
||||||
|
it[2, 0] = z
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Vector.asMatrix4(): MutableMatrix {
|
||||||
|
return MutableMatrix(4, 1).also {
|
||||||
|
it[0, 0] = x
|
||||||
|
it[1, 0] = y
|
||||||
|
it[2, 0] = z
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Direction.asAngle(): Angle {
|
||||||
|
return when (this) {
|
||||||
|
Direction.DOWN -> Angle.DOWN
|
||||||
|
Direction.UP -> Angle.UP
|
||||||
|
Direction.NORTH -> Angle.NORTH
|
||||||
|
Direction.SOUTH -> Angle.SOUTH
|
||||||
|
Direction.WEST -> Angle.WEST
|
||||||
|
Direction.EAST -> Angle.EAST
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IAngle {
|
||||||
|
val pitch: Double
|
||||||
|
val yaw: Double
|
||||||
|
val roll: Double
|
||||||
|
|
||||||
|
fun forward() = VECTOR_FORWARD.rotate(this)
|
||||||
|
fun left() = VECTOR_LEFT.rotate(this)
|
||||||
|
fun right() = VECTOR_RIGHT.rotate(this)
|
||||||
|
fun up() = VECTOR_UP.rotate(this)
|
||||||
|
fun down() = VECTOR_DOWN.rotate(this)
|
||||||
|
|
||||||
|
fun rotationX(): MutableMatrix {
|
||||||
|
if (roll == 0.0) {
|
||||||
|
return MutableMatrix(3, 3).also { it.identityFast() }
|
||||||
|
}
|
||||||
|
|
||||||
|
return MutableMatrix(3, 3).also {
|
||||||
|
val s = sin(roll)
|
||||||
|
val c = cos(roll)
|
||||||
|
|
||||||
|
it[0, 0] = 1.0
|
||||||
|
it[1, 1] = c
|
||||||
|
it[1, 2] = -s
|
||||||
|
it[2, 1] = s
|
||||||
|
it[2, 2] = c
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun left(): Vector {
|
fun rotationZ(): MutableMatrix {
|
||||||
return -right()
|
if (pitch == 0.0) {
|
||||||
|
return MutableMatrix(3, 3).also { it.identityFast() }
|
||||||
|
}
|
||||||
|
|
||||||
|
return MutableMatrix(3, 3).also {
|
||||||
|
val s = sin(pitch)
|
||||||
|
val c = cos(pitch)
|
||||||
|
|
||||||
|
it[0, 0] = c
|
||||||
|
it[0, 1] = -s
|
||||||
|
it[1, 0] = s
|
||||||
|
it[1, 1] = c
|
||||||
|
it[2, 2] = 1.0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun right(): Vector {
|
fun rotationY(): MutableMatrix {
|
||||||
val yaw = yaw + PI_HALF
|
if (yaw == 0.0) {
|
||||||
val pitch = 0.0
|
return MutableMatrix(3, 3).also { it.identityFast() }
|
||||||
val x = cos(yaw) * cos(pitch)
|
}
|
||||||
val y = -sin(pitch)
|
|
||||||
val z = sin(yaw) * cos(pitch)
|
|
||||||
|
|
||||||
return Vector(x, y, z)
|
return MutableMatrix(3, 3).also {
|
||||||
|
val s = sin(yaw)
|
||||||
|
val c = cos(yaw)
|
||||||
|
|
||||||
|
it[0, 0] = c
|
||||||
|
it[0, 2] = s
|
||||||
|
|
||||||
|
it[2, 0] = -s
|
||||||
|
it[2, 2] = c
|
||||||
|
|
||||||
|
it[1, 1] = 1.0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun up(): Vector {
|
fun rotationXYZ(): MutableMatrix {
|
||||||
val yaw = yaw - PI_HALF
|
if (pitch == 0.0 && yaw == 0.0 && roll == 0.0)
|
||||||
val pitch = pitch - PI_HALF
|
return MutableMatrix(3, 3).also { it.identity() }
|
||||||
val x = cos(yaw) * cos(pitch)
|
|
||||||
val y = -sin(pitch)
|
|
||||||
val z = sin(yaw) * cos(pitch)
|
|
||||||
|
|
||||||
return Vector(x, y, z)
|
return rotationY().multiply(rotationZ()).multiply(rotationX())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun down(): Vector {
|
fun rotationXYZW(): MutableMatrix {
|
||||||
val yaw = yaw - PI_HALF
|
if (pitch == 0.0 && yaw == 0.0 && roll == 0.0)
|
||||||
val pitch = pitch + PI_HALF
|
return MutableMatrix(4, 4).also { it.identity() }
|
||||||
val x = cos(yaw) * cos(pitch)
|
|
||||||
val y = -sin(pitch)
|
|
||||||
val z = sin(yaw) * cos(pitch)
|
|
||||||
|
|
||||||
return Vector(x, y, z)
|
return rotationXYZ().resize(4, 4).also { it[3, 3] = 1.0 }
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data class Angle(override val pitch: Double = 0.0, override val yaw: Double = 0.0, override val roll: Double = 0.0) : IAngle {
|
||||||
companion object {
|
companion object {
|
||||||
const val PI_HALF = Math.PI / 2.0
|
const val PI_HALF = Math.PI / 2.0
|
||||||
|
|
||||||
fun degrees(pitch: Double, yaw: Double, roll: Double): Angle {
|
fun deg(pitch: Double, yaw: Double, roll: Double): Angle {
|
||||||
return Angle(Math.toDegrees(pitch), Math.toDegrees(yaw), Math.toDegrees(roll))
|
return Angle(Math.toDegrees(pitch), Math.toDegrees(yaw), Math.toDegrees(roll))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JvmField val ZERO = Angle()
|
||||||
|
@JvmField val UP = Angle(pitch = PI / 2)
|
||||||
|
@JvmField val DOWN = Angle(pitch = -PI / 2)
|
||||||
|
@JvmField val NORTH = Angle()
|
||||||
|
@JvmField val SOUTH = Angle(yaw = PI)
|
||||||
|
@JvmField val WEST = Angle(yaw = PI / 2)
|
||||||
|
@JvmField val EAST = Angle(yaw = -PI / 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data class MutableAngle(override var pitch: Double = 0.0, override var yaw: Double = 0.0, override var roll: Double = 0.0) : IAngle {
|
||||||
|
companion object {
|
||||||
|
fun deg(pitch: Double, yaw: Double, roll: Double): MutableAngle {
|
||||||
|
return MutableAngle(Math.toDegrees(pitch), Math.toDegrees(yaw), Math.toDegrees(roll))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@ operator fun Vec3i.minus(direction: Vec3i): Vec3i = this.subtract(direction)
|
|||||||
operator fun Vec3i.minus(direction: Direction): Vec3i = this.subtract(direction.normal)
|
operator fun Vec3i.minus(direction: Direction): Vec3i = this.subtract(direction.normal)
|
||||||
|
|
||||||
operator fun Vec3i.times(int: Int): Vec3i = this.multiply(int)
|
operator fun Vec3i.times(int: Int): Vec3i = this.multiply(int)
|
||||||
|
operator fun Vec3i.times(double: Double): Vector = Vector(x * double, y * double, z * double)
|
||||||
|
|
||||||
fun BlockPos.asVector(): Vector {
|
fun BlockPos.asVector(): Vector {
|
||||||
return Vector(x + 0.5, y + 0.5, z + 0.5)
|
return Vector(x + 0.5, y + 0.5, z + 0.5)
|
||||||
|
276
src/main/kotlin/ru/dbotthepony/mc/otm/core/MutableMatrix.kt
Normal file
276
src/main/kotlin/ru/dbotthepony/mc/otm/core/MutableMatrix.kt
Normal file
@ -0,0 +1,276 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.core
|
||||||
|
|
||||||
|
import com.mojang.math.Matrix3f
|
||||||
|
import com.mojang.math.Matrix4f
|
||||||
|
import com.mojang.math.Vector3f
|
||||||
|
import com.mojang.math.Vector4f
|
||||||
|
import org.jetbrains.annotations.Contract
|
||||||
|
import java.nio.FloatBuffer
|
||||||
|
|
||||||
|
fun Matrix3f.asMutableMatrix(): MutableMatrix = MutableMatrix(this)
|
||||||
|
fun Matrix4f.asMutableMatrix(): MutableMatrix = MutableMatrix(this)
|
||||||
|
|
||||||
|
fun Matrix4f.rotate(angle: IAngle): Matrix4f {
|
||||||
|
multiply(angle.rotationXYZW().toMatrix4f())
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Matrix4f.translate(vector: Vector) {
|
||||||
|
translate(-vector.asVector3f())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Matrix4f.rotateAroundPoint(point: Vector, axis: Vector, rotation: Float, isDegrees: Boolean = false) {
|
||||||
|
val p = point.asVector3f()
|
||||||
|
translate(-p)
|
||||||
|
multiply(axis.rotateAroundThis(rotation, isDegrees))
|
||||||
|
translate(-p)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Matrix4f.rotateAroundPoint(point: Vector, axis: Vector3f, rotation: Float, isDegrees: Boolean = false) {
|
||||||
|
val p = point.asVector3f()
|
||||||
|
translate(-p)
|
||||||
|
multiply(if (isDegrees) axis.rotationDegrees(rotation) else axis.rotation(rotation))
|
||||||
|
translate(-p)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Matrix4f.rotateAroundPoint(point: Vector, rotation: IAngle) {
|
||||||
|
val p = point.asVector3f()
|
||||||
|
translate(-p)
|
||||||
|
multiply(rotation.rotationXYZW().toMatrix4f())
|
||||||
|
translate(-p)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Matrix4f.rotateAroundPoint(point: Vector3f, axis: Vector, rotation: Float, isDegrees: Boolean = false) {
|
||||||
|
translate(-point)
|
||||||
|
multiply(axis.rotateAroundThis(rotation, isDegrees))
|
||||||
|
translate(-point)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Matrix4f.rotateAroundPoint(point: Vector3f, rotation: IAngle) {
|
||||||
|
translate(-point)
|
||||||
|
multiply(rotation.rotationXYZW().toMatrix4f())
|
||||||
|
translate(-point)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Matrix4f.rotateAroundPoint(point: Vector3f, axis: Vector3f, rotation: Float, isDegrees: Boolean = false) {
|
||||||
|
translate(-point)
|
||||||
|
multiply(if (isDegrees) axis.rotationDegrees(rotation) else axis.rotation(rotation))
|
||||||
|
translate(-point)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val floatBuff3 = FloatBuffer.allocate(3 * 3)
|
||||||
|
private val floatBuff4 = FloatBuffer.allocate(4 * 4)
|
||||||
|
|
||||||
|
fun Matrix4f.getTranslation(): Vector3f {
|
||||||
|
store(floatBuff4)
|
||||||
|
|
||||||
|
return Vector3f(floatBuff4[0 + 3 * 4], floatBuff4[1 + 3 * 4], floatBuff4[2 + 3 * 4])
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Matrix4f.getTranslation4(): Vector4f {
|
||||||
|
store(floatBuff4)
|
||||||
|
|
||||||
|
return Vector4f(floatBuff4[0 + 3 * 4], floatBuff4[1 + 3 * 4], floatBuff4[2 + 3 * 4], floatBuff4[3 + 3 * 4])
|
||||||
|
}
|
||||||
|
|
||||||
|
class MutableMatrix(val rows: Int, val columns: Int = 1) {
|
||||||
|
private val buffer = Array(columns * rows) {0.0}
|
||||||
|
|
||||||
|
constructor(matrix3f: Matrix3f) : this(3, 3) {
|
||||||
|
matrix3f.store(floatBuff3)
|
||||||
|
load(floatBuff3)
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(matrix4f: Matrix4f) : this(4, 4) {
|
||||||
|
matrix4f.store(floatBuff4)
|
||||||
|
load(floatBuff4)
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(other: MutableMatrix) : this(other.rows, other.columns) {
|
||||||
|
for (i in 0 .. buffer.size) {
|
||||||
|
buffer[i] = other.buffer[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun identity(): MutableMatrix {
|
||||||
|
check(columns == rows) { "Matrix is not cubic ($rows by $columns)" }
|
||||||
|
|
||||||
|
for (column in 0 until columns) {
|
||||||
|
for (row in 0 until rows) {
|
||||||
|
buffer[row + column * rows] = if (column == row) 1.0 else 0.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun identityFast(): MutableMatrix {
|
||||||
|
check(columns == rows) { "Matrix is not cubic ($rows by $columns)" }
|
||||||
|
|
||||||
|
for (i in 0 until rows) {
|
||||||
|
buffer[i + i * columns] = 1.0
|
||||||
|
}
|
||||||
|
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toMatrix3f(): Matrix3f {
|
||||||
|
check(rows == columns && rows == 3) { "This matrix has wrong dimensions: $rows by $columns" }
|
||||||
|
store(floatBuff3)
|
||||||
|
return Matrix3f().also { it.load(floatBuff3) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toMatrix4f(): Matrix4f {
|
||||||
|
check(rows == columns && rows == 4) { "This matrix has wrong dimensions: $rows by $columns" }
|
||||||
|
store(floatBuff4)
|
||||||
|
return Matrix4f().also { it.load(floatBuff4) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun store(buff: FloatBuffer) {
|
||||||
|
for (row in 0 until rows) {
|
||||||
|
for (column in 0 until columns) {
|
||||||
|
buff.put(row + column * columns, buffer[row + column * columns].toFloat())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun store(matrix: Matrix4f) {
|
||||||
|
check(rows == columns && rows == 4) { "This matrix has wrong dimensions: $rows by $columns" }
|
||||||
|
store(floatBuff4)
|
||||||
|
matrix.load(floatBuff4)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun store(matrix: Matrix3f) {
|
||||||
|
check(rows == columns && rows == 3) { "This matrix has wrong dimensions: $rows by $columns" }
|
||||||
|
store(floatBuff3)
|
||||||
|
matrix.load(floatBuff3)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun load(buff: FloatBuffer) {
|
||||||
|
for (row in 0 until rows) {
|
||||||
|
for (column in 0 until columns) {
|
||||||
|
buffer[row + column * columns] = buff[row + column * columns].toDouble()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun load(matrix: Matrix4f) {
|
||||||
|
check(rows == columns && rows == 4) { "This matrix has wrong dimensions: $rows by $columns" }
|
||||||
|
matrix.store(floatBuff4)
|
||||||
|
load(floatBuff4)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun load(matrix: Matrix3f) {
|
||||||
|
check(rows == columns && rows == 3) { "This matrix has wrong dimensions: $rows by $columns" }
|
||||||
|
matrix.store(floatBuff3)
|
||||||
|
load(floatBuff3)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun resize(rows: Int, columns: Int): MutableMatrix {
|
||||||
|
return MutableMatrix(rows, columns).also {
|
||||||
|
for (row in 0 until this.rows.coerceAtMost(rows)) {
|
||||||
|
for (column in 0 until this.columns.coerceAtMost(columns)) {
|
||||||
|
it.buffer[row + column * columns] = buffer[row + column * this.columns]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Contract(pure = true)
|
||||||
|
operator fun get(row: Int, column: Int): Double {
|
||||||
|
require(row >= 0) { "Row out of bounds: $row" }
|
||||||
|
require(row < rows) { "Row out of bounds: $row" }
|
||||||
|
require(column >= 0) { "Column out of bounds: $row" }
|
||||||
|
require(column < columns) { "Column out of bounds: $row" }
|
||||||
|
return buffer[row + column * rows]
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun set(row: Int, column: Int, value: Double) {
|
||||||
|
require(row >= 0) { "Row out of bounds: $row" }
|
||||||
|
require(row < rows) { "Row out of bounds: $row" }
|
||||||
|
require(column >= 0) { "Column out of bounds: $row" }
|
||||||
|
require(column < columns) { "Column out of bounds: $row" }
|
||||||
|
buffer[row + column * rows] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this = this * other
|
||||||
|
* при inverse = true
|
||||||
|
* other = this * other
|
||||||
|
*
|
||||||
|
* без создания новой матрицы
|
||||||
|
*/
|
||||||
|
fun multiply(other: MutableMatrix, inverse: Boolean = false): MutableMatrix {
|
||||||
|
check(columns == other.rows) { "Matrixes are not compatible for multiplication (this: $rows by $columns, other: ${other.rows} by ${other.columns})" }
|
||||||
|
val resultSize = rows * other.columns
|
||||||
|
check(!inverse && buffer.size == resultSize || inverse && other.buffer.size == resultSize) { "Matrixes are not compatible for ${if (inverse) "direct" else "inverse"} multiplication in place (this: $rows by $columns, other: ${other.rows} by ${other.columns})" }
|
||||||
|
|
||||||
|
val buff = Array(resultSize) { 0.0 }
|
||||||
|
|
||||||
|
for (row in 0 until rows) {
|
||||||
|
for (column in 0 until other.columns) {
|
||||||
|
var sum = 0.0
|
||||||
|
|
||||||
|
for (elem in 0 until columns) {
|
||||||
|
sum += this[row, elem] * other[elem, column]
|
||||||
|
}
|
||||||
|
|
||||||
|
buff[row + column * columns] = sum
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inverse) {
|
||||||
|
for (i in buff.indices) {
|
||||||
|
other.buffer[i] = buff[i]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (i in buff.indices) {
|
||||||
|
buffer[i] = buff[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return if (inverse) other else this
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* new = this * other
|
||||||
|
*
|
||||||
|
* с созданием новой матрицы
|
||||||
|
*/
|
||||||
|
operator fun times(other: MutableMatrix): MutableMatrix {
|
||||||
|
check(columns == other.rows) { "Matrixes are not compatible for multiplication (this: $rows by $columns, other: ${other.rows} by ${other.columns})" }
|
||||||
|
val new = MutableMatrix(rows, other.columns)
|
||||||
|
|
||||||
|
for (row in 0 until rows) {
|
||||||
|
for (column in 0 until other.columns) {
|
||||||
|
var sum = 0.0
|
||||||
|
|
||||||
|
for (elem in 0 until columns) {
|
||||||
|
sum += this[row, elem] * other[elem, column]
|
||||||
|
}
|
||||||
|
|
||||||
|
new[row, column] = sum
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new
|
||||||
|
}
|
||||||
|
|
||||||
|
var translation: Vector
|
||||||
|
get() {
|
||||||
|
check(columns == rows && rows == 4) { "Matrix is expected to be 4x4 (this one is $rows by $columns)" }
|
||||||
|
return Vector(this[0, 3], this[1, 3], this[2, 3])
|
||||||
|
}
|
||||||
|
|
||||||
|
set(value) {
|
||||||
|
check(columns == rows && rows == 4) { "Matrix is expected to be 4x4 (this one is $rows by $columns)" }
|
||||||
|
this[0, 0] = 1.0
|
||||||
|
this[1, 1] = 1.0
|
||||||
|
this[2, 2] = 1.0
|
||||||
|
this[3, 3] = 1.0
|
||||||
|
|
||||||
|
this[0, 3] = value.x
|
||||||
|
this[1, 3] = value.y
|
||||||
|
this[2, 3] = value.z
|
||||||
|
}
|
||||||
|
}
|
@ -41,6 +41,9 @@
|
|||||||
"otm.gui.redstone.low.description": "Machine work if no redstone signal is present",
|
"otm.gui.redstone.low.description": "Machine work if no redstone signal is present",
|
||||||
"otm.gui.redstone.high.description": "Machine work only if any redstone signal is present",
|
"otm.gui.redstone.high.description": "Machine work only if any redstone signal is present",
|
||||||
|
|
||||||
|
"otm.3d2d.gravitation_stabilizer.mass": "Singularity mass: %s",
|
||||||
|
"otm.3d2d.gravitation_stabilizer.strength": "Gravitation strength: %s",
|
||||||
|
|
||||||
"otm.death_reason": "Decommissioned!",
|
"otm.death_reason": "Decommissioned!",
|
||||||
|
|
||||||
"otm.item.power.infinite.storage": "Stored energy: Infinity / Infinity",
|
"otm.item.power.infinite.storage": "Stored energy: Infinity / Infinity",
|
||||||
|
Loading…
Reference in New Issue
Block a user