/**
* 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.logic;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.Path2D;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.ImageIcon;
import jo.sm.data.BlockTypes;
import jo.sm.data.RenderPoly;
import jo.sm.data.RenderSet;
import jo.sm.data.SparseMatrix;
import jo.sm.ship.data.Block;
import jo.sm.ui.BlockTypeColors;
import jo.vecmath.Matrix3f;
import jo.vecmath.Matrix4f;
import jo.vecmath.Point3f;
import jo.vecmath.Point3i;
import jo.vecmath.logic.Point3iLogic;
public class RenderPolyLogic {
private static final Logger log = Logger.getLogger(RenderPolyLogic.class.getName());
public static void fillPolys(SparseMatrix<Block> blocks, RenderSet set) {
set.getAllPolys().clear();
Point3i lower = new Point3i();
Point3i upper = new Point3i();
blocks.getBounds(lower, upper);
getBasicPolys(blocks, upper, lower, set.getAllPolys());
//log.log(Level.INFO, "FillPolys: count="+set.getAllPolys().size());
}
private static void getBasicPolys(SparseMatrix<Block> blocks,
Point3i upper, Point3i lower, List<RenderPoly> polys) {
/*
for (int z = lower.z; z <= upper.z; z++)
{
System.out.println("Z="+z);
for (int y = lower.y; y <= upper.y; y++)
{
if (y < 10)
System.out.print(" ");
System.out.print(y+": ");
for (int x = lower.x; x <= upper.x; x++)
{
Block b = blocks.get(x, y, z);
// if (b == null)
// System.out.print(" ------------------------");
// else
// System.out.print(" "+b.getOrientation()+":"+StringUtils.zeroPrefix(Integer.toBinaryString(b.getBitfield()), 24));
if (b == null)
System.out.print(" --");
else
System.out.print(" "+StringUtils.spacePrefix(Integer.toString(b.getOrientation()), 2));
}
System.out.println();
}
}
*/
for (Iterator<Point3i> i = blocks.iteratorNonNull(); i.hasNext();) {
Point3i p = i.next();
Block b = blocks.get(p);
short blockID = b.getBlockID();
if (BlockTypes.isCorner(blockID) || BlockTypes.isPowerCorner(blockID)) {
doCorner(blocks, p, polys);
} else if (BlockTypes.isWedge(blockID) || BlockTypes.isPowerWedge(blockID)) {
doWedge(blocks, p, polys);
} else if (BlockTypes.isPenta(blockID) || BlockTypes.isPowerPenta(blockID)) {
doPenta(blocks, p, polys);
} else if (BlockTypes.isTetra(blockID) || BlockTypes.isPowerTetra(blockID)) {
doTetra(blocks, p, polys);
} else {
doCube(blocks, p, polys);
}
}
}
private static void doPenta(SparseMatrix<Block> blocks, Point3i p, List<RenderPoly> polys) {
doXPSquare(blocks, p, polys, RenderPoly.SQUARE);
doXMSquare(blocks, p, polys, RenderPoly.SQUARE);
doYPSquare(blocks, p, polys, RenderPoly.SQUARE);
doYMSquare(blocks, p, polys, RenderPoly.SQUARE);
doZPSquare(blocks, p, polys, RenderPoly.SQUARE);
doZMSquare(blocks, p, polys, RenderPoly.SQUARE);
}
private static void doTetra(SparseMatrix<Block> blocks, Point3i p, List<RenderPoly> polys) {
doXPSquare(blocks, p, polys, RenderPoly.SQUARE);
doXMSquare(blocks, p, polys, RenderPoly.SQUARE);
doYPSquare(blocks, p, polys, RenderPoly.SQUARE);
doYMSquare(blocks, p, polys, RenderPoly.SQUARE);
doZPSquare(blocks, p, polys, RenderPoly.SQUARE);
doZMSquare(blocks, p, polys, RenderPoly.SQUARE);
}
private static void doCorner(SparseMatrix<Block> blocks, Point3i p, List<RenderPoly> polys) {
//System.out.println("Corner, ori="+blocks.get(p).getOrientation());
switch (blocks.get(p).getOrientation()) {
case 0: // spire: xp,zm>yp
doYMSquare(blocks, p, polys, RenderPoly.SQUARE); // bottom
doXMSquare(blocks, p, polys, RenderPoly.TRI4); // back
doZPSquare(blocks, p, polys, RenderPoly.TRI1); // back
doRect(blocks, p, polys, RenderPoly.XPYP, RenderPoly.TRI2);
doRect(blocks, p, polys, RenderPoly.YPZM, RenderPoly.TRI1);
break;
case 1: // spire: xp,zp>yp
doYMSquare(blocks, p, polys, RenderPoly.SQUARE); // bottom
doXMSquare(blocks, p, polys, RenderPoly.TRI1); // back
doZMSquare(blocks, p, polys, RenderPoly.TRI1); // back
doRect(blocks, p, polys, RenderPoly.XPYP, RenderPoly.TRI1);
doRect(blocks, p, polys, RenderPoly.YPZP, RenderPoly.TRI4);
break;
case 2: // spire: xm,zp>yp
doYMSquare(blocks, p, polys, RenderPoly.SQUARE); // bottom
doXPSquare(blocks, p, polys, RenderPoly.TRI1); // back
doZMSquare(blocks, p, polys, RenderPoly.TRI2); // back
doRect(blocks, p, polys, RenderPoly.XMYP, RenderPoly.TRI1);
doRect(blocks, p, polys, RenderPoly.YPZP, RenderPoly.TRI3);
break;
case 3: // spire: xm,zp>yp
doYMSquare(blocks, p, polys, RenderPoly.SQUARE); // bottom
doXPSquare(blocks, p, polys, RenderPoly.TRI4); // back
doZPSquare(blocks, p, polys, RenderPoly.TRI2); // back
doRect(blocks, p, polys, RenderPoly.XMYP, RenderPoly.TRI4);
doRect(blocks, p, polys, RenderPoly.YPZM, RenderPoly.TRI2);
break;
case 4: // spire: xm,zp>yp
doYPSquare(blocks, p, polys, RenderPoly.SQUARE); // bottom
doXMSquare(blocks, p, polys, RenderPoly.TRI3); // back
doZPSquare(blocks, p, polys, RenderPoly.TRI4); // back
doRect(blocks, p, polys, RenderPoly.XPYM, RenderPoly.TRI3);
doRect(blocks, p, polys, RenderPoly.YMZM, RenderPoly.TRI1);
break;
case 5: // spire: xm,zp>yp
doYPSquare(blocks, p, polys, RenderPoly.SQUARE); // bottom
doXMSquare(blocks, p, polys, RenderPoly.TRI2); // back
doZMSquare(blocks, p, polys, RenderPoly.TRI4); // back
doRect(blocks, p, polys, RenderPoly.XPYM, RenderPoly.TRI2);
doRect(blocks, p, polys, RenderPoly.YMZP, RenderPoly.TRI4);
break;
case 6: // spire: xm,zp>yp
doYPSquare(blocks, p, polys, RenderPoly.SQUARE); // bottom
doXPSquare(blocks, p, polys, RenderPoly.TRI2); // back
doZMSquare(blocks, p, polys, RenderPoly.TRI3); // back
doRect(blocks, p, polys, RenderPoly.XMYM, RenderPoly.TRI4);
doRect(blocks, p, polys, RenderPoly.YMZP, RenderPoly.TRI3);
break;
case 7: // spire: xm,zp>yp
doYPSquare(blocks, p, polys, RenderPoly.SQUARE); // bottom
doXPSquare(blocks, p, polys, RenderPoly.TRI3); // back
doZPSquare(blocks, p, polys, RenderPoly.TRI3); // back
doRect(blocks, p, polys, RenderPoly.XMYM, RenderPoly.TRI3);
doRect(blocks, p, polys, RenderPoly.YMZM, RenderPoly.TRI2);
break;
}
}
private static void doWedge(SparseMatrix<Block> blocks, Point3i p, List<RenderPoly> polys) {
switch (blocks.get(p).getOrientation()) {
case 0: // YPZM
doXMSquare(blocks, p, polys, RenderPoly.TRI4);
doXPSquare(blocks, p, polys, RenderPoly.TRI4);
// no YP face
doYMSquare(blocks, p, polys, RenderPoly.SQUARE);
doZPSquare(blocks, p, polys, RenderPoly.SQUARE);
// no ZM face
doRect(blocks, p, polys, RenderPoly.YPZM);
break;
case 1: // XMYP
doXPSquare(blocks, p, polys, RenderPoly.SQUARE);
// no XM face
// no YP face
doYMSquare(blocks, p, polys, RenderPoly.SQUARE);
doZMSquare(blocks, p, polys, RenderPoly.TRI2);
doZPSquare(blocks, p, polys, RenderPoly.TRI2);
doRect(blocks, p, polys, RenderPoly.XMYP);
break;
case 2: // YPZP
doXMSquare(blocks, p, polys, RenderPoly.TRI1);
doXPSquare(blocks, p, polys, RenderPoly.TRI1);
// no YP face
doYMSquare(blocks, p, polys, RenderPoly.SQUARE);
// no ZP face
doZMSquare(blocks, p, polys, RenderPoly.SQUARE);
doRect(blocks, p, polys, RenderPoly.YPZP);
break;
case 3: // XPYP
// no XP face
doXMSquare(blocks, p, polys, RenderPoly.SQUARE);
// no YP face
doYMSquare(blocks, p, polys, RenderPoly.SQUARE);
doZMSquare(blocks, p, polys, RenderPoly.TRI1);
doZPSquare(blocks, p, polys, RenderPoly.TRI1);
doRect(blocks, p, polys, RenderPoly.XPYP);
break;
case 4: // YMZM
doXMSquare(blocks, p, polys, RenderPoly.TRI3);
doXPSquare(blocks, p, polys, RenderPoly.TRI3);
doYPSquare(blocks, p, polys, RenderPoly.SQUARE);
// no YM face
doZPSquare(blocks, p, polys, RenderPoly.SQUARE);
// no ZM face
doRect(blocks, p, polys, RenderPoly.YMZM);
break;
case 5: // XPYM
// no XP face
doXMSquare(blocks, p, polys, RenderPoly.SQUARE);
doYPSquare(blocks, p, polys, RenderPoly.SQUARE);
// no YM face
doZMSquare(blocks, p, polys, RenderPoly.TRI4);
doZPSquare(blocks, p, polys, RenderPoly.TRI4);
doRect(blocks, p, polys, RenderPoly.XPYM);
break;
case 6: // YMZP
doXMSquare(blocks, p, polys, RenderPoly.TRI2);
doXPSquare(blocks, p, polys, RenderPoly.TRI2);
doYPSquare(blocks, p, polys, RenderPoly.SQUARE);
// no YM face
// no ZP face
doZMSquare(blocks, p, polys, RenderPoly.SQUARE);
doRect(blocks, p, polys, RenderPoly.YMZP);
break;
case 7: // XMYM
doXPSquare(blocks, p, polys, RenderPoly.SQUARE);
// no XM face
doYPSquare(blocks, p, polys, RenderPoly.SQUARE);
// no YM face
doZMSquare(blocks, p, polys, RenderPoly.TRI3);
doZPSquare(blocks, p, polys, RenderPoly.TRI3);
doRect(blocks, p, polys, RenderPoly.XMYM);
break;
case 8: // XPZM
case 12: // ???
// no XP face
doXMSquare(blocks, p, polys, RenderPoly.SQUARE);
doYPSquare(blocks, p, polys, RenderPoly.TRI4);
doYMSquare(blocks, p, polys, RenderPoly.TRI4);
doZPSquare(blocks, p, polys, RenderPoly.SQUARE);
// no ZM face
doRect(blocks, p, polys, RenderPoly.ZMXP);
break;
case 10: // XMZM
case 14:
doXPSquare(blocks, p, polys, RenderPoly.SQUARE);
// no XM face
doYPSquare(blocks, p, polys, RenderPoly.TRI3);
doYMSquare(blocks, p, polys, RenderPoly.TRI3);
doZPSquare(blocks, p, polys, RenderPoly.SQUARE);
// no ZM face
doRect(blocks, p, polys, RenderPoly.ZMXM);
break;
case 11: // XMZP
doXPSquare(blocks, p, polys, RenderPoly.SQUARE);
// no XM face
doYPSquare(blocks, p, polys, RenderPoly.TRI2);
doYMSquare(blocks, p, polys, RenderPoly.TRI2);
// no ZP face
doZMSquare(blocks, p, polys, RenderPoly.SQUARE);
doRect(blocks, p, polys, RenderPoly.ZPXM);
break;
case 13: // XPZP
// no XP face
doXMSquare(blocks, p, polys, RenderPoly.SQUARE);
doYPSquare(blocks, p, polys, RenderPoly.TRI1);
doYMSquare(blocks, p, polys, RenderPoly.TRI1);
// no ZP face
doZMSquare(blocks, p, polys, RenderPoly.SQUARE);
doRect(blocks, p, polys, RenderPoly.ZPXP);
break;
default:
log.log(Level.INFO, "Wedge with unknown ori="+blocks.get(p).getOrientation());
break;
}
}
private static void doCube(SparseMatrix<Block> blocks, Point3i p, List<RenderPoly> polys) {
doXPSquare(blocks, p, polys, RenderPoly.SQUARE);
doXMSquare(blocks, p, polys, RenderPoly.SQUARE);
doYPSquare(blocks, p, polys, RenderPoly.SQUARE);
doYMSquare(blocks, p, polys, RenderPoly.SQUARE);
doZPSquare(blocks, p, polys, RenderPoly.SQUARE);
doZMSquare(blocks, p, polys, RenderPoly.SQUARE);
}
private static void doRect(SparseMatrix<Block> blocks, Point3i p,
List<RenderPoly> polys, int facing) {
doRect(blocks, p, polys, facing, RenderPoly.SQUARE);
}
private static void doRect(SparseMatrix<Block> blocks, Point3i p,
List<RenderPoly> polys, int facing, int type) {
RenderPoly rp = new RenderPoly();
rp.setPosition(p);
rp.setBlock(blocks.get(p));
rp.setNormal(facing);
switch (facing) {
case RenderPoly.XPYP:
case RenderPoly.XMYM:
rp.setModelPoints(new Point3i[]{
new Point3i(p.x + 1, p.y + 0, p.z + 0),
new Point3i(p.x + 1, p.y + 0, p.z + 1),
new Point3i(p.x + 0, p.y + 1, p.z + 1),
new Point3i(p.x + 0, p.y + 1, p.z + 0),});
break;
case RenderPoly.XPYM:
case RenderPoly.XMYP:
rp.setModelPoints(new Point3i[]{
new Point3i(p.x + 0, p.y + 0, p.z + 0),
new Point3i(p.x + 1, p.y + 1, p.z + 0),
new Point3i(p.x + 1, p.y + 1, p.z + 1),
new Point3i(p.x + 0, p.y + 0, p.z + 1),});
break;
case RenderPoly.YPZP:
case RenderPoly.YMZM:
rp.setModelPoints(new Point3i[]{
new Point3i(p.x + 0, p.y + 1, p.z + 0),
new Point3i(p.x + 1, p.y + 1, p.z + 0),
new Point3i(p.x + 1, p.y + 0, p.z + 1),
new Point3i(p.x + 0, p.y + 0, p.z + 1),});
break;
case RenderPoly.YPZM:
case RenderPoly.YMZP:
rp.setModelPoints(new Point3i[]{
new Point3i(p.x + 0, p.y + 0, p.z + 0),
new Point3i(p.x + 1, p.y + 0, p.z + 0),
new Point3i(p.x + 1, p.y + 1, p.z + 1),
new Point3i(p.x + 0, p.y + 1, p.z + 1),});
break;
case RenderPoly.ZPXP:
case RenderPoly.ZMXM:
rp.setModelPoints(new Point3i[]{
new Point3i(p.x + 1, p.y + 0, p.z + 0),
new Point3i(p.x + 1, p.y + 1, p.z + 0),
new Point3i(p.x + 0, p.y + 1, p.z + 1),
new Point3i(p.x + 0, p.y + 0, p.z + 1),});
break;
case RenderPoly.ZPXM:
case RenderPoly.ZMXP:
rp.setModelPoints(new Point3i[]{
new Point3i(p.x + 0, p.y + 0, p.z + 0),
new Point3i(p.x + 1, p.y + 0, p.z + 1),
new Point3i(p.x + 1, p.y + 1, p.z + 1),
new Point3i(p.x + 0, p.y + 1, p.z + 0),});
break;
default:
return;
}
rp.setType(type);
polys.add(rp);
}
private static void doZMSquare(SparseMatrix<Block> blocks, Point3i p,
List<RenderPoly> polys, int type) {
if (!opaque(blocks, p.x, p.y, p.z - 1)) {
RenderPoly rp = new RenderPoly();
rp.setPosition(p);
rp.setBlock(blocks.get(p));
rp.setNormal(RenderPoly.ZM);
rp.setModelPoints(new Point3i[]{
new Point3i(p.x + 0, p.y + 0, p.z + 0),
new Point3i(p.x + 1, p.y + 0, p.z + 0),
new Point3i(p.x + 1, p.y + 1, p.z + 0),
new Point3i(p.x + 0, p.y + 1, p.z + 0),});
rp.setType(type);
polys.add(rp);
}
}
private static void doZPSquare(SparseMatrix<Block> blocks, Point3i p,
List<RenderPoly> polys, int type) {
if (!opaque(blocks, p.x, p.y, p.z + 1)) {
RenderPoly rp = new RenderPoly();
rp.setPosition(p);
rp.setBlock(blocks.get(p));
rp.setNormal(RenderPoly.ZP);
rp.setModelPoints(new Point3i[]{
new Point3i(p.x + 0, p.y + 0, p.z + 1),
new Point3i(p.x + 1, p.y + 0, p.z + 1),
new Point3i(p.x + 1, p.y + 1, p.z + 1),
new Point3i(p.x + 0, p.y + 1, p.z + 1),});
rp.setType(type);
polys.add(rp);
}
}
private static void doYMSquare(SparseMatrix<Block> blocks, Point3i p,
List<RenderPoly> polys, int type) {
if (!opaque(blocks, p.x, p.y - 1, p.z)) {
RenderPoly rp = new RenderPoly();
rp.setPosition(p);
rp.setBlock(blocks.get(p));
rp.setNormal(RenderPoly.YM);
rp.setModelPoints(new Point3i[]{
new Point3i(p.x + 0, p.y + 0, p.z + 0),
new Point3i(p.x + 1, p.y + 0, p.z + 0),
new Point3i(p.x + 1, p.y + 0, p.z + 1),
new Point3i(p.x + 0, p.y + 0, p.z + 1),});
rp.setType(type);
polys.add(rp);
}
}
private static void doYPSquare(SparseMatrix<Block> blocks, Point3i p,
List<RenderPoly> polys, int type) {
if (!opaque(blocks, p.x, p.y + 1, p.z)) {
RenderPoly rp = new RenderPoly();
rp.setPosition(p);
rp.setBlock(blocks.get(p));
rp.setNormal(RenderPoly.YP);
rp.setModelPoints(new Point3i[]{
new Point3i(p.x + 0, p.y + 1, p.z + 0),
new Point3i(p.x + 1, p.y + 1, p.z + 0),
new Point3i(p.x + 1, p.y + 1, p.z + 1),
new Point3i(p.x + 0, p.y + 1, p.z + 1),});
rp.setType(type);
polys.add(rp);
}
}
private static void doXMSquare(SparseMatrix<Block> blocks, Point3i p,
List<RenderPoly> polys, int type) {
if (!opaque(blocks, p.x - 1, p.y, p.z)) {
RenderPoly rp = new RenderPoly();
rp.setPosition(p);
rp.setBlock(blocks.get(p));
rp.setNormal(RenderPoly.XM);
rp.setModelPoints(new Point3i[]{
new Point3i(p.x + 0, p.y + 0, p.z + 0),
new Point3i(p.x + 0, p.y + 1, p.z + 0),
new Point3i(p.x + 0, p.y + 1, p.z + 1),
new Point3i(p.x + 0, p.y + 0, p.z + 1),});
rp.setType(type);
polys.add(rp);
}
}
private static void doXPSquare(SparseMatrix<Block> blocks, Point3i p,
List<RenderPoly> polys, int type) {
if (!opaque(blocks, p.x + 1, p.y, p.z)) {
RenderPoly rp = new RenderPoly();
rp.setPosition(p);
rp.setBlock(blocks.get(p));
rp.setNormal(RenderPoly.XP);
rp.setModelPoints(new Point3i[]{
new Point3i(p.x + 1, p.y + 0, p.z + 0),
new Point3i(p.x + 1, p.y + 1, p.z + 0),
new Point3i(p.x + 1, p.y + 1, p.z + 1),
new Point3i(p.x + 1, p.y + 0, p.z + 1),});
rp.setType(type);
polys.add(rp);
}
}
private static boolean opaque(SparseMatrix<Block> grid, int x, int y, int z) {
Block b = grid.get(x, y, z);
return (b != null) && !BlockTypes.isAnyCorner(b.getBlockID()) && !BlockTypes.isAnyWedge(b.getBlockID());
}
public static void transformAndSort(final RenderSet set, Matrix4f transform) {
List<RenderPoly> tiles = set.getAllPolys();
List<RenderPoly> visible = set.getVisiblePolys();
visible.clear();
Point3f o = new Point3f();
transform.transform(o);
set.setOrigin(o);
Matrix3f rot = new Matrix3f();
transform.get(rot);
float scale = transform.getScale();
boolean[] showing = new boolean[6 + 12];
Point3f unitX = calcShowing(showing, rot, 1, 0, 0, RenderPoly.XP, RenderPoly.XM);
Point3f unitY = calcShowing(showing, rot, 0, 1, 0, RenderPoly.YP, RenderPoly.YM);
Point3f unitZ = calcShowing(showing, rot, 0, 0, 1, RenderPoly.ZP, RenderPoly.ZM);
calcShowing(showing, rot, 1, 1, 0, RenderPoly.XPYP, RenderPoly.XMYM);
calcShowing(showing, rot, -1, 1, 0, RenderPoly.XMYP, RenderPoly.XPYM);
calcShowing(showing, rot, 0, 1, 1, RenderPoly.YPZP, RenderPoly.YMZM);
calcShowing(showing, rot, 0, -1, 1, RenderPoly.YMZP, RenderPoly.YPZM);
calcShowing(showing, rot, 1, 0, 1, RenderPoly.ZPXP, RenderPoly.ZMXM);
calcShowing(showing, rot, 1, 0, -1, RenderPoly.ZMXP, RenderPoly.ZPXM);
unitX.scale(scale);
set.setUnitX(unitX);
unitY.scale(scale);
set.setUnitY(unitY);
unitZ.scale(scale);
set.setUnitZ(unitZ);
//log.log(Level.INFO, "Unit X="+unitX+", Y="+unitY+", Z="+unitZ);
//log.log(Level.INFO, "Showing +x="+showing[0]+", -x="+showing[1]+", +y="+showing[2]+", -y="+showing[3]+", +z="+showing[4]+", -z="+showing[5]);
//log.log(Level.INFO, "Showing XPYP="+showing[RenderPoly.XPYP]);
//System.out.println("Unit X="+unitX+", Y="+unitY+", Z="+unitZ);
//System.out.println("Showing +x="+showing[0]+", -x="+showing[1]+", +y="+showing[2]+", -y="+showing[3]+", +z="+showing[4]+", -z="+showing[5]);
//System.out.println("Showing XPYP="+showing[RenderPoly.XPYP]);
for (RenderPoly tile : tiles) {
if (showing[tile.getNormal()]) {
visible.add(tile);
}
}
Collections.sort(visible, new Comparator<RenderPoly>() {
@Override
public int compare(RenderPoly tile1, RenderPoly tile2) {
float delta = getMidZ(tile2, set) - getMidZ(tile1, set);
if (Math.abs(delta) < .001) {
return (int) Math.signum(tile1.getBlock().getBlockID() - tile2.getBlock().getBlockID());
}
return (int) Math.signum(delta);
}
});
//log.log(Level.INFO, "TransformAndSort, visible="+set.getVisiblePolys().size());
//System.out.println("TransformAndSort, visible="+set.getVisiblePolys().size());
}
private static float getX(Point3i p, RenderSet set) {
float z = set.getOrigin().x + p.x * set.getUnitX().x + p.y * set.getUnitY().x + p.z * set.getUnitZ().x;
return z;
}
private static float getY(Point3i p, RenderSet set) {
float z = set.getOrigin().y + p.x * set.getUnitX().y + p.y * set.getUnitY().y + p.z * set.getUnitZ().y;
return z;
}
private static float getZ(Point3i p, RenderSet set) {
float z = set.getOrigin().z + p.x * set.getUnitX().z + p.y * set.getUnitY().z + p.z * set.getUnitZ().z;
return z;
}
private static float getMidZ(RenderPoly tile, RenderSet set) {
float z = 0;
for (Point3i p : tile.getModelPoints()) {
z += getZ(p, set);
}
z /= tile.getModelPoints().length;
return z;
}
private static Point3f calcShowing(boolean[] showing, Matrix3f rot, int dx, int dy, int dz, int axis, int naxis) {
Point3f xp = new Point3f(dx, dy, dz);
rot.transform(xp);
showing[axis] = xp.z < 0;
showing[naxis] = !showing[axis];
return xp;
}
public static void draw(Graphics2D g2, RenderSet set, boolean fancyGraphics) {
for (RenderPoly tile : set.getVisiblePolys().toArray(new RenderPoly[0])) {
ImageIcon icon = null;
if (fancyGraphics) {
icon = BlockTypeColors.getBlockImage(tile.getBlock().getBlockID());
}
if (tile.getType() == RenderPoly.SQUARE) {
renderSquare(g2, set, tile, icon);
} else if ((tile.getType() >= RenderPoly.TRI1) && (tile.getType() <= RenderPoly.TRI4)) {
renderTriangle(g2, set, tile, icon);
}
}
}
private static void renderTriangle(Graphics2D g2, RenderSet set,
RenderPoly tile, ImageIcon icon) {
//log.log(Level.INFO, "Render triangle "+tile.getType());
//System.out.println("Render triangle "+tile.getType());
Point3f[] corners = getCorners(tile, set);
int pCenter = (tile.getType() - RenderPoly.TRI1);
int pLeft = (pCenter + 1) % 4;
int pRight = (pCenter + 3) % 4;
Path2D p = new Path2D.Float();
p.moveTo(corners[pCenter].x, corners[pCenter].y);
p.lineTo(corners[pLeft].x, corners[pLeft].y);
p.lineTo(corners[pRight].x, corners[pRight].y);
p.lineTo(corners[pCenter].x, corners[pCenter].y);
if (icon != null) {
float m00 = (corners[pRight].x - corners[pCenter].x) / 64f;
float m10 = (corners[pRight].y - corners[pCenter].y) / 64f;
float m01 = (corners[pLeft].x - corners[pCenter].x) / 64f;
float m11 = (corners[pLeft].y - corners[pCenter].y) / 64f;
float m02 = corners[pCenter].x;
float m12 = corners[pCenter].y;
AffineTransform t = new AffineTransform(m00, m10, m01, m11, m02, m12);
if ((icon.getIconWidth() != 64) || (icon.getIconHeight() != 64)) {
t.scale(64.0 / icon.getIconWidth(), 64.0 / icon.getIconHeight());
}
Graphics2D g3 = (Graphics2D) g2.create();
g3.clip(p);
g3.drawImage(icon.getImage(), t, null);
} else {
g2.setPaint(BlockTypeColors.getFillColor(tile.getBlock().getBlockID()));
g2.fill(p);
g2.setPaint(BlockTypeColors.getOutlineColor(tile.getBlock().getBlockID()));
g2.draw(p);
}
}
private static void renderSquare(Graphics2D g2, RenderSet set,
RenderPoly tile, ImageIcon icon) {
Point3f[] corners = getCorners(tile, set);
if (icon != null) {
float m00 = (corners[1].x - corners[0].x) / 64f;
float m10 = (corners[1].y - corners[0].y) / 64f;
float m01 = (corners[3].x - corners[0].x) / 64f;
float m11 = (corners[3].y - corners[0].y) / 64f;
float m02 = corners[0].x;
float m12 = corners[0].y;
AffineTransform t = new AffineTransform(m00, m10, m01, m11, m02, m12);
if ((icon.getIconWidth() != 64) || (icon.getIconHeight() != 64)) {
t.scale(64.0 / icon.getIconWidth(), 64.0 / icon.getIconHeight());
}
g2.drawImage(icon.getImage(), t, null);
} else {
Path2D p = new Path2D.Float();
p.moveTo(corners[0].x, corners[0].y);
p.lineTo(corners[1].x, corners[1].y);
p.lineTo(corners[2].x, corners[2].y);
p.lineTo(corners[3].x, corners[3].y);
p.lineTo(corners[0].x, corners[0].y);
g2.setPaint(BlockTypeColors.getFillColor(tile.getBlock().getBlockID()));
g2.fill(p);
g2.setPaint(BlockTypeColors.getOutlineColor(tile.getBlock().getBlockID()));
g2.draw(p);
}
}
public static Point3f[] getCorners(RenderPoly tile, RenderSet set) {
Point3f[] corners = new Point3f[tile.getModelPoints().length];
for (int i = 0; i < corners.length; i++) {
Point3i p = tile.getModelPoints()[i];
corners[i] = new Point3f();
corners[i].x = getX(p, set);
corners[i].y = getY(p, set);
}
return corners;
}
public static void getBounds(RenderPoly tile, Point3i lower, Point3i upper) {
lower.set(tile.getModelPoints()[0]);
upper.set(tile.getModelPoints()[0]);
for (int i = 1; i < tile.getModelPoints().length; i++) {
Point3iLogic.min(lower, lower, tile.getModelPoints()[i]);
Point3iLogic.max(upper, upper, tile.getModelPoints()[i]);
}
}
}