/**
* 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.ui.lwjgl;
import java.awt.Color;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import jo.sm.data.RenderPoly;
import jo.sm.data.SparseMatrix;
import jo.sm.ship.data.Block;
import jo.sm.ui.BlockTypeColors;
import jo.util.jgl.obj.JGLGroup;
import jo.util.jgl.obj.tri.JGLObj;
import jo.util.lwjgl.win.JGLTextureCache;
import jo.vecmath.Color3f;
import jo.vecmath.Point2f;
import jo.vecmath.Point3f;
import jo.vecmath.Point3i;
import jo.vecmath.logic.MathUtils;
public class LWJGLRenderLogic {
private static int mTextureID = -1;
public static void addBlocks(JGLGroup group, SparseMatrix<Block> grid, boolean plain) {
if (mTextureID < 0) {
BlockTypeColors.loadBlockIcons();
JGLTextureCache.register(1, BlockTypeColors.mAllTextures);
mTextureID = 1;
}
MeshInfo info = new MeshInfo();
info.verts = new ArrayList<>();
info.indexes = new ArrayList<>();
if (plain) {
info.colors = new ArrayList<>();
} else {
info.uv = new ArrayList<>();
}
for (Iterator<Point3i> i = grid.iteratorNonNull(); i.hasNext();) {
addBlock(info, grid, i.next());
}
JGLObj obj = infoToObj(info);
group.add(obj);
}
/**
*
* @param info
* @return
*/
public static JGLObj infoToObj(MeshInfo info) {
JGLObj obj = new JGLObj();
obj.setMode(JGLObj.QUADS);
obj.setVertices(info.verts);
obj.setIndices(info.indexes);
if (info.colors != null) {
obj.setColors(info.colors);
} else {
obj.setTextures(info.uv);
obj.setTextureID(mTextureID);
}
return obj;
}
/**
*
* @param group
* @param grid
* @param p
*/
public static void addBlock(MeshInfo group, SparseMatrix<Block> grid, Point3i p) {
Block b = grid.get(p);
if (b == null) {
return;
}
Point3f lower = new Point3f(p.x - .5f, p.y - .5f, p.z - .5f);
Point3f upper = new Point3f(p.x + .5f, p.y + .5f, p.z + .5f);
short[] colors = new short[]{b.getBlockID()};
List<JGLObj> objs = new ArrayList<>();
if (!grid.contains(p.x + 1, p.y, p.z)) {
addSelectFace(group, upper.x, lower.y, lower.z, upper.x, upper.y, upper.z,
RenderPoly.XP, colors[0 % colors.length]);
}
if (!grid.contains(p.x - 1, p.y, p.z)) {
addSelectFace(group, lower.x, lower.y, lower.z, lower.x, upper.y, upper.z,
RenderPoly.XM, colors[1 % colors.length]);
}
if (!grid.contains(p.x, p.y + 1, p.z)) {
addSelectFace(group, lower.x, upper.y, lower.z, upper.x, upper.y, upper.z,
RenderPoly.YP, colors[2 % colors.length]);
}
if (!grid.contains(p.x, p.y - 1, p.z)) {
addSelectFace(group, lower.x, lower.y, lower.z, upper.x, lower.y, upper.z,
RenderPoly.YM, colors[3 % colors.length]);
}
if (!grid.contains(p.x, p.y, p.z + 1)) {
addSelectFace(group, lower.x, lower.y, upper.z, upper.x, upper.y, upper.z,
RenderPoly.ZP, colors[4 % colors.length]);
}
if (!grid.contains(p.x, p.y, p.z - 1)) {
addSelectFace(group, lower.x, lower.y, lower.z, upper.x, upper.y, lower.z,
RenderPoly.ZM, colors[5 % colors.length]);
}
for (JGLObj obj : objs) {
obj.setData("point", p);
obj.setData("block", b);
}
}
/**
*
* @param group
* @param lower
* @param upper
* @param colors
*/
public static void addBox(MeshInfo group, Point3f lower, Point3f upper, short[] colors) {
if ((lower == null) || (upper == null)) {
return;
}
lower = new Point3f(lower.x - .5f, lower.y - .5f, lower.z - .5f);
upper = new Point3f(upper.x + .5f, upper.y + .5f, upper.z + .5f); // only place where bounds are at +1
addSelectFace(group, upper.x, lower.y, lower.z, upper.x, upper.y, upper.z,
RenderPoly.XP, colors[0 % colors.length]);
addSelectFace(group, lower.x, lower.y, lower.z, lower.x, upper.y, upper.z,
RenderPoly.XM, colors[1 % colors.length]);
addSelectFace(group, lower.x, upper.y, lower.z, upper.x, upper.y, upper.z,
RenderPoly.YP, colors[2 % colors.length]);
addSelectFace(group, lower.x, lower.y, lower.z, upper.x, lower.y, upper.z,
RenderPoly.YM, colors[3 % colors.length]);
addSelectFace(group, lower.x, lower.y, upper.z, upper.x, upper.y, upper.z,
RenderPoly.ZP, colors[4 % colors.length]);
addSelectFace(group, lower.x, lower.y, lower.z, upper.x, upper.y, lower.z,
RenderPoly.ZM, colors[5 % colors.length]);
}
/**
*
* @param group
* @param x1
* @param y1
* @param z1
* @param x2
* @param y2
* @param z2
* @param face
* @param type
*/
public static void addSelectFace(MeshInfo group, float x1, float y1, float z1, float x2, float y2, float z2,
int face, short type) {
if (MathUtils.epsilonEquals(x1, x2)) {
if (face == RenderPoly.XP) {
addSelectQuad(group, new Point3f(x1, y1, z1),
new Point3f(x1, y1, z2),
new Point3f(x1, y2, z2),
new Point3f(x1, y2, z1),
type);
} else {
addSelectQuad(group, new Point3f(x1, y1, z1),
new Point3f(x1, y2, z1),
new Point3f(x1, y2, z2),
new Point3f(x1, y1, z2),
type);
}
} else if (MathUtils.epsilonEquals(y1, y2)) {
if (face == RenderPoly.YP) {
addSelectQuad(group, new Point3f(x1, y1, z1),
new Point3f(x2, y1, z1),
new Point3f(x2, y1, z2),
new Point3f(x1, y1, z2),
type);
} else {
addSelectQuad(group, new Point3f(x1, y1, z1),
new Point3f(x1, y1, z2),
new Point3f(x2, y1, z2),
new Point3f(x2, y1, z1),
type);
}
} else if (MathUtils.epsilonEquals(z1, z2)) {
if (face == RenderPoly.ZP) {
addSelectQuad(group, new Point3f(x1, y1, z1),
new Point3f(x1, y2, z1),
new Point3f(x2, y2, z1),
new Point3f(x2, y1, z1),
type);
} else {
addSelectQuad(group, new Point3f(x1, y1, z1),
new Point3f(x2, y1, z1),
new Point3f(x2, y2, z1),
new Point3f(x1, y2, z1),
type);
}
}
}
/**
*
* @param info
* @param left
* @param top
* @param right
* @param bottom
* @param type
*/
public static void addSelectQuad(MeshInfo info, Point3f left, Point3f top, Point3f right, Point3f bottom,
short type) {
info.verts.add(left);
info.verts.add(top);
info.verts.add(right);
info.verts.add(bottom);
info.indexes.add(info.verts.size() - 1);
info.indexes.add(info.verts.size() - 2);
info.indexes.add(info.verts.size() - 3);
info.indexes.add(info.verts.size() - 4);
if (info.colors != null) {
Color c = BlockTypeColors.getFillColor(type);
Color3f color = new Color3f(c.getRed() / 255f, c.getGreen() / 255f, c.getBlue() / 255f);
info.colors.add(color);
info.colors.add(color);
info.colors.add(color);
info.colors.add(color);
}
if (info.uv != null) {
Rectangle2D.Float rec = BlockTypeColors.getAllTextureLocation(type);
info.uv.add(new Point2f(rec.x, rec.y));
info.uv.add(new Point2f(rec.x + rec.width, rec.y));
info.uv.add(new Point2f(rec.x + rec.width, rec.y + rec.height));
info.uv.add(new Point2f(rec.x, rec.y + rec.height));
}
}
}
class MeshInfo {
List<Point3f> verts;
List<Integer> indexes;
List<Color3f> colors;
List<Point2f> uv;
}