mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-13 17:37:58 -04:00
Render: support for BlockRotations
This commit is contained in:
parent
364f2736cb
commit
4c52ebab97
@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="Python" name="Python">
|
||||
<configuration sdkName="" />
|
||||
</facet>
|
||||
</component>
|
||||
</module>
|
12
pom.xml
12
pom.xml
@ -25,9 +25,15 @@
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<source>15</source>
|
||||
<target>15</target>
|
||||
<compilerArgs>--enable-preview</compilerArgs>
|
||||
<source>
|
||||
14
|
||||
</source>
|
||||
<target>
|
||||
14
|
||||
</target>
|
||||
<compilerArgs>
|
||||
--enable-preview
|
||||
</compilerArgs>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2020 Moritz Zwerger
|
||||
* Copyright (C) 2020 Lukas Eisenhauer
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
@ -13,88 +13,55 @@
|
||||
|
||||
package de.bixilon.minosoft.render.blockModels;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import de.bixilon.minosoft.data.mappings.blocks.Block;
|
||||
import de.bixilon.minosoft.data.mappings.blocks.BlockProperties;
|
||||
import de.bixilon.minosoft.data.mappings.blocks.BlockRotations;
|
||||
import de.bixilon.minosoft.data.mappings.blocks.Blocks;
|
||||
import de.bixilon.minosoft.data.world.BlockPosition;
|
||||
import de.bixilon.minosoft.logging.Log;
|
||||
import de.bixilon.minosoft.render.blockModels.Face.Axis;
|
||||
import de.bixilon.minosoft.render.blockModels.Face.FaceOrientation;
|
||||
import de.bixilon.minosoft.render.blockModels.subBlocks.SubBlock;
|
||||
import de.bixilon.minosoft.render.texture.TextureLoader;
|
||||
import org.apache.commons.collections.primitives.ArrayFloatList;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class BlockModel {
|
||||
private ArrayList<SubBlock> subBlocks;
|
||||
private boolean[] full; // minor memory improvement over a Map
|
||||
public class BlockModel implements BlockModelInterface {
|
||||
private final HashMap<HashSet<String>, HashSet<SubBlock>> stateMap;
|
||||
private final HashMap<HashSet<String>, boolean[]> full; // minor memory improvement over a Map FaceOrientation -> boolean and also performance should be boosted
|
||||
|
||||
public BlockModel(JsonObject block, JsonObject allModels) {
|
||||
subBlocks = load(block, allModels);
|
||||
}
|
||||
|
||||
public BlockModel(BlockModel blockModel, JsonObject json) {
|
||||
if (blockModel != null) {
|
||||
subBlocks = blockModel.getSubBlocks();
|
||||
} else {
|
||||
subBlocks = new ArrayList<>();
|
||||
}
|
||||
if (json.has("x")) {
|
||||
rotate(Axis.X, json.get("x").getAsInt());
|
||||
}
|
||||
if (json.has("y")) {
|
||||
rotate(Axis.Y, json.get("y").getAsInt());
|
||||
}
|
||||
if (json.has("z")) {
|
||||
rotate(Axis.Z, json.get("z").getAsInt());
|
||||
}
|
||||
full = createFullValues();
|
||||
}
|
||||
|
||||
private void rotate(Axis axis, int rotation) {
|
||||
for (SubBlock subBlock : subBlocks) {
|
||||
subBlock.rotate(axis, rotation);
|
||||
}
|
||||
}
|
||||
|
||||
public BlockModel() {
|
||||
}
|
||||
|
||||
static ArrayList<SubBlock> load(JsonObject json, JsonObject allModels, HashMap<String, String> variables) {
|
||||
ArrayList<SubBlock> result = new ArrayList<>();
|
||||
if (json.has("textures")) {
|
||||
// read the textures into a variable hashmap
|
||||
JsonObject textures = json.getAsJsonObject("textures");
|
||||
for (String texture : textures.keySet()) {
|
||||
if (texture.contains("#") && variables.containsKey(texture)) {
|
||||
variables.put("#" + texture, variables.get(texture));
|
||||
} else {
|
||||
variables.put("#" + texture, textures.get(texture).getAsString());
|
||||
public BlockModel(HashMap<String, HashSet<SubBlock>> blockModels, JsonArray states) {
|
||||
stateMap = new HashMap<>();
|
||||
full = new HashMap<>();
|
||||
for (JsonElement element : states) {
|
||||
JsonObject state = element.getAsJsonObject();
|
||||
HashSet<SubBlock> model = blockModels.get(state.get("model").getAsString()).stream().map(SubBlock::new).collect(Collectors.toCollection(HashSet::new));
|
||||
HashSet<String> properties = new HashSet<>();
|
||||
for (Map.Entry<String, JsonElement> property : state.getAsJsonObject("properties").entrySet()) {
|
||||
if (Blocks.getPropertiesMapping().containsKey(property.getKey())) {
|
||||
properties.add(Blocks.getPropertiesMapping().get(property.getKey()).get(property.getValue().getAsString()).name());
|
||||
} else if (Blocks.getRotationMapping().containsKey(property.getValue().getAsString())) {
|
||||
properties.add(Blocks.getRotationMapping().get(property.getValue().getAsString()).name());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (json.has("elements")) {
|
||||
for (JsonElement subBlockJson : json.get("elements").getAsJsonArray()) {
|
||||
result.add(new SubBlock(subBlockJson.getAsJsonObject(), variables));
|
||||
for (Axis axis : Axis.values()) {
|
||||
String lowercase = axis.name().toLowerCase();
|
||||
if (state.has(lowercase)) {
|
||||
BlockModelInterface.rotateModel(model, axis, state.get(lowercase).getAsInt());
|
||||
}
|
||||
}
|
||||
} else if (json.has("parent") && !json.get("parent").getAsString().equals("block/block")) {
|
||||
String parent = json.get("parent").getAsString();
|
||||
if (parent.equals("block/block")) {
|
||||
return result;
|
||||
}
|
||||
String parentIdentifier = parent.substring(parent.lastIndexOf("/") + 1);
|
||||
result.addAll(load(allModels.get(parentIdentifier).getAsJsonObject(), allModels, variables));
|
||||
stateMap.put(properties, model);
|
||||
full.put(properties, createFullValues(model));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static ArrayList<SubBlock> load(JsonObject json, JsonObject allModels) {
|
||||
return load(json, allModels, new HashMap<>());
|
||||
}
|
||||
|
||||
private boolean[] createFullValues() {
|
||||
private static boolean[] createFullValues(HashSet<SubBlock> subBlocks) {
|
||||
boolean[] result = new boolean[6];
|
||||
outer:
|
||||
for (FaceOrientation orientation : FaceOrientation.values()) {
|
||||
@ -108,41 +75,60 @@ public class BlockModel {
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean isFull(FaceOrientation orientation) {
|
||||
return full[orientation.getId()];
|
||||
private static HashSet<String> getProperties(Block block) {
|
||||
HashSet<String> result = new HashSet<>();
|
||||
if (block.getRotation() != BlockRotations.NONE) {
|
||||
result.add(block.getRotation().name());
|
||||
}
|
||||
for (BlockProperties property : block.getProperties()) {
|
||||
result.add(property.name());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean full(Block block, FaceOrientation orientation) {
|
||||
HashSet<String> properties = getProperties(block);
|
||||
for (Map.Entry<HashSet<String>, boolean[]> entry : full.entrySet()) {
|
||||
if (properties.containsAll(entry.getKey())) {
|
||||
return entry.getValue()[orientation.getId()];
|
||||
}
|
||||
}
|
||||
properties.add(BlockRotations.NONE.name());
|
||||
for (Map.Entry<HashSet<String>, boolean[]> entry : full.entrySet()) {
|
||||
if (properties.containsAll(entry.getKey())) {
|
||||
return entry.getValue()[orientation.getId()];
|
||||
}
|
||||
}
|
||||
Log.warn(String.format("could not find a corresponding block model for block %s", block.toString()));
|
||||
return false;
|
||||
}
|
||||
|
||||
public ArrayFloatList prepare(HashSet<FaceOrientation> facesToDraw, BlockPosition position, Block block) {
|
||||
ArrayFloatList result = new ArrayFloatList();
|
||||
for (SubBlock subBlock : subBlocks) {
|
||||
result.addAll(subBlock.getFaces(facesToDraw, position));
|
||||
HashSet<String> properties = getProperties(block);
|
||||
for (Map.Entry<HashSet<String>, HashSet<SubBlock>> entry : stateMap.entrySet()) {
|
||||
if (properties.containsAll(entry.getKey())) {
|
||||
ArrayFloatList result = new ArrayFloatList();
|
||||
for (SubBlock subBlock : entry.getValue()) {
|
||||
result.addAll(subBlock.getFaces(facesToDraw, position));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
properties.add(BlockRotations.NONE.name());
|
||||
for (Map.Entry<HashSet<String>, HashSet<SubBlock>> entry : stateMap.entrySet()) {
|
||||
if (properties.containsAll(entry.getKey())) {
|
||||
ArrayFloatList result = new ArrayFloatList();
|
||||
for (SubBlock subBlock : entry.getValue()) {
|
||||
result.addAll(subBlock.getFaces(facesToDraw, position));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
Log.warn(String.format("could not find a corresponding block model for block %s", block.toString()));
|
||||
return new ArrayFloatList();
|
||||
}
|
||||
|
||||
public boolean isFull() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public HashSet<String> getAllTextures() {
|
||||
HashSet<String> result = new HashSet<>();
|
||||
for (SubBlock subBlock : subBlocks) {
|
||||
result.addAll(subBlock.getTextures());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public void applyTextures(String mod, TextureLoader loader) {
|
||||
for (SubBlock subBlock : subBlocks) {
|
||||
subBlock.applyTextures(mod, loader);
|
||||
}
|
||||
}
|
||||
|
||||
public ArrayList<SubBlock> getSubBlocks() {
|
||||
return subBlocks;
|
||||
}
|
||||
|
||||
public boolean[] getFull() {
|
||||
return full;
|
||||
}
|
||||
}
|
||||
|
@ -1,52 +0,0 @@
|
||||
/*
|
||||
* 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.data.mappings.blocks.Block;
|
||||
import de.bixilon.minosoft.data.mappings.blocks.BlockRotations;
|
||||
|
||||
public class BlockModelBlockWrapper {
|
||||
Block block;
|
||||
|
||||
public BlockModelBlockWrapper(Block block) {
|
||||
this.block = block;
|
||||
}
|
||||
|
||||
public Block getBlock() {
|
||||
return block;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return block.getMod().hashCode() * block.getIdentifier().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (super.equals(obj)) {
|
||||
return true;
|
||||
}
|
||||
BlockModelBlockWrapper their = (BlockModelBlockWrapper) obj;
|
||||
if (block.equals(their.getBlock())) {
|
||||
return true;
|
||||
}
|
||||
if (!(block.getMod().equals(their.getBlock().getMod()) && block.getIdentifier().equals(their.getBlock().getIdentifier()))) {
|
||||
return false;
|
||||
}
|
||||
if (block.getRotation() == BlockRotations.NONE || their.getBlock().getRotation() == BlockRotations.NONE || block.getProperties().size() == 0 || their.getBlock().getProperties().size() == 0) {
|
||||
return true;
|
||||
}
|
||||
return block.getProperties().equals(their.getBlock().getProperties()) && block.getMod().equals(their.getBlock().getMod());
|
||||
}
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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 com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import de.bixilon.minosoft.data.mappings.blocks.Block;
|
||||
import de.bixilon.minosoft.data.world.BlockPosition;
|
||||
import de.bixilon.minosoft.render.blockModels.Face.Axis;
|
||||
import de.bixilon.minosoft.render.blockModels.Face.FaceOrientation;
|
||||
import de.bixilon.minosoft.render.blockModels.subBlocks.SubBlock;
|
||||
import org.apache.commons.collections.primitives.ArrayFloatList;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
||||
public interface BlockModelInterface {
|
||||
static HashSet<SubBlock> load(JsonObject block, JsonObject allModels, HashMap<String, String> variables) {
|
||||
HashSet<SubBlock> result = new HashSet<>();
|
||||
if (block.has("textures")) {
|
||||
// read the textures into a variable hashmap
|
||||
JsonObject textures = block.getAsJsonObject("textures");
|
||||
for (String texture : textures.keySet()) {
|
||||
if (texture.contains("#") && variables.containsKey(texture)) {
|
||||
variables.put("#" + texture, variables.get(texture));
|
||||
} else {
|
||||
variables.put("#" + texture, textures.get(texture).getAsString());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (block.has("elements")) {
|
||||
for (JsonElement subBlockJson : block.get("elements").getAsJsonArray()) {
|
||||
result.add(new SubBlock(subBlockJson.getAsJsonObject(), variables));
|
||||
}
|
||||
} else if (block.has("parent") && !block.get("parent").getAsString().equals("block/block")) {
|
||||
String parent = block.get("parent").getAsString();
|
||||
if (parent.equals("block/block")) {
|
||||
return result;
|
||||
}
|
||||
String parentIdentifier = parent.substring(parent.lastIndexOf("/") + 1);
|
||||
result.addAll(load(allModels.get(parentIdentifier).getAsJsonObject(), allModels, variables));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static HashSet<SubBlock> load(JsonObject json, JsonObject allModels) {
|
||||
return load(json, allModels, new HashMap<>());
|
||||
}
|
||||
|
||||
static void rotateModel(HashSet<SubBlock> subBlocks, Axis axis, int rotation) {
|
||||
for (SubBlock subBlock : subBlocks) {
|
||||
subBlock.rotate(axis, rotation);
|
||||
}
|
||||
}
|
||||
|
||||
boolean full(Block block, FaceOrientation orientation);
|
||||
|
||||
boolean isFull();
|
||||
|
||||
ArrayFloatList prepare(HashSet<FaceOrientation> facesToDraw, BlockPosition position, Block block);
|
||||
}
|
@ -20,6 +20,7 @@ import de.bixilon.minosoft.data.mappings.blocks.Block;
|
||||
import de.bixilon.minosoft.data.mappings.blocks.Blocks;
|
||||
import de.bixilon.minosoft.data.world.BlockPosition;
|
||||
import de.bixilon.minosoft.render.blockModels.Face.FaceOrientation;
|
||||
import de.bixilon.minosoft.render.blockModels.subBlocks.SubBlock;
|
||||
import de.bixilon.minosoft.render.texture.TextureLoader;
|
||||
import de.bixilon.minosoft.util.Util;
|
||||
import org.apache.commons.collections.primitives.ArrayFloatList;
|
||||
@ -29,14 +30,13 @@ import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
public class BlockModelLoader {
|
||||
HashMap<BlockModelBlockWrapper, BlockModel> blockMap;
|
||||
TextureLoader textureLoader;
|
||||
public static BlockModelLoader blockModelLoader;
|
||||
HashMap<String, HashMap<String, BlockModelInterface>> modelMap;
|
||||
|
||||
public BlockModelLoader() {
|
||||
blockMap = new HashMap<>();
|
||||
modelMap = new HashMap<>();
|
||||
HashSet<JsonObject> mods = new HashSet<>();
|
||||
HashMap<String, HashMap<String, float[]>> tints = new HashMap<>();
|
||||
try {
|
||||
@ -45,10 +45,14 @@ public class BlockModelLoader {
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
HashMap<String, HashMap<String, BlockModel>> blockModels = new HashMap<>();
|
||||
HashMap<String, HashMap<String, HashSet<SubBlock>>> blockModels = new HashMap<>();
|
||||
for (JsonObject mod : mods) {
|
||||
blockModels.put(mod.get("mod").getAsString(), loadModels(mod));
|
||||
tints.put(mod.get("mod").getAsString(), readTints(mod));
|
||||
String modName = mod.get("mod").getAsString();
|
||||
if (!modelMap.containsKey(mod.get("mod").getAsString())) {
|
||||
modelMap.put(modName, new HashMap<>());
|
||||
}
|
||||
blockModels.put(modName, loadModels(mod));
|
||||
tints.put(modName, readTints(mod));
|
||||
}
|
||||
textureLoader = new TextureLoader(getTextures(blockModels), tints);
|
||||
applyTextures(blockModels);
|
||||
@ -57,47 +61,46 @@ public class BlockModelLoader {
|
||||
}
|
||||
}
|
||||
|
||||
private void loadBlocks(JsonObject mod, HashMap<String, BlockModel> blockModels) {
|
||||
private void loadBlocks(JsonObject mod, HashMap<String, HashSet<SubBlock>> blockModels) {
|
||||
for (Map.Entry<String, JsonElement> blockEntry : mod.get("blockStates").getAsJsonObject().entrySet()) {
|
||||
JsonObject block = blockEntry.getValue().getAsJsonObject();
|
||||
if (block.has("states")) {
|
||||
JsonArray states = block.get("states").getAsJsonArray();
|
||||
for (JsonElement state : states) {
|
||||
BlockModel model = blockModels.get(state.getAsJsonObject().get("model").getAsString());
|
||||
Block wrapper = new Block(mod.get("mod").getAsString(), blockEntry.getKey(), state.getAsJsonObject().get("properties").getAsJsonObject());
|
||||
blockMap.put(new BlockModelBlockWrapper(wrapper), new BlockModel(model, state.getAsJsonObject()));
|
||||
}
|
||||
modelMap.get(mod.get("mod").getAsString()).put(blockEntry.getKey(), new BlockModel(blockModels, states));
|
||||
} else if (block.has("conditional")) {
|
||||
Block wrapper = new Block(mod.get("mod").getAsString(), blockEntry.getKey());
|
||||
blockMap.put(new BlockModelBlockWrapper(wrapper), new ConditionalModel(blockModels, block.get("conditional").getAsJsonArray()));
|
||||
modelMap.get(mod.get("mod").getAsString()).put(blockEntry.getKey(), new ConditionalModel(blockModels, block.get("conditional").getAsJsonArray()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private HashMap<String, BlockModel> loadModels(JsonObject mod) {
|
||||
HashMap<String, BlockModel> modMap = new HashMap<>();
|
||||
for (Map.Entry<String, JsonElement> block : mod.get("blockModels").getAsJsonObject().entrySet()) {
|
||||
modMap.put(block.getKey(), new BlockModel(block.getValue().getAsJsonObject(), mod.get("blockModels").getAsJsonObject()));
|
||||
private HashMap<String, HashSet<SubBlock>> loadModels(JsonObject mod) {
|
||||
HashMap<String, HashSet<SubBlock>> modMap = new HashMap<>();
|
||||
for (Map.Entry<String, JsonElement> block : mod.getAsJsonObject("blockModels").entrySet()) {
|
||||
modMap.put(block.getKey(), BlockModelInterface.load(block.getValue().getAsJsonObject(), mod.getAsJsonObject("blockModels")));
|
||||
}
|
||||
return modMap;
|
||||
}
|
||||
|
||||
public HashMap<String, HashSet<String>> getTextures(HashMap<String, HashMap<String, BlockModel>> blockModels) {
|
||||
public HashMap<String, HashSet<String>> getTextures(HashMap<String, HashMap<String, HashSet<SubBlock>>> blockModels) {
|
||||
HashMap<String, HashSet<String>> textures = new HashMap<>();
|
||||
for (Map.Entry<String, HashMap<String, BlockModel>> mod : blockModels.entrySet()) {
|
||||
for (Map.Entry<String, HashMap<String, HashSet<SubBlock>>> mod : blockModels.entrySet()) {
|
||||
HashSet<String> modTextures = new HashSet<>();
|
||||
for (BlockModel blockModel : mod.getValue().values()) {
|
||||
modTextures.addAll(blockModel.getAllTextures());
|
||||
for (HashSet<SubBlock> subBlocks : mod.getValue().values()) {
|
||||
for (SubBlock subBlock : subBlocks) {
|
||||
modTextures.addAll(subBlock.getTextures());
|
||||
}
|
||||
}
|
||||
textures.put(mod.getKey(), modTextures);
|
||||
}
|
||||
return textures;
|
||||
}
|
||||
|
||||
public void applyTextures(HashMap<String, HashMap<String, BlockModel>> blockModels) {
|
||||
for (Map.Entry<String, HashMap<String, BlockModel>> mod : blockModels.entrySet()) {
|
||||
for (Map.Entry<String, BlockModel> block : mod.getValue().entrySet()) {
|
||||
block.getValue().applyTextures(mod.getKey(), textureLoader);
|
||||
public void applyTextures(HashMap<String, HashMap<String, HashSet<SubBlock>>> blockModels) {
|
||||
for (Map.Entry<String, HashMap<String, HashSet<SubBlock>>> mod : blockModels.entrySet()) {
|
||||
for (Map.Entry<String, HashSet<SubBlock>> block : mod.getValue().entrySet()) {
|
||||
for (SubBlock subBlock : block.getValue()) {
|
||||
subBlock.applyTextures(mod.getKey(), textureLoader);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -118,19 +121,19 @@ public class BlockModelLoader {
|
||||
return result;
|
||||
}
|
||||
|
||||
public BlockModel getBlockModel(Block block) {
|
||||
BlockModel model = blockMap.get(new BlockModelBlockWrapper(block));
|
||||
public BlockModelInterface getBlockModel(Block block) {
|
||||
BlockModelInterface model = modelMap.get(block.getMod()).get(block.getIdentifier());
|
||||
if (model == null) {
|
||||
throw new RuntimeException("block " + block + " could not be found");
|
||||
}
|
||||
return blockMap.get(new BlockModelBlockWrapper(block));
|
||||
return model;
|
||||
}
|
||||
|
||||
public boolean isFull(Block block, FaceOrientation orientation) {
|
||||
if (block == null || block.equals(Blocks.nullBlock)) {
|
||||
return false;
|
||||
}
|
||||
return getBlockModel(block).isFull(orientation);
|
||||
return getBlockModel(block).full(block, orientation);
|
||||
}
|
||||
|
||||
public boolean isFull(Block block) {
|
||||
|
@ -19,16 +19,17 @@ import com.google.gson.JsonObject;
|
||||
import de.bixilon.minosoft.data.mappings.blocks.Block;
|
||||
import de.bixilon.minosoft.data.world.BlockPosition;
|
||||
import de.bixilon.minosoft.render.blockModels.Face.FaceOrientation;
|
||||
import de.bixilon.minosoft.render.blockModels.subBlocks.SubBlock;
|
||||
import org.apache.commons.collections.primitives.ArrayFloatList;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
|
||||
public class ConditionalModel extends BlockModel {
|
||||
HashMap<BlockCondition, BlockModel> conditionMap;
|
||||
public class ConditionalModel implements BlockModelInterface {
|
||||
HashMap<BlockCondition, HashSet<SubBlock>> conditionMap;
|
||||
|
||||
public ConditionalModel(HashMap<String, BlockModel> blockModels, JsonArray elements) {
|
||||
public ConditionalModel(HashMap<String, HashSet<SubBlock>> blockModels, JsonArray elements) {
|
||||
conditionMap = new HashMap<>();
|
||||
for (JsonElement element : elements) {
|
||||
JsonObject block = element.getAsJsonObject();
|
||||
@ -38,29 +39,31 @@ public class ConditionalModel extends BlockModel {
|
||||
} else {
|
||||
condition = BlockCondition.trueCondition;
|
||||
}
|
||||
BlockModel model = blockModels.get(block.get("model").getAsString());
|
||||
conditionMap.put(condition, new BlockModel(model, block));
|
||||
HashSet<SubBlock> model = blockModels.get(block.get("model").getAsString());
|
||||
conditionMap.put(condition, model);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayFloatList prepare(HashSet<FaceOrientation> facesToDraw, BlockPosition position, Block block) {
|
||||
ArrayFloatList result = new ArrayFloatList();
|
||||
for (Map.Entry<BlockCondition, BlockModel> entry : conditionMap.entrySet()) {
|
||||
for (Map.Entry<BlockCondition, HashSet<SubBlock>> entry : conditionMap.entrySet()) {
|
||||
if (entry.getKey().contains(block)) {
|
||||
result.addAll(entry.getValue().prepare(facesToDraw, position, block));
|
||||
for (SubBlock subBlock : entry.getValue()) {
|
||||
result.addAll(subBlock.getFaces(facesToDraw, position));
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFull() {
|
||||
public boolean full(Block block, FaceOrientation orientation) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFull(FaceOrientation orientation) {
|
||||
public boolean isFull() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
package de.bixilon.minosoft.render.blockModels.subBlocks;
|
||||
|
||||
// a 3d object with 8 corners, 6 faces and 12 edges (example: cube, but can be deformed)
|
||||
// a 3d object with 8 corners, 6 faces and 12 edges (cube, but can be deformed)
|
||||
|
||||
import de.bixilon.minosoft.render.blockModels.Face.Axis;
|
||||
import de.bixilon.minosoft.render.blockModels.Face.FaceOrientation;
|
||||
@ -47,6 +47,13 @@ public class Cuboid {
|
||||
}
|
||||
}
|
||||
|
||||
public Cuboid(Cuboid cuboid) {
|
||||
positions = new SubBlockPosition[cuboid.positions.length];
|
||||
for (int i = 0; i < positions.length; i++) {
|
||||
positions[i] = new SubBlockPosition(cuboid.positions[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public SubBlockPosition[] getFacePositions(FaceOrientation orientation) {
|
||||
int[] positionIds = facePositionMapTemplate[orientation.getId()];
|
||||
SubBlockPosition[] result = new SubBlockPosition[positionIds.length];
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2020 Moritz Zwerger
|
||||
* Copyright (C) 2020 Lukas Eisenhauer
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
@ -27,7 +27,7 @@ import java.util.Map;
|
||||
|
||||
public class SubBlock {
|
||||
private final HashMap<FaceOrientation, Float> textureCoordinates;
|
||||
private final HashMap<FaceOrientation, String> textures;
|
||||
private HashMap<FaceOrientation, String> textures;
|
||||
private final HashMap<FaceOrientation, Integer> textureRotations;
|
||||
private final boolean[] full;
|
||||
private final HashMap<FaceOrientation, InFaceUV> uv;
|
||||
@ -56,6 +56,14 @@ public class SubBlock {
|
||||
full = createFull();
|
||||
}
|
||||
|
||||
public SubBlock(SubBlock subBlock) {
|
||||
textureCoordinates = subBlock.textureCoordinates;
|
||||
textureRotations = subBlock.textureRotations;
|
||||
uv = subBlock.uv;
|
||||
cuboid = new Cuboid(subBlock.cuboid);
|
||||
full = createFull();
|
||||
}
|
||||
|
||||
private static String getRealTextureName(String textureName, HashMap<String, String> variables) {
|
||||
// read the variables and find the real texture name
|
||||
if (textureName.contains("#")) {
|
||||
|
@ -41,6 +41,10 @@ public class SubBlockPosition {
|
||||
this.vector = vector;
|
||||
}
|
||||
|
||||
public SubBlockPosition(SubBlockPosition position) {
|
||||
vector = new Vec3(position.vector);
|
||||
}
|
||||
|
||||
public SubBlockPosition rotated(Axis axis, int rotation) {
|
||||
return new SubBlockRotation(middlePos, axis, rotation).apply(this);
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2020 Moritz Zwerger
|
||||
* Copyright (C) 2020 Lukas Eisenhauer
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
@ -16,73 +16,52 @@ package de.bixilon.minosoft.render.blockModels.subBlocks;
|
||||
import com.google.gson.JsonObject;
|
||||
import de.bixilon.minosoft.render.blockModels.Face.Axis;
|
||||
import de.bixilon.minosoft.render.utility.Vec3;
|
||||
|
||||
import javafx.util.Pair;
|
||||
|
||||
public class SubBlockRotation {
|
||||
private final Vec3 origin;
|
||||
private final double angle;
|
||||
private final Vec3 direction;
|
||||
private final Axis axis;
|
||||
private final double sin;
|
||||
private final double cos;
|
||||
|
||||
public SubBlockRotation(SubBlockPosition origin, Axis direction, float angle) {
|
||||
public SubBlockRotation(SubBlockPosition origin, Axis axis, float angle) {
|
||||
this.origin = origin.getVector();
|
||||
this.direction = switch (direction) {
|
||||
case X -> new Vec3(1, 0, 0);
|
||||
case Y -> new Vec3(0, 1, 0);
|
||||
case Z -> new Vec3(0, 0, 1);
|
||||
};
|
||||
this.angle = angle;
|
||||
this.axis = axis;
|
||||
double angleRad = Math.toRadians(angle);
|
||||
sin = Math.sin(angleRad);
|
||||
cos = Math.cos(angleRad);
|
||||
}
|
||||
|
||||
public SubBlockRotation(JsonObject rotation) {
|
||||
origin = new SubBlockPosition(rotation.get("origin").getAsJsonArray()).getVector();
|
||||
String axis = rotation.get("axis").getAsString();
|
||||
direction = switch (axis) {
|
||||
case "x" -> new Vec3(1, 0, 0);
|
||||
case "y" -> new Vec3(0, 1, 0);
|
||||
case "z" -> new Vec3(0, 0, 1);
|
||||
default -> throw new IllegalStateException("Unexpected value: " + axis);
|
||||
String direction = rotation.get("axis").getAsString();
|
||||
axis = switch (direction) {
|
||||
case "x" -> Axis.X;
|
||||
case "y" -> Axis.Y;
|
||||
case "z" -> Axis.Z;
|
||||
default -> throw new IllegalStateException("Unexpected value: " + direction);
|
||||
};
|
||||
angle = Math.toRadians(rotation.get("angle").getAsFloat());
|
||||
double angleRad = Math.toRadians(rotation.get("angle").getAsDouble());
|
||||
sin = Math.sin(angleRad);
|
||||
cos = Math.cos(angleRad);
|
||||
}
|
||||
|
||||
public SubBlockPosition apply(SubBlockPosition position) {
|
||||
Vec3 transformed = Vec3.add(position.getVector(), Vec3.mul(origin, -1));
|
||||
|
||||
Vec3 result = Vec3.mul(transformed, Math.cos(angle));
|
||||
result.add(Vec3.mul(Vec3.cross(direction, transformed), Math.sin(angle)));
|
||||
//result.add(Vec3.mul(direction, direction, transformed, ));
|
||||
return new SubBlockPosition(Vec3.add(transformed, origin));
|
||||
}
|
||||
|
||||
/*
|
||||
public static Pair<Float, Float> rotate(float x, float y, float angle) {
|
||||
float angleRad = (float) Math.toRadians(angle);
|
||||
float newX = x * (float) StrictMath.cos(angleRad) + y * (float) StrictMath.sin(angleRad);
|
||||
float newY = - x * (float) StrictMath.sin(angleRad) + y * (float) StrictMath.cos(angleRad);
|
||||
private Pair<Double, Double> rotate(double x, double y) {
|
||||
double newX = x * cos - y * sin;
|
||||
double newY = x * sin + y * cos;
|
||||
return new Pair<>(newX, newY);
|
||||
}
|
||||
|
||||
|
||||
public SubBlockPosition apply(SubBlockPosition position) {
|
||||
SubBlockPosition transformed = SubBlockPosition.subtract(position, origin);
|
||||
Pair<Float, Float> rotated;
|
||||
switch (direction) {
|
||||
case X -> {
|
||||
rotated = rotate(transformed.y, transformed.z, angle);
|
||||
transformed.y = rotated.getKey();
|
||||
transformed.z = rotated.getValue();
|
||||
}
|
||||
case Y -> {
|
||||
rotated = rotate(transformed.x, transformed.z, angle);
|
||||
transformed.x = rotated.getKey();
|
||||
transformed.z = rotated.getValue();
|
||||
}
|
||||
case Z -> {
|
||||
rotated = rotate(transformed.x, transformed.y, angle);
|
||||
transformed.x = rotated.getKey();
|
||||
transformed.y = rotated.getValue();
|
||||
}
|
||||
}
|
||||
return SubBlockPosition.add(transformed, origin);
|
||||
Vec3 transformedPosition = Vec3.add(position.getVector(), Vec3.mul(origin, -1));
|
||||
return switch (axis) {
|
||||
case X:
|
||||
Pair<Double, Double> rotateX = rotate(transformedPosition.y, transformedPosition.z); transformedPosition.y = rotateX.getKey(); transformedPosition.z = rotateX.getValue(); yield new SubBlockPosition(Vec3.add(transformedPosition, origin));
|
||||
case Y:
|
||||
Pair<Double, Double> rotateY = rotate(transformedPosition.x, transformedPosition.z); transformedPosition.x = rotateY.getKey(); transformedPosition.z = rotateY.getValue(); yield new SubBlockPosition(Vec3.add(transformedPosition, origin));
|
||||
case Z:
|
||||
Pair<Double, Double> rotateZ = rotate(transformedPosition.x, transformedPosition.y); transformedPosition.x = rotateZ.getKey(); transformedPosition.y = rotateZ.getValue(); yield new SubBlockPosition(Vec3.add(transformedPosition, origin));
|
||||
};
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
@ -64,6 +64,7 @@ public class PlayerController {
|
||||
applyVelocity(deltaTime);
|
||||
|
||||
if (gameMode == GameModes.SPECTATOR) {
|
||||
glTranslated(-playerPos.x, -(playerPos.y + playerHeight - 0.2f), -playerPos.z);
|
||||
return;
|
||||
}
|
||||
handleCollisions(connection.getPlayer().getWorld());
|
||||
|
@ -35,6 +35,12 @@ public class Vec3 {
|
||||
z = (float) location.getZ();
|
||||
}
|
||||
|
||||
public Vec3(Vec3 vector) {
|
||||
x = vector.x;
|
||||
y = vector.y;
|
||||
z = vector.z;
|
||||
}
|
||||
|
||||
public static Vec3 add(Vec3... vectors) {
|
||||
Vec3 result = new Vec3(0, 0, 0);
|
||||
for (Vec3 vector : vectors) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user