Package Hexel.things

Source Code of Hexel.things.ThingTools

package Hexel.things;

import java.util.ArrayList;
import java.util.HashSet;

import Hexel.Engine;
import Hexel.Resources;
import Hexel.blocks.BlockTools;
import Hexel.blocks.BlockTools.PointFloodSearchMatcher;
import Hexel.blocks.types.Block;
import Hexel.blocks.types.BlockEmpty;
import Hexel.blocks.types.BlockWater;
import Hexel.chunk.Chunk;
import Hexel.chunk.Chunks;
import Hexel.math.HexGeometry;
import Hexel.math.Vector2d;
import Hexel.math.Vector2i;
import Hexel.math.Vector3d;
import Hexel.math.Vector3i;
import Hexel.things.types.Cuboid;
import Hexel.things.types.Thing;
import Hexel.things.types.Volumetric;

public class ThingTools {

  private Chunks chunks;
  private Engine engine;
  private static final Vector3d zeroOffset = new Vector3d(0, 0, 0);

  public ThingTools(Engine engine, Chunks chunks) {
    this.engine = engine;
    this.chunks = chunks;
  }
 
  public ArrayList<Vector3i> getBlocksIntersectingThing(final Cuboid c, final FixOffsetTmps fixOffsetTmps){
    Vector3i checkBlockPos = new Vector3i();
    Vector2d tmp = new Vector2d();
    HexGeometry.cartesianToBlock(c.getX(), c.getY(), c.getZ(), tmp, checkBlockPos);
    final ArrayList<Vector3i> blocks = new ArrayList<Vector3i>();
    BlockTools.pointFloodSearch(checkBlockPos, new PointFloodSearchMatcher(){
      @Override
      public boolean matches(Vector3i p) {
        Vector3d partialFix = Resources.vector3dResourcePool.aquire();
        partialFix.x = 0;
        partialFix.y = 0;
        partialFix.z = 0;
        collides(c, zeroOffset, p.x, p.y, p.z, partialFix, fixOffsetTmps.collidesTmps);
        if (partialFix.x != 0 || partialFix.y != 0 || partialFix.z != 0){
          blocks.add(new Vector3i(p));
          return true;
        }
        else {
          Resources.vector3dResourcePool.recycle(partialFix);
        }
        return false;
      }
    });
    return blocks;
  }

  public boolean isOutOfRangeOfCamera(Volumetric v){
    Vector3d c = Resources.vector3dResourcePool.aquire();
    c.x = this.engine.camera.getCameraX();
    c.y = this.engine.camera.getCameraY();
    c.z = this.engine.camera.getCameraZ();
    Vector3d p = Resources.vector3dResourcePool.aquire();
    v.getXYZ(p);

    Resources.vector3dResourcePool.recycle(c);
    Resources.vector3dResourcePool.recycle(p);

    return p.distance(c) > this.engine.chunkVisibilityManager.renderDistance;
  }

  private interface CheckCollidableBlock {
    public boolean isColliding(Block block);
  }

  private CheckCollidableBlock checkCollidesSolid = new CheckCollidableBlock() {
    @Override
    public boolean isColliding(Block block) {
      return !(block instanceof BlockEmpty || block instanceof BlockWater);
    }
  };

  private CheckCollidableBlock checkCollidesWater = new CheckCollidableBlock() {
    @Override
    public boolean isColliding(Block block) {
      return block instanceof BlockWater;
    }
  };

  public class CollidesTmps {
    public Vector3d[] v3d6 = new Vector3d[6];
    public Vector2d vd = new Vector2d();
    public Vector2d ud = new Vector2d();
    public double[] d6 = new double[6];
    public Vector2d v2d = new Vector2d();

    public final Vector3d up = new Vector3d(0, 0, 1);
    public final Vector3d vd100 = new Vector3d(1, 0, 0);
    public final Vector3d vd010 = new Vector3d(0, 1, 0);
    public final Vector3d vd001 = new Vector3d(0, 0, 1);

    public Vector3d[] v3d3 = new Vector3d[]{ new Vector3d(), new Vector3d(), new Vector3d() };

  }

  public class FixOffsetTmps {
    public Vector3i tmp3i = new Vector3i();
    public Vector2d tmp2d = new Vector2d();
    public HashSet<Vector3i> toCheck = new HashSet<Vector3i>();
    public HashSet<Vector3d> toFixBlockSet = new HashSet<Vector3d>();
    public Vector3d attempt = new Vector3d();
    public Vector3i tmp = new Vector3i();
    public CollidesTmps collidesTmps = new CollidesTmps();


  }

  public boolean collidesSolid(Volumetric v, Vector3d offset, FixOffsetTmps tmps) {
    if (v instanceof Cuboid) {
      return this.fixOffset((Cuboid) v, offset, false, this.checkCollidesSolid, tmps) != null;
    } else {
      return false;
    }
  }

  public boolean collidesWater(Volumetric v, Vector3d offset, FixOffsetTmps tmps) {
    if (v instanceof Cuboid) {
      return this.fixOffset((Cuboid) v, offset, false, this.checkCollidesWater, tmps) != null;
    } else {
      return false;
    }
  }

  public boolean collidesWater(double x, double y, double z, Vector2d tmp2d, Vector3i tmp3i) {
    Vector3i blockPos = new Vector3i();
    HexGeometry.cartesianToBlock(x, y, z, tmp2d, blockPos);
    Block b = this.chunks.getBlock(blockPos.x, blockPos.y, blockPos.z, tmp3i, (Chunk)null);
    return b instanceof BlockWater;
  }

  public Vector3d fixOffset(Cuboid c, Vector3d offset, boolean considerNeighbors, FixOffsetTmps tmps) {
    return fixOffset(c, offset, considerNeighbors, this.checkCollidesSolid, tmps);
  }

  public Vector3d fixOffset(final Cuboid c, final Vector3d offset,
      boolean considerNeighbors, final CheckCollidableBlock checkCollidableBlock, final FixOffsetTmps tmps) {

    tmps.toCheck.clear();
    tmps.toFixBlockSet.clear();

    Vector3i checkBlockPos = tmps.tmp3i;
    HexGeometry.cartesianToBlock(c.getX(), c.getY(), c.getZ(), tmps.tmp2d, checkBlockPos);
    BlockTools.pointFloodSearch(checkBlockPos, new PointFloodSearchMatcher(){
      @Override
      public boolean matches(Vector3i p) {
        Vector3d partialFix = Resources.vector3dResourcePool.aquire();
        partialFix.x = 0;
        partialFix.y = 0;
        partialFix.z = 0;
        collides(c, offset, p.x, p.y, p.z, partialFix, tmps.collidesTmps);
        if (partialFix.x != 0 || partialFix.y != 0 || partialFix.z != 0){
          Block b = chunks.getBlock(p.x, p.y, p.z, tmps.tmp3i, (Chunk)null);
          if (checkCollidableBlock.isColliding(b)){
            tmps.toFixBlockSet.add(partialFix);
            return true;
          }
          else {
            Resources.vector3dResourcePool.recycle(partialFix);
            return true;
          }
        }
        else {
          Resources.vector3dResourcePool.recycle(partialFix);
        }
        return false;
      }
    });


    Vector3d toFix = new Vector3d();
    for (Vector3d toFixBlock : tmps.toFixBlockSet) {
      toFix.add(toFixBlock);
      Resources.vector3dResourcePool.recycle(toFixBlock);
    }
    if (toFix.mag() == 0)
      return null;
    else {
      return toFix;
    }
  }

  public void collides(Cuboid c, Vector3d offset, int blockx, int blocky,
      int blockz, Vector3d toFix, CollidesTmps tmps) {

    Vector2i[] points;
    if (blockx % 2 == 0) {
      points = HexGeometry.evenTringlePoints;
    } else {
      points = HexGeometry.oddTringlePoints;
    }

    Vector3d[] axis = tmps.v3d6;
    axis[0] = tmps.vd100;
    axis[1] = tmps.vd010;
    axis[2] = tmps.vd001;
    axis[3] = null;
    axis[4] = null;
    axis[5] = null;


    Vector3d up = tmps.up;
    for (int i = 0; i < points.length; i++) {
      Vector2i v = points[i];
      Vector2i u = points[(i + 1) % points.length];
      Vector2d vd = tmps.vd;
      Vector2d ud = tmps.ud;
      HexGeometry.hexToCartesian(v.x, v.y, vd);
      HexGeometry.hexToCartesian(u.x, u.y, ud);

      Vector3d plane = tmps.v3d3[i];
      plane.x = vd.x - ud.x;
      plane.y = vd.y - ud.y;
      plane.z = 0;
      plane.cross(up);
      plane.unit();
      axis[3 + i] = plane;
      if (plane.y == -1)
        plane.y = 1;
    }
    double[] magnitudes = tmps.d6;
    magnitudes[0] = 0;
    magnitudes[1] = 0;
    magnitudes[2] = 0;
    magnitudes[3] = 0;
    magnitudes[4] = 0;
    magnitudes[5] = 0;
    for (int i = 0; i < axis.length; i++) {
      Double m = calcOverlapMagnitude(c, offset, blockx, blocky, blockz,
          axis[i], tmps);
      if (m == 0)
        return;
      magnitudes[i] = m;

    }
    for (int i = 0; i < axis.length; i++) {
      double overlapMagnitude = magnitudes[i];
      if (overlapMagnitude != 0
          && (toFix.mag() == 0 || Math.abs(overlapMagnitude) < toFix.mag())) {
        toFix.x = overlapMagnitude * axis[i].x;
        toFix.y = overlapMagnitude * axis[i].y;
        toFix.z = overlapMagnitude * axis[i].z;
      }
    }
  }

  public Double calcOverlapMagnitude(Cuboid c, Vector3d offset, int blockx,
      int blocky, int blockz, Vector3d axis, CollidesTmps tmps) {
    double minC = Integer.MAX_VALUE;
    double maxC = Integer.MIN_VALUE;
    double cx = c.getX() + offset.x;
    double cy = c.getY() + offset.y;
    double cz = c.getZ() + offset.z;
    minC = Math.min(minC, axis.dot(cx, cy, cz));
    minC = Math.min(minC, axis.dot(cx + c.getWidth(), cy, cz));
    minC = Math.min(minC, axis.dot(cx, cy + c.getHeight(), cz));
    minC = Math.min(minC,
        axis.dot(cx + c.getWidth(), cy + c.getHeight(), cz));
    minC = Math.min(minC, axis.dot(cx, cy, cz + c.getDepth()));
    minC = Math.min(minC,
        axis.dot(cx + c.getWidth(), cy, cz + c.getDepth()));
    minC = Math.min(minC,
        axis.dot(cx, cy + c.getHeight(), cz + c.getDepth()));
    minC = Math.min(
        minC,
        axis.dot(cx + c.getWidth(), cy + c.getHeight(),
            cz + c.getDepth()));

    maxC = Math.max(maxC, axis.dot(cx, cy, cz));
    maxC = Math.max(maxC, axis.dot(cx + c.getWidth(), cy, cz));
    maxC = Math.max(maxC, axis.dot(cx, cy + c.getHeight(), cz));
    maxC = Math.max(maxC,
        axis.dot(cx + c.getWidth(), cy + c.getHeight(), cz));
    maxC = Math.max(maxC, axis.dot(cx, cy, cz + c.getDepth()));
    maxC = Math.max(maxC,
        axis.dot(cx + c.getWidth(), cy, cz + c.getDepth()));
    maxC = Math.max(maxC,
        axis.dot(cx, cy + c.getHeight(), cz + c.getDepth()));
    maxC = Math.max(
        maxC,
        axis.dot(cx + c.getWidth(), cy + c.getHeight(),
            cz + c.getDepth()));

    double minB = Integer.MAX_VALUE;
    double maxB = Integer.MIN_VALUE;

    Vector2d p = tmps.v2d;

    Vector2i[] points;
    if (blockx % 2 == 0) {
      points = HexGeometry.evenTringlePoints;
    } else {
      points = HexGeometry.oddTringlePoints;
    }

    for (Vector2i point : points) {
      HexGeometry.hexToCartesian(Math.floor(blockx / 2.0) + point.x,
          blocky + point.y, p);

      minB = Math.min(minB, axis.dot(p.x, p.y, blockz / 2.0));
      maxB = Math.max(maxB, axis.dot(p.x, p.y, blockz / 2.0));

      minB = Math.min(minB, axis.dot(p.x, p.y, blockz / 2.0 + .5));
      maxB = Math.max(maxB, axis.dot(p.x, p.y, blockz / 2.0 + .5));
    }

    if (maxC <= minB || minC >= maxB) {
      return 0.0;
    } else {
      double a = minB - maxC;
      double b = maxB - minC;

      if (Math.abs(a) > Math.abs(b))
        return b;
      else
        return a;
    }
  }
}
TOP

Related Classes of Hexel.things.ThingTools

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.