new block rendering system wip 1

This commit is contained in:
Lukas 2020-07-29 18:15:12 +02:00
parent 4046b39d8e
commit c3faa0e9e3
8 changed files with 211 additions and 75 deletions

View File

@ -18,28 +18,26 @@ import de.bixilon.minosoft.game.datatypes.objectLoader.blocks.Blocks;
import de.bixilon.minosoft.game.datatypes.world.*;
import de.bixilon.minosoft.logging.Log;
import de.bixilon.minosoft.render.blockModels.BlockModelLoader;
import de.bixilon.minosoft.render.blockModels.Face;
import de.bixilon.minosoft.render.fullFace.FaceOrientation;
import de.bixilon.minosoft.render.fullFace.FullFacePosition;
import de.bixilon.minosoft.render.fullFace.RenderConstants;
import de.bixilon.minosoft.render.texture.TextureLoader;
import javafx.util.Pair;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import static de.bixilon.minosoft.render.fullFace.RenderConstants.UV;
import static de.bixilon.minosoft.render.fullFace.RenderConstants.faceDir;
import static org.lwjgl.opengl.GL11.*;
public class WorldRenderer {
private final TextureLoader textureLoader;
private final HashMap<FullFacePosition, Pair<Float, Float>> faces;
private final HashMap<BlockPosition, HashSet<Face>> faces;
private final int faceCount = 0;
private BlockModelLoader modelLoader;
public WorldRenderer() {
textureLoader = new TextureLoader(MainWindow.getOpenGLWindow().getWindow());
faces = new HashMap<FullFacePosition, Pair<Float, Float>>();
faces = new HashMap<>();
}
public void init() {
@ -67,67 +65,34 @@ public class WorldRenderer {
}
public void prepareBlock(BlockPosition position, Block block) {
if (block == Blocks.nullBlock)
return;
if (block.equals(Blocks.nullBlock))
faces.put(position, null);
HashMap<FaceOrientation, Boolean> adjacentBlocks = new HashMap<>();
for (FaceOrientation orientation : FaceOrientation.values()) {
BlockPosition neighbourPos = position.add(faceDir[orientation.getId()]);
if (neighbourPos.getY() >= 0) {
Block neighbourBlock = MainWindow.getConnection().getPlayer().getWorld().getBlock(neighbourPos);
if (!(neighbourBlock == Blocks.nullBlock || neighbourBlock == null)) //!modelLoader.isFull(neighbourBlock))
// if there is a block next to the current block, don't draw the face
continue;
//TODO: fix buggy behavior, not always working correctly, probably a problem in the World or BlockPosition class
boolean isNeighbourFull = modelLoader.isFull(neighbourBlock);
adjacentBlocks.put(orientation, isNeighbourFull);
} else {
adjacentBlocks.put(orientation, false);
}
/*
FullFacePosition facePosition = new FullFacePosition(position, orientation);
Pair<Float, Float> texture = modelLoader.getBlockDescription(block).getTexture(orientation);
if (!faces.containsKey(facePosition)) {
synchronized (faces) {
faces.put(facePosition, texture);
}
}
*/
}
synchronized (faces) {
faces.put(position, modelLoader.getBlockDescription(block).prepare(adjacentBlocks));
}
}
public void draw() {
glPushMatrix();
/*
glBindBuffer(GL_ARRAY_BUFFER, vbo);
float[] floatArray = vertices.toArray();
glBufferData(GL_ARRAY_BUFFER,
(FloatBuffer) BufferUtils.createFloatBuffer(vertices.size()).put(
floatArray).flip(), GL_STATIC_DRAW);
glBindTexture(GL_TEXTURE_2D, textureLoader.getTextureID());
glVertexPointer(3, GL_FLOAT, 28, 0L);
glTexCoordPointer(2, GL_FLOAT,28, 0L);
glDrawArrays(GL_QUADS, 0, floatArray.length);
*/
glBindTexture(GL_TEXTURE_2D, textureLoader.getTextureID());
glBegin(GL_QUADS);
synchronized (faces) {
for (Map.Entry<FullFacePosition, Pair<Float, Float>> entry : faces.entrySet()) {
float[][] vertPositions = RenderConstants.FACE_VERTEX[entry.getKey().getFaceOrientation().getId()];
for (int vert = 0; vert < 4; vert++) {
float u = 0;
switch (UV[vert][0]) {
case 0:
u = entry.getValue().getKey();
break;
case 1:
u = entry.getValue().getValue();
break;
}
float x = vertPositions[vert][0] + entry.getKey().getBlockPosition().getX();
float y = vertPositions[vert][1] + entry.getKey().getBlockPosition().getY();
float z = vertPositions[vert][2] + entry.getKey().getBlockPosition().getZ();
glTexCoord2f(u, UV[vert][1]);
glVertex3f(x, y, z);
for (Map.Entry<BlockPosition, HashSet<Face>> entry : faces.entrySet()) {
for (Face face : entry.getValue()) {
face.draw(entry.getKey());
}
}
}

View File

@ -16,6 +16,7 @@ package de.bixilon.minosoft.render.blockModels;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import de.bixilon.minosoft.Config;
import de.bixilon.minosoft.render.fullFace.FaceOrientation;
import java.io.IOException;
import java.util.HashMap;
@ -68,4 +69,12 @@ public class BlockDescription {
public boolean isFull() {
return isFull;
}
public HashSet<Face> prepare(HashMap<FaceOrientation, Boolean> adjacentBlocks) {
HashSet<Face> result = new HashSet<>();
for (SubBlock subBlock : subBlocks) {
result.addAll(subBlock.getFaces(adjacentBlocks));
}
return result;
}
}

View File

@ -368,6 +368,7 @@ public class BlockModelLoader {
String path = Config.homeDir + "assets/" + mod + "/models/block/" + identifier + ".json";
JsonObject json = readJsonFromFile(path);
BlockDescription description = new BlockDescription(json);
blockDescriptionMap.put(mod + ":" + identifier, description);
//Log.info("Loaded model for " + mod + ":" + identifier);
} catch (IOException e) {
Log.debug("could not load block model for block " + mod + ":" + identifier);
@ -380,8 +381,10 @@ public class BlockModelLoader {
}
public BlockDescription getBlockDescription(Block block) {
if (!blockDescriptionMap.containsKey(block)) {
throw new IllegalArgumentException(String.format("No description for block %s found", block));
String blockName = block.getMod() + ":" + block.getIdentifier();
if (!blockDescriptionMap.containsKey(blockName)) {
System.out.println(String.format("No description for block %s found", blockName));
System.exit(-1);
}
return blockDescriptionMap.get(block.getMod() + ":" + block.getIdentifier());
}

View File

@ -0,0 +1,137 @@
/*
* Codename Minosoft
* Copyright (C) 2020 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.render.blockModels;
import de.bixilon.minosoft.game.datatypes.world.BlockPosition;
import de.bixilon.minosoft.render.MainWindow;
import de.bixilon.minosoft.render.fullFace.FaceOrientation;
import de.bixilon.minosoft.render.fullFace.InFaceUV;
import javafx.util.Pair;
import static de.bixilon.minosoft.render.fullFace.RenderConstants.blockRes;
import static de.bixilon.minosoft.render.fullFace.RenderConstants.texturePackRes;
import static org.lwjgl.opengl.GL11.glTexCoord2f;
import static org.lwjgl.opengl.GL11.glVertex3f;
public class Face {
FaceOrientation orientation;
Pair<Float, Float> texture;
InFaceUV uv;
SubBlock subBlock;
public Face(FaceOrientation orientation, Pair<Float, Float> texture, InFaceUV uv, SubBlock subBlock) {
this.orientation = orientation;
this.texture = texture;
this.uv = uv;
this.subBlock = subBlock;
}
public void draw(BlockPosition pos) {
float x1 = 0, y1 = 0, z1 = 0, x2 = 0, y2 = 0, z2 = 0;
float step = MainWindow.getRenderer().getTextureLoader().getStep();
float u1 = texture.getKey() + (float) uv.u1 / (float) blockRes * step;
float u2 = texture.getValue() + (float) uv.u1 / (float) blockRes * step;
float v1 = (float) uv.v1 / (float) texturePackRes;
float v2 = (float) uv.v2 / (float) texturePackRes;
switch (orientation) {
case EAST:
x1 = x2 = subBlock.pos2.x;
y1 = subBlock.pos1.y;
y2 = subBlock.pos2.y;
z1 = subBlock.pos1.z;
z2 = subBlock.pos2.z;
break;
case WEST:
x1 = x2 = subBlock.pos1.x;
y1 = subBlock.pos1.y;
y2 = subBlock.pos2.y;
z1 = subBlock.pos1.z;
z2 = subBlock.pos2.z;
break;
case UP:
y1 = y2 = subBlock.pos2.y;
x1 = subBlock.pos1.x;
x2 = subBlock.pos2.x;
z1 = subBlock.pos1.z;
z2 = subBlock.pos2.z;
break;
case DOWN:
y1 = y2 = subBlock.pos1.y;
x1 = subBlock.pos1.x;
x2 = subBlock.pos2.x;
z1 = subBlock.pos1.z;
z2 = subBlock.pos2.z;
break;
case SOUTH:
z1 = z2 = subBlock.pos2.z;
x1 = subBlock.pos1.x;
x2 = subBlock.pos2.x;
y1 = subBlock.pos1.y;
y2 = subBlock.pos2.y;
break;
case NORTH:
z1 = z2 = subBlock.pos1.z;
x1 = subBlock.pos1.x;
x2 = subBlock.pos2.x;
y1 = subBlock.pos1.y;
y2 = subBlock.pos2.y;
break;
}
switch (orientation) {
case EAST:
case WEST:
glTexCoord2f(u1, v1);
glVertex3f(x1, y1, z1);
glTexCoord2f(u2, v1);
glVertex3f(x1, y2, z1);
glTexCoord2f(u2, v2);
glVertex3f(x1, y2, z2);
glTexCoord2f(u2, v2);
glVertex3f(x1, y2, z2);
break;
case UP:
case DOWN:
glTexCoord2f(u1, v1);
glVertex3f(x1, y1, z1);
glTexCoord2f(u2, v1);
glVertex3f(x2, y1, z1);
glTexCoord2f(u2, v2);
glVertex3f(x2, y1, z2);
glTexCoord2f(u2, v2);
glVertex3f(x1, y1, z2);
break;
case NORTH:
case SOUTH:
glTexCoord2f(u1, v1);
glVertex3f(x1, y1, z1);
glTexCoord2f(u2, v1);
glVertex3f(x2, y1, z1);
glTexCoord2f(u2, v2);
glVertex3f(x2, y2, z1);
glTexCoord2f(u2, v2);
glVertex3f(x1, y2, z1);
break;
}
}
}

View File

@ -20,13 +20,14 @@ import de.bixilon.minosoft.render.fullFace.InFaceUV;
import javafx.util.Pair;
import java.util.HashMap;
import java.util.HashSet;
public class SubBlock {
SubBlockPosition pos1; // the most negative Point of the SubBlock
SubBlockPosition pos2; // the most positive Point of the SubBlock
HashMap<FaceOrientation, Pair<Float, Float>> textures;
HashMap<FaceOrientation, Pair<Float, Float>> cullFaceTextures;
HashMap<FaceOrientation, Boolean> cullFaceTextures;
HashMap<FaceOrientation, InFaceUV> uv;
@ -46,24 +47,7 @@ public class SubBlock {
}
}
private void applyTexture(JsonObject faceJson, FaceOrientation orientation, HashMap<String, String> variables) {
try {
uv.put(orientation, new InFaceUV(faceJson.getAsJsonArray("uv")));
} catch (Exception e) {
uv.put(orientation, new InFaceUV());
}
String textureName = getRealTextureName(faceJson.get("texture").getAsString(), variables);
Pair<Float, Float> texture = MainWindow.getRenderer().getTextureLoader().getTexture(textureName);
if (faceJson.has("cullface")) {
cullFaceTextures.put(orientation, texture);
} else {
textures.put(orientation, texture);
}
}
private String getRealTextureName(String textureName, HashMap<String, String> variables) {
private static String getRealTextureName(String textureName, HashMap<String, String> variables) {
if (textureName.contains("#")) {
if (variables.containsKey(textureName)) {
String newName = variables.get(textureName);
@ -81,4 +65,33 @@ public class SubBlock {
return textureName;
}
}
private void applyTexture(JsonObject faceJson, FaceOrientation orientation, HashMap<String, String> variables) {
try {
uv.put(orientation, new InFaceUV(faceJson.getAsJsonArray("uv")));
} catch (Exception e) {
uv.put(orientation, new InFaceUV());
}
String textureName = getRealTextureName(faceJson.get("texture").getAsString(), variables);
Pair<Float, Float> texture = MainWindow.getRenderer().getTextureLoader().getTexture(textureName);
cullFaceTextures.put(orientation, faceJson.has("cullface"));
textures.put(orientation, texture);
}
public HashSet<Face> getFaces(HashMap<FaceOrientation, Boolean> adjacentBlocks) {
HashSet<Face> result = new HashSet<>();
for (FaceOrientation orientation : FaceOrientation.values()) {
if (!textures.containsKey(orientation)) {
continue;
}
if (!(adjacentBlocks.get(orientation) && cullFaceTextures.get(orientation))) {
result.add(new Face(orientation, textures.get(orientation),
uv.get(orientation), this));
}
}
return result;
}
}

View File

@ -16,7 +16,7 @@ package de.bixilon.minosoft.render.fullFace;
import com.google.gson.JsonArray;
public class InFaceUV {
int u1, v1, u2, v2;
public int u1, v1, u2, v2;
public InFaceUV(JsonArray json) {
u1 = json.get(0).getAsInt();

View File

@ -14,7 +14,10 @@
package de.bixilon.minosoft.render.fullFace;
public class RenderConstants {
//TODO: fix rotated faces
public static final int texturePackRes = 16;
public static final int blockRes = 16;
public static final float[][][] FACE_VERTEX = new float[][][]{
{
{1, 0, 0},

View File

@ -38,6 +38,7 @@ public class TextureLoader {
private final int TEXTURE_PACK_RES = 16;
private HashMap<String, Integer> textureCoordinates;
int imageLength = 1;
float step;
public TextureLoader(long window) {
try {
@ -143,6 +144,7 @@ public class TextureLoader {
} catch (IOException e) {
e.printStackTrace();
}
step = (float) 1 / (float) imageLength;
}
private int bindTexture(ByteBuffer buf, int width, int height) {
@ -183,4 +185,8 @@ public class TextureLoader {
public int getTextureID() {
return textureID;
}
public float getStep() {
return step;
}
}