io.github.kosmx.bendylib.impl.BendableCuboid Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of bendy-lib Show documentation
Show all versions of bendy-lib Show documentation
Minecraft FabricMC model render library
The newest version!
package io.github.kosmx.bendylib.impl;
import io.github.kosmx.bendylib.ICuboidBuilder;
import io.github.kosmx.bendylib.impl.accessors.DirectionMutator;
import net.minecraft.class_1159;
import net.minecraft.class_1160;
import net.minecraft.class_1162;
import net.minecraft.class_2350;
import net.minecraft.class_4587;
import net.minecraft.class_4588;
import net.minecraft.class_630;
import net.minecraft.util.math.*;
import java.util.*;
import java.util.function.Consumer;
/**
* Bendable cuboid literally...
* If you don't know the math behind it
* (Vectors, matrices, quaternions)
* don't try to edit.
*
* Use {@link BendableCuboid#setRotationDeg(float, float)} to bend the cube
*/
public class BendableCuboid implements ICuboid, IBendable, IterableRePos {
protected final Quad[] sides;
protected final RememberingPos[] positions;
//protected final Matrix4f matrix; - Shouldn't use... Change the moveVec instead of this.
protected class_1159 lastPosMatrix;
//protected final RepositionableVertex.Pos3f[] positions = new RepositionableVertex.Pos3f[8];
//protected final Vec3f[] origins = new Vec3f[4];
public final float minX;
public final float minY;
public final float minZ;
public final float maxX;
public final float maxY;
public final float maxZ;
//protected final float size;
//to shift the matrix to the center axis
protected final float fixX;
protected final float fixY;
protected final float fixZ;
protected final class_2350 direction;
protected final Plane basePlane;
protected final Plane otherPlane;
protected final float fullSize;
private float bend, bendAxis;
//Use Builder
protected BendableCuboid(Quad[] sides, RememberingPos[] positions, float minX, float minY, float minZ, float maxX, float maxY, float maxZ, float fixX, float fixY, float fixZ, class_2350 direction, Plane basePlane, Plane otherPlane, float fullSize) {
this.sides = sides;
this.positions = positions;
this.minX = minX;
this.minY = minY;
this.minZ = minZ;
this.maxX = maxX;
this.maxY = maxY;
this.maxZ = maxZ;
this.fixX = fixX;
this.fixY = fixY;
this.fixZ = fixZ;
//this.size = size;
this.direction = direction;
this.basePlane = basePlane;
this.otherPlane = otherPlane;
this.fullSize = fullSize;
this.applyBend(0, 0);//Init values to render
}
public class_1159 applyBend(float bendAxis, float bendValue){
this.bend = bendValue; this.bendAxis = bendAxis;
return this.applyBend(bendAxis, bendValue, this);
}
@Override
public class_2350 getBendDirection() {
return this.direction;
}
@Override
public float getBendX() {
return fixX;
}
@Override
public float getBendY() {
return fixY;
}
@Override
public float getBendZ() {
return fixZ;
}
@Override
public Plane getBasePlane() {
return basePlane;
}
@Override
public Plane getOtherSidePlane() {
return otherPlane;
}
@Override
public float bendHeight() {
return fullSize;
}
@Override
public void iteratePositions(Consumer consumer){
for(IPosWithOrigin pos:positions){
consumer.accept(pos);
}
}
/**
* a.k.a BendableCuboidFactory
*/
public static class Builder implements ICuboidBuilder {
/**
* Size parameters
*/
public class_2350 direction; //now, way better
public Builder setDirection(class_2350 d){
this.direction = d;
return this;
}
public BendableCuboid build(Data data){
ArrayList planes = new ArrayList<>();
HashMap positions = new HashMap<>();
float minX = data.x, minY = data.y, minZ = data.z, maxX = data.x + data.sizeX, maxY = data.y + data.sizeY, maxZ = data.z + data.sizeZ;
float pminX = data.x - data.extraX, pminY = data.y - data.extraY, pminZ = data.z - data.extraZ, pmaxX = maxX + data.extraX, pmaxY = maxY + data.extraY, pmaxZ = maxZ + data.extraZ;
if(data.mirror){
float tmp = pminX;
pminX = pmaxX;
pmaxX = tmp;
}
//this is copy from MC's cuboid constructor
class_1160 vertex1 = new class_1160(pminX, pminY, pminZ);
class_1160 vertex2 = new class_1160(pmaxX, pminY, pminZ);
class_1160 vertex3 = new class_1160(pmaxX, pmaxY, pminZ);
class_1160 vertex4 = new class_1160(pminX, pmaxY, pminZ);
class_1160 vertex5 = new class_1160(pminX, pminY, pmaxZ);
class_1160 vertex6 = new class_1160(pmaxX, pminY, pmaxZ);
class_1160 vertex7 = new class_1160(pmaxX, pmaxY, pmaxZ);
class_1160 vertex8 = new class_1160(pminX, pmaxY, pmaxZ);
int j = data.u;
int k = (int) (data.u + data.sizeZ);
int l = (int) (data.u + data.sizeZ + data.sizeX);
int m = (int) (data.u + data.sizeZ + data.sizeX + data.sizeX);
int n = (int) (data.u + data.sizeZ + data.sizeX + data.sizeZ);
int o = (int) (data.u + data.sizeZ + data.sizeX + data.sizeZ + data.sizeX);
int p = data.v;
int q = (int) (data.v + data.sizeZ);
int r = (int) (data.v + data.sizeZ + data.sizeY);
createAndAddQuads(planes, positions, new class_1160[]{vertex6, vertex5, vertex2}, k, p, l, q, data.textureWidth, data.textureHeight, data.mirror, data);
createAndAddQuads(planes, positions, new class_1160[]{vertex3, vertex4, vertex7}, l, q, m, p, data.textureWidth, data.textureHeight, data.mirror, data);
createAndAddQuads(planes, positions, new class_1160[]{vertex1, vertex5, vertex4}, j, q, k, r, data.textureWidth, data.textureHeight, data.mirror, data);
createAndAddQuads(planes, positions, new class_1160[]{vertex2, vertex1, vertex3}, k, q, l, r, data.textureWidth, data.textureHeight, data.mirror, data);
createAndAddQuads(planes, positions, new class_1160[]{vertex6, vertex2, vertex7}, l, q, n, r, data.textureWidth, data.textureHeight, data.mirror, data);
createAndAddQuads(planes, positions, new class_1160[]{vertex5, vertex6, vertex8}, n, q, o, r, data.textureWidth, data.textureHeight, data.mirror, data);
Plane aPlane = new Plane(direction.method_23955(), vertex7);
Plane bPlane = new Plane(direction.method_23955(), vertex1);
boolean bl = direction == class_2350.field_11036 || direction == class_2350.field_11035 || direction == class_2350.field_11034;
float fullSize = - direction.method_23955().method_4950(vertex1) + direction.method_23955().method_4950(vertex7);
float bendX = ((float) data.sizeX + data.x + data.x)/2;
float bendY = ((float) data.sizeY + data.y + data.y)/2;
float bendZ = ((float) data.sizeZ + data.z + data.z)/2;
return new BendableCuboid(planes.toArray(new Quad[0]), positions.values().toArray(new RememberingPos[0]), minX, minY, minZ, maxX, maxY, maxZ, bendX, bendY, bendZ, direction, bl ? aPlane : bPlane, bl ? bPlane : aPlane, fullSize);
}
//edge[2] can be calculated from edge 0, 1, 3...
private void createAndAddQuads(Collection quads, HashMap positions, class_1160[] edges, int u1, int v1, int u2, int v2, float squishU, float squishV, boolean flip, Data data){
int du = u2 < u1 ? 1 : -1;
int dv = v1 < v2 ? 1 : -1;
for(int localU = u2; localU != u1; localU += du){
for(int localV = v1; localV != v2; localV += dv){
int localU2 = localU + du;
int localV2 = localV + dv;
RememberingPos rp0 = getOrCreate(positions, transformVector(edges[0].method_23850(), edges[1].method_23850(), edges[2].method_23850(), u2, v1, u1, v2, localU2, localV));
RememberingPos rp1 = getOrCreate(positions, transformVector(edges[0].method_23850(), edges[1].method_23850(), edges[2].method_23850(), u2, v1, u1, v2, localU2, localV2));
RememberingPos rp2 = getOrCreate(positions, transformVector(edges[0].method_23850(), edges[1].method_23850(), edges[2].method_23850(), u2, v1, u1, v2, localU, localV2));
RememberingPos rp3 = getOrCreate(positions, transformVector(edges[0].method_23850(), edges[1].method_23850(), edges[2].method_23850(), u2, v1, u1, v2, localU, localV));
quads.add(new Quad(new RememberingPos[]{rp3, rp0, rp1, rp2}, localU2, localV, localU, localV2, data.textureWidth, data.textureHeight, data.mirror));
}
}
}
class_1160 transformVector(class_1160 pos, class_1160 vectorU, class_1160 vectorV, int u1, int v1, int u2, int v2, int u, int v){
vectorU.method_4944(pos);
vectorU.method_4942(((float)u - u1)/(u2-u1));
vectorV.method_4944(pos);
vectorV.method_4942(((float)v - v1)/(v2-v1));
pos.method_23846(vectorU);
pos.method_23846(vectorV);
return pos;
}
RememberingPos getOrCreate(HashMap positions, class_1160 pos){
if(!positions.containsKey(pos)){
positions.put(pos, new RememberingPos(pos));
}
return positions.get(pos);
}
}
/**
* Use {@link IBendable#applyBend(float, float, IterableRePos)} instead
* @param axisf bend around this axis
* @param value bend value in radians
* @return Used Matrix4f
*/
@Deprecated
public class_1159 setRotationRad(float axisf, float value){
return this.applyBend(axisf, value);
}
/**
* Set the bend's rotation
* @param axis rotation axis in deg
* @param val rotation's value in deg
* @return Rotated Matrix4f
*/
public class_1159 setRotationDeg(float axis, float val){
return this.setRotationRad(axis * 0.0174533f, val * 0.0174533f);
}
@Override
public void render(class_4587.class_4665 matrices, class_4588 vertexConsumer, float red, float green, float blue, float alpha, int light, int overlay) {
for(Quad quad:sides){
quad.render(matrices, vertexConsumer, light, overlay, red, green, blue, alpha);
}
}
@Override
public void copyState(ICuboid other) {
if(other instanceof BendableCuboid b){
this.applyBend(b.bendAxis, b.bend); //This works only in J16 or higher
}
}
public class_1159 getLastPosMatrix(){
return this.lastPosMatrix.method_22673();
}
/*
* A replica of {@link ModelPart.Quad}
* with IVertex and render()
*/
public static class Quad{
public final IVertex[] vertices;
final float u1, u2, v1, v2, su, sv;
public Quad(RememberingPos[] vertices, float u1, float v1, float u2, float v2, float squishU, float squishV, boolean flip){
this.u1 = u1; this.u2 = u2; this.v1 = v1; this.v2 = v2; su = squishU; sv = squishV;
float f = 0/squishU;
float g = 0/squishV;
this.vertices = new IVertex[4];
this.vertices[0] = new RepositionableVertex(u2 / squishU - f, v1 / squishV + g, vertices[0]);
this.vertices[1] = new RepositionableVertex(u1 / squishU + f, v1 / squishV + g, vertices[1]);
this.vertices[2] = new RepositionableVertex(u1 / squishU + f, v2 / squishV - g, vertices[2]);
this.vertices[3] = new RepositionableVertex(u2 / squishU - f, v2 / squishV - g, vertices[3]);
if(flip){
int i = vertices.length;
for(int j = 0; j < i / 2; ++j) {
IVertex vertex = this.vertices[j];
this.vertices[j] = this.vertices[i - 1 - j];
this.vertices[i - 1 - j] = vertex;
}
}
}
public void render(class_4587.class_4665 matrices, class_4588 vertexConsumer, int light, int overlay, float red, float green, float blue, float alpha){
class_1160 direction = this.getDirection();
direction.method_23215(matrices.method_23762());
for (int i = 0; i != 4; ++i){
IVertex vertex = this.vertices[i];
class_1160 vertexPos = vertex.getPos();
class_1162 pos = new class_1162(vertexPos.method_4943()/16f, vertexPos.method_4945()/16f, vertexPos.method_4947()/16f, 1);
pos.method_22674(matrices.method_23761());
vertexConsumer.method_23919(pos.method_4953(), pos.method_4956(), pos.method_4957(), red, green, blue, alpha, vertex.getU(), vertex.getV(), overlay, light, direction.method_4943(), direction.method_4945(), direction.method_4947());
}
}
/**
* calculate the normal vector from the vertices' coordinates with cross product
* @return the normal vector (direction)
*/
private class_1160 getDirection(){
class_1160 buf = vertices[3].getPos().method_23850();
buf.method_4942(-1);
class_1160 vecB = vertices[1].getPos().method_23850();
vecB.method_23846(buf);
buf = vertices[2].getPos().method_23850();
buf.method_4942(-1);
class_1160 vecA = vertices[0].getPos().method_23850();
vecA.method_23846(buf);
vecA.method_4951(vecB);
//Return the cross product, if it's zero then return anything non-zero to not cause crash...
return vecA.method_4952() ? vecA : class_2350.field_11043.method_23955();
}
@SuppressWarnings({"ConstantConditions"})
private class_630.class_593 toModelPart_Quad(){
class_630.class_593 quad = new class_630.class_593(new class_630.class_618[]{
vertices[0].toMojVertex(),
vertices[1].toMojVertex(),
vertices[2].toMojVertex(),
vertices[3].toMojVertex()
}, u1, v1, u2, v2, su, sv, false, class_2350.field_11036);
((DirectionMutator)quad).setDirection(this.getDirection());
return quad;
}
}
@Override
public boolean disableAfterDraw() {
return false;
}
@Override
public List getQuads() {
List sides = new ArrayList<>();
for(Quad quad : this.sides){
sides.add(quad.toModelPart_Quad());
}
return sides;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy