/******************************************************************************* * Copyright 2015 Maximilian Stark | Dakror <mail@dakror.de> * * 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 de.dakror.vloxlands.game.voxel; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.Mesh; import com.badlogic.gdx.graphics.VertexAttribute; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.math.Vector3; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.FloatArray; import com.badlogic.gdx.utils.ObjectMap; import de.dakror.vloxlands.render.TextureFace; import de.dakror.vloxlands.util.CSVReader; import de.dakror.vloxlands.util.Direction; public class Voxel { public static enum Categories { classpath, id, textureX, textureY, name, opaque, weight, uplift, brightness, mining, itemdrop, tool, custom, } static short[] indices; static FloatArray verts = new FloatArray(); public static final int VOXELS = 256; public static final float TEXSIZE = 16 / 512f; private static ObjectMap<String, Voxel> voxels = new ObjectMap<String, Voxel>(); private static Voxel[] voxelList = new Voxel[VOXELS]; String name = "NA"; String custom; Class<?> tool; boolean opaque = true; boolean replaceable = false; float smoothness = 0; byte id; float weight = 1f; float uplift = 0; float brightness; int textureX; int textureY; int mining; byte itemdrop; Mesh mesh; public void registerVoxel(int id) { if (voxelList[id + 128] == null) voxelList[id + 128] = this; else { Gdx.app.error("Voxel.registerVoxel", "The ID " + id + " was already taken up by \"" + voxelList[id + 128].name + "\""); Gdx.app.exit(); } this.id = (byte) id; } public static Voxel getForId(byte id) { return voxelList[id + 128]; } public synchronized static Voxel getForId(int id) { return voxelList[id]; } public Mesh getMesh() { return mesh; } public boolean isReplaceable() { return false; } public String getName() { return name; } public Class<?> getTool() { return tool; } protected Vector2 getTexCoord(int x, int y, int z, Direction d) { return new Vector2(textureX, textureY); } public Vector2 getTextureUV(int x, int y, int z, Direction d) { return getTexCoord(x, y, z, d).cpy().scl(TEXSIZE); } public boolean isOpaque() { return opaque; } public float getSmoothness() { return smoothness; } public byte getId() { return id; } public float getWeight() { return weight; } public float getUplift() { return uplift; } public float getBrightness() { return brightness; } public String getCustom() { return custom; } public int getMining() { return mining; } public byte getItemdrop() { if (itemdrop == 127) return id; return itemdrop; } @Override public String toString() { return getClass().getName() + "." + name.toUpperCase().replace(" ", "_"); } public boolean hasItemdrop() { return itemdrop != (byte) 0; } public static int getIdForName(String name) { for (int i = 0; i < voxelList.length; i++) { Voxel v = Voxel.getForId(i); if (v.getName().equals(name)) return i; } Gdx.app.error("Voxel.getIdForName", name + " not found"); return -1; } public static Voxel get(String name) { return voxels.get(name); } public static Array<Voxel> getAll() { return voxels.values().toArray(); } public static void loadVoxels() { CSVReader csv = new CSVReader(Gdx.files.internal("data/voxels.csv")); String[] categories = csv.readRow(); String[] defaults = csv.readRow(); String cell; Voxel voxel = null; while ((cell = csv.readNext()) != null) { if (csv.getIndex() == 0) { try { if (cell.length() > 0) voxel = (Voxel) Class.forName("de.dakror.vloxlands.game.voxel." + cell).newInstance(); else voxel = new Voxel(); } catch (Exception e) { e.printStackTrace(); } } Categories c = Categories.valueOf(categories[csv.getIndex()]); switch (c) { case classpath: break; case id: { voxel.registerVoxel(Integer.valueOf(cell) - 128); break; } case textureX: { if (cell.length() > 0) voxel.textureX = Integer.parseInt(cell); else voxel.textureX = Integer.parseInt(defaults[csv.getIndex()]); break; } case textureY: { if (cell.length() > 0) voxel.textureY = Integer.parseInt(cell); else voxel.textureY = Integer.parseInt(defaults[csv.getIndex()]); break; } case name: { if (cell.length() > 0) voxel.name = cell; else voxel.name = defaults[csv.getIndex()]; voxels.put(voxel.getName().toUpperCase().replace(" ", "_"), voxel); break; } case opaque: { if (cell.length() > 0) voxel.opaque = cell.equals("1"); else voxel.opaque = defaults[csv.getIndex()].equals("1"); break; } case weight: { if (cell.length() > 0) voxel.weight = Float.parseFloat(cell); else voxel.weight = Float.parseFloat(defaults[csv.getIndex()]); break; } case uplift: { if (cell.length() > 0) voxel.uplift = Float.parseFloat(cell); else voxel.uplift = Float.parseFloat(defaults[csv.getIndex()]); break; } case brightness: { if (cell.length() > 0) voxel.brightness = Float.parseFloat(cell); else voxel.brightness = Float.parseFloat(defaults[csv.getIndex()]); break; } case mining: { if (cell.length() > 0) voxel.mining = Integer.parseInt(cell); else voxel.mining = Integer.parseInt(defaults[csv.getIndex()]); break; } case itemdrop: { if (cell.length() > 0) voxel.itemdrop = (byte) (Integer.parseInt(cell) - 128); else voxel.itemdrop = (byte) (Integer.parseInt(defaults[csv.getIndex()]) - 128); break; } case tool: { if (cell.length() > 0) { try { voxel.tool = Class.forName("de.dakror.vloxlands.game.item.tool." + cell); } catch (ClassNotFoundException e) { e.printStackTrace(); } } else voxel.tool = null; break; } case custom: { if (cell.length() > 0) voxel.custom = cell; else voxel.custom = null; break; } default: Gdx.app.log("Voxel.loadVoxels", "Unhandled voxel data column: " + c); break; } } voxels.put(voxel.getName().toUpperCase().replace(" ", "_"), voxel); Gdx.app.log("Voxel.loadVoxels", voxels.size + " voxels loaded."); } public static void buildMeshes() { if (indices == null) { int len = 3 * 6 * 6 / 3; indices = new short[len]; short j = 0; for (int i = 0; i < len; i += 6, j += 4) { indices[i + 0] = (short) (j + 0); indices[i + 1] = (short) (j + 1); indices[i + 2] = (short) (j + 2); indices[i + 3] = (short) (j + 2); indices[i + 4] = (short) (j + 3); indices[i + 5] = (short) (j + 0); } } for (Voxel v : voxels.values()) { v.mesh = new Mesh(true, 24, indices.length, VertexAttribute.Position(), VertexAttribute.Normal(), VertexAttribute.ColorPacked(), VertexAttribute.TexCoords(0), VertexAttribute.TexCoords(1)); v.mesh.setIndices(indices); verts = new FloatArray(); for (Direction d : Direction.values()) new TextureFace(d, new Vector3(), v.getTextureUV(0, 0, 0, d)).getVertexData(verts); v.mesh.setVertices(verts.items, 0, verts.size); } } public static String capitalizeFirstLetter(String string) { return string.substring(0, 1).toUpperCase() + string.substring(1); } }