mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-17 03:15:35 -04:00
new block rendering system wip 1
This commit is contained in:
parent
4046b39d8e
commit
c3faa0e9e3
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
137
src/main/java/de/bixilon/minosoft/render/blockModels/Face.java
Normal file
137
src/main/java/de/bixilon/minosoft/render/blockModels/Face.java
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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},
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user