/**
* Copyright 2014
* SMEdit https://github.com/StarMade/SMEdit
* SMTools https://github.com/StarMade/SMTools
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
**/
package jo.sm.ship.logic;
import java.util.Iterator;
import jo.sm.data.BlockTypes;
import jo.sm.data.BooleanMatrix3D;
import jo.sm.data.CubeIterator;
import jo.sm.data.RenderTile;
import jo.sm.data.SparseMatrix;
import jo.sm.data.StarMade;
import jo.sm.mods.IPluginCallback;
import jo.sm.ship.data.Block;
import jo.vecmath.Point3i;
/**
* @Auther Jo Jaquinta for SMEdit Classic - version 1.0
**/
public class SmoothLogic {
public static final int EXTERIOR = 1;
public static final int INTERIOR = 2;
public static final int EVERYWHERE = EXTERIOR + INTERIOR;
public static final int WEDGES = 1;
public static final int CORNERS = 2;
public static final int EVERYTHING = WEDGES + CORNERS;
private static final Point3i[] DELTAS = {
new Point3i(1, 0, 0),
new Point3i(-1, 0, 0),
new Point3i(0, 1, 0),
new Point3i(0, -1, 0),
new Point3i(0, 0, 1),
new Point3i(0, 0, -1),};
public static void smooth(SparseMatrix<Block> grid, int scope, int type, StarMade sm, IPluginCallback cb) {
//Set<Point3i> exterior = HullLogic.findExterior(grid, cb);
BooleanMatrix3D exterior = HullLogic.findExteriorMatrix(grid, cb);
boolean[] edges = new boolean[6];
cb.setStatus("Smoothing");
Point3i lower = new Point3i();
Point3i upper = new Point3i();
if ((sm.getSelectedLower() != null) && (sm.getSelectedUpper() != null)) {
lower.set(sm.getSelectedLower());
upper.set(sm.getSelectedUpper());
} else {
grid.getBounds(lower, upper);
lower.x--;
lower.y--;
lower.z--;
upper.x++;
upper.y++;
upper.z++;
}
cb.startTask((upper.x - lower.x + 1) * (upper.y - lower.y + 1) * (upper.z - lower.z + 1));
for (Iterator<Point3i> i = new CubeIterator(lower, upper); i.hasNext();) {
cb.workTask(1);
Point3i p = i.next();
if (grid.contains(p)) {
continue;
}
if (exterior.contains(p)) {
if ((scope & EXTERIOR) == 0) {
continue;
}
} else {
if ((scope & INTERIOR) == 0) {
continue;
}
}
int tot = 0;
for (int j = 0; j < edges.length; j++) {
edges[j] = isEdge(grid, p, DELTAS[j]);
if (edges[j]) {
tot++;
}
}
if ((tot == 2) && ((type & WEDGES) != 0)) {
doWedge(grid, p, edges);
}
if ((tot == 3) && ((type & CORNERS) != 0)) {
doCorner(grid, p, edges);
}
}
cb.endTask();
}
private static void doCorner(SparseMatrix<Block> grid, Point3i p, boolean[] edges) {
int ori = -1;
if (edges[RenderTile.XM]) {
if (edges[RenderTile.YM]) {
if (edges[RenderTile.ZM]) {
ori = 1;
} else if (edges[RenderTile.ZP]) {
ori = 0;
}
} else if (edges[RenderTile.YP]) {
if (edges[RenderTile.ZM]) {
ori = 5;
} else if (edges[RenderTile.ZP]) {
ori = 4;
}
}
} else if (edges[RenderTile.XP]) {
if (edges[RenderTile.YM]) {
if (edges[RenderTile.ZM]) {
ori = 2;
} else if (edges[RenderTile.ZP]) {
ori = 3;
}
} else if (edges[RenderTile.YP]) {
if (edges[RenderTile.ZM]) {
ori = 6;
} else if (edges[RenderTile.ZP]) {
ori = 7;
}
}
}
if (ori < 0) {
return;
}
Block b = new Block();
b.setActive(false);
b.setBlockID(calculateCornerType(grid, p, edges));
b.setOrientation((short) ori);
grid.set(p, b);
}
private static void doWedge(SparseMatrix<Block> grid, Point3i p, boolean[] edges) {
int ori = -1;
if (edges[RenderTile.XM]) {
if (edges[RenderTile.YM]) {
ori = 3;
} else if (edges[RenderTile.YP]) {
ori = 5;
} else if (edges[RenderTile.ZM]) {
ori = 13;
} else if (edges[RenderTile.ZP]) {
ori = 8;
}
} else if (edges[RenderTile.XP]) {
if (edges[RenderTile.YM]) {
ori = 1;
} else if (edges[RenderTile.YP]) {
ori = 7;
} else if (edges[RenderTile.ZM]) {
ori = 11;
} else if (edges[RenderTile.ZP]) {
ori = 10;
}
} else if (edges[RenderTile.YM]) {
if (edges[RenderTile.ZM]) {
ori = 2;
} else if (edges[RenderTile.ZP]) {
ori = 0;
}
} else if (edges[RenderTile.YP]) {
if (edges[RenderTile.ZM]) {
ori = 6;
} else if (edges[RenderTile.ZP]) {
ori = 4;
}
}
if (ori < 0) {
return;
}
Block b = new Block();
b.setActive(false);
b.setBlockID(calculateWedgeType(grid, p, edges));
b.setOrientation((short) ori);
grid.set(p, b);
}
private static short calculateWedgeType(SparseMatrix<Block> grid, Point3i p,
boolean[] edges) {
short type1 = -1;
short type2 = -1;
for (int i = 0; i < edges.length; i++) {
if (!edges[i]) {
continue;
}
Point3i p2 = new Point3i();
p2.add(p, DELTAS[i]);
Block b = grid.get(p2);
if (b == null) {
continue;
}
if (type1 == -1) {
type1 = b.getBlockID();
} else if (type2 == -1) {
type2 = b.getBlockID();
break;
}
}
if (type1 > type2) {
type1 = type2;
}
if (type1 == BlockTypes.HULL_COLOR_GREY_ID) {
return BlockTypes.HULL_COLOR_WEDGE_GREY_ID;
}
if (type1 == BlockTypes.HULL_COLOR_PURPLE_ID) {
return BlockTypes.HULL_COLOR_WEDGE_PURPLE_ID;
}
if (type1 == BlockTypes.HULL_COLOR_BROWN_ID) {
return BlockTypes.HULL_COLOR_WEDGE_BROWN_ID;
}
if (type1 == BlockTypes.HULL_COLOR_BLACK_ID) {
return BlockTypes.HULL_COLOR_WEDGE_BLACK_ID;
}
if (type1 == BlockTypes.HULL_COLOR_RED_ID) {
return BlockTypes.HULL_COLOR_WEDGE_RED_ID;
}
if (type1 == BlockTypes.HULL_COLOR_BLUE_ID) {
return BlockTypes.HULL_COLOR_WEDGE_BLUE_ID;
}
if (type1 == BlockTypes.HULL_COLOR_GREEN_ID) {
return BlockTypes.HULL_COLOR_WEDGE_GREEN_ID;
}
if (type1 == BlockTypes.HULL_COLOR_YELLOW_ID) {
return BlockTypes.HULL_COLOR_WEDGE_YELLOW_ID;
}
if (type1 == BlockTypes.HULL_COLOR_WHITE_ID) {
return BlockTypes.HULL_COLOR_WEDGE_WHITE_ID;
}
if (type1 == BlockTypes.GLASS_ID) {
return BlockTypes.GLASS_WEDGE_ID;
}
if (type1 == BlockTypes.POWERHULL_COLOR_GREY) {
return BlockTypes.POWERHULL_COLOR_WEDGE_GREY;
}
if (type1 == BlockTypes.POWERHULL_COLOR_PURPLE) {
return BlockTypes.POWERHULL_COLOR_WEDGE_PURPLE;
}
if (type1 == BlockTypes.POWERHULL_COLOR_BROWN) {
return BlockTypes.POWERHULL_COLOR_WEDGE_BROWN;
}
if (type1 == BlockTypes.POWERHULL_COLOR_BLACK) {
return BlockTypes.POWERHULL_COLOR_WEDGE_BLACK;
}
if (type1 == BlockTypes.POWERHULL_COLOR_RED) {
return BlockTypes.POWERHULL_COLOR_WEDGE_RED;
}
if (type1 == BlockTypes.POWERHULL_COLOR_BLUE) {
return BlockTypes.POWERHULL_COLOR_WEDGE_BLUE;
}
if (type1 == BlockTypes.POWERHULL_COLOR_GREEN) {
return BlockTypes.POWERHULL_COLOR_WEDGE_GREEN;
}
if (type1 == BlockTypes.POWERHULL_COLOR_GOLD) {
return BlockTypes.POWERHULL_COLOR_WEDGE_GOLD;
}
if (type1 == BlockTypes.POWERHULL_COLOR_WHITE) {
return BlockTypes.POWERHULL_COLOR_WEDGE_WHITE;
}
return type1;
}
private static short calculateCornerType(SparseMatrix<Block> grid, Point3i p,
boolean[] edges) {
short type1 = -1;
short type2 = -1;
short type3 = -1;
for (int i = 0; i < edges.length; i++) {
if (!edges[i]) {
continue;
}
Point3i p2 = new Point3i();
p2.add(p, DELTAS[i]);
Block b = grid.get(p2);
if (b == null) {
continue;
}
if (type1 == -1) {
type1 = b.getBlockID();
} else if (type2 == -1) {
type2 = b.getBlockID();
} else if (type3 == -1) {
type3 = b.getBlockID();
break;
}
}
if (type1 != type2) {
if (type2 == type3) {
type1 = type2;
} else if (type1 != type3) {
type1 = (short) Math.min(type1, Math.min(type2, type3));
}
}
if (type1 == BlockTypes.HULL_COLOR_GREY_ID) {
return BlockTypes.HULL_COLOR_CORNER_GREY_ID;
}
if (type1 == BlockTypes.HULL_COLOR_PURPLE_ID) {
return BlockTypes.HULL_COLOR_CORNER_PURPLE_ID;
}
if (type1 == BlockTypes.HULL_COLOR_BROWN_ID) {
return BlockTypes.HULL_COLOR_CORNER_BROWN_ID;
}
if (type1 == BlockTypes.HULL_COLOR_BLACK_ID) {
return BlockTypes.HULL_COLOR_CORNER_BLACK_ID;
}
if (type1 == BlockTypes.HULL_COLOR_RED_ID) {
return BlockTypes.HULL_COLOR_CORNER_RED_ID;
}
if (type1 == BlockTypes.HULL_COLOR_BLUE_ID) {
return BlockTypes.HULL_COLOR_CORNER_BLUE_ID;
}
if (type1 == BlockTypes.HULL_COLOR_GREEN_ID) {
return BlockTypes.HULL_COLOR_CORNER_GREEN_ID;
}
if (type1 == BlockTypes.HULL_COLOR_YELLOW_ID) {
return BlockTypes.HULL_COLOR_CORNER_YELLOW_ID;
}
if (type1 == BlockTypes.HULL_COLOR_WHITE_ID) {
return BlockTypes.HULL_COLOR_CORNER_WHITE_ID;
}
if (type1 == BlockTypes.GLASS_ID) {
return BlockTypes.GLASS_CORNER_ID;
}
if (type1 == BlockTypes.POWERHULL_COLOR_GREY) {
return BlockTypes.POWERHULL_COLOR_CORNER_GREY;
}
if (type1 == BlockTypes.POWERHULL_COLOR_PURPLE) {
return BlockTypes.POWERHULL_COLOR_WEDGE_PURPLE;
}
if (type1 == BlockTypes.POWERHULL_COLOR_BROWN) {
return BlockTypes.POWERHULL_COLOR_CORNER_BROWN;
}
if (type1 == BlockTypes.POWERHULL_COLOR_BLACK) {
return BlockTypes.POWERHULL_COLOR_CORNER_BLACK;
}
if (type1 == BlockTypes.POWERHULL_COLOR_RED) {
return BlockTypes.POWERHULL_COLOR_CORNER_RED;
}
if (type1 == BlockTypes.POWERHULL_COLOR_BLUE) {
return BlockTypes.POWERHULL_COLOR_CORNER_BLUE;
}
if (type1 == BlockTypes.POWERHULL_COLOR_GREEN) {
return BlockTypes.POWERHULL_COLOR_CORNER_GREEN;
}
if (type1 == BlockTypes.POWERHULL_COLOR_GOLD) {
return BlockTypes.POWERHULL_COLOR_CORNER_GOLD;
}
if (type1 == BlockTypes.POWERHULL_COLOR_WHITE) {
return BlockTypes.POWERHULL_COLOR_CORNER_WHITE;
}
return type1;
}
private static boolean isEdge(SparseMatrix<Block> grid, Point3i p, Point3i d) {
Point3i p2 = new Point3i();
p2.add(p, d);
if (!grid.contains(p2)) {
return false;
}
short type = grid.get(p2).getBlockID();
if (BlockTypes.isWedge(type) || BlockTypes.isPowerWedge(type)) {
return false;
}
return BlockTypes.isHull(type) || BlockTypes.isPowerHull(type) || (type == BlockTypes.GLASS_ID);
}
}