1 package com.irtimaled.bbor.client.models;
3 import com.irtimaled.bbor.client.ClientRenderer;
4 import com.irtimaled.bbor.client.RenderCulling;
5 import com.irtimaled.bbor.client.renderers.AbstractRenderer;
6 import com.irtimaled.bbor.client.renderers.LineRenderer;
7 import com.irtimaled.bbor.common.BoundingBoxType;
8 import com.irtimaled.bbor.common.MathHelper;
9 import com.irtimaled.bbor.common.TypeHelper;
10 import com.irtimaled.bbor.common.models.AbstractBoundingBox;
12 public class BoundingBoxLine extends AbstractBoundingBox {
13 private static final AbstractRenderer<BoundingBoxLine> RENDERER = ClientRenderer.registerRenderer(BoundingBoxLine.class, () -> new LineRenderer());
15 private final Point minPoint;
16 private final Point maxPoint;
17 private final Double width;
18 private final Point[] corners;
20 protected BoundingBoxLine(Point minPoint, Point maxPoint, double width, BoundingBoxType type, Point... corners) {
22 this.minPoint = minPoint;
23 this.maxPoint = maxPoint;
25 this.corners = corners;
28 public static BoundingBoxLine from(Point minPoint, Point maxPoint, Double width, BoundingBoxType type) {
29 if (width == 0) return new BoundingBoxLine(minPoint, maxPoint, width, type);
31 double halfWidth = width / 2.0d;
33 double dx = maxPoint.getX() - minPoint.getX();
34 double dz = maxPoint.getZ() - minPoint.getZ();
36 double dxm = dx == 0 ? 0 : dx / Math.abs(dx);
37 double dzm = dz == 0 ? 0 : dz / Math.abs(dz);
40 if (dxm == 0 || dzm == 0) {
41 xc = Math.abs(dzm) * halfWidth;
42 zc = Math.abs(dxm) * halfWidth;
44 double h = Math.sqrt(dx * dx + dz * dz);
45 double theta = Math.acos((dz * dz + h * h - dx * dx) / (2 * dz * h));
46 zc = halfWidth * Math.sin(theta);
47 xc = Math.sqrt(halfWidth * halfWidth - zc * zc) * dxm * dzm;
50 return new BoundingBoxLine(minPoint, maxPoint, width, type,
51 new Point(minPoint.getX() + xc, minPoint.getY(), minPoint.getZ() - zc),
52 new Point(minPoint.getX() - xc, minPoint.getY(), minPoint.getZ() + zc),
53 new Point(maxPoint.getX() - xc, maxPoint.getY(), maxPoint.getZ() + zc),
54 new Point(maxPoint.getX() + xc, maxPoint.getY(), maxPoint.getZ() - zc));
58 public int hashCode() {
59 return TypeHelper.combineHashCodes(minPoint.hashCode(), maxPoint.hashCode());
63 public boolean equals(Object obj) {
64 if (this == obj) return true;
65 if (obj == null || getClass() != obj.getClass()) return false;
66 BoundingBoxLine other = (BoundingBoxLine) obj;
67 return minPoint.equals(other.minPoint) && maxPoint.equals(other.maxPoint);
70 public Point getMinPoint() {
74 public Point getMaxPoint() {
78 public double getWidth() {
82 public Point[] getCorners() {
87 public Boolean intersectsBounds(int minX, int minZ, int maxX, int maxZ) {
88 boolean minXWithinBounds = isBetween(minPoint.getX(), minX, maxX);
89 boolean maxXWithinBounds = isBetween(maxPoint.getX(), minX, maxX);
90 boolean minZWithinBounds = isBetween(minPoint.getZ(), minZ, maxZ);
91 boolean maxZWithinBounds = isBetween(maxPoint.getZ(), minZ, maxZ);
93 return (minXWithinBounds && minZWithinBounds) ||
94 (maxXWithinBounds && maxZWithinBounds) ||
95 (minXWithinBounds && maxZWithinBounds) ||
96 (maxXWithinBounds && minZWithinBounds);
100 protected double getDistanceX(double x) {
101 return x - MathHelper.clamp(x, minPoint.getX(), maxPoint.getX());
105 protected double getDistanceY(double y) {
106 return y - MathHelper.clamp(y, minPoint.getY(), maxPoint.getY());
110 protected double getDistanceZ(double z) {
111 return z - MathHelper.clamp(z, minPoint.getZ(), maxPoint.getZ());
114 private boolean isBetween(double val, int min, int max) {
115 return val >= min && val <= max;
119 public AbstractRenderer<?> getRenderer() {
124 public boolean isVisibleCulling() {
125 return RenderCulling.isVisibleCulling(minPoint.getX(), minPoint.getY(), minPoint.getZ(), maxPoint.getX(), maxPoint.getY(), maxPoint.getZ()); // TODO better culling