108 lines
6.1 KiB
Java
108 lines
6.1 KiB
Java
import eu.mhsl.minecraft.pixelpics.assets.*;
|
|
import eu.mhsl.minecraft.pixelpics.render.entity.*;
|
|
import eu.mhsl.minecraft.pixelpics.render.render.*;
|
|
import eu.mhsl.minecraft.pixelpics.render.sky.SkyContext;
|
|
import eu.mhsl.minecraft.pixelpics.render.snapshot.WorldSnapshot;
|
|
import eu.mhsl.minecraft.pixelpics.render.tint.BiomeTintProvider;
|
|
import org.bukkit.Location;
|
|
import org.bukkit.Material;
|
|
import org.bukkit.block.data.BlockData;
|
|
import org.bukkit.util.Vector;
|
|
|
|
import javax.imageio.ImageIO;
|
|
import java.awt.image.BufferedImage;
|
|
import java.io.File;
|
|
import java.lang.reflect.Proxy;
|
|
import java.util.*;
|
|
import java.util.List;
|
|
import java.util.logging.Logger;
|
|
|
|
/**
|
|
* Standalone (no server) render of {@link ObjectState}s — block/item/text displays, dropped items,
|
|
* falling blocks — in one scene, to check the ObjectBaker geometry, UV orientation and transforms.
|
|
* Output: ~/Dokumente/PixelPics-Entity-Renders/objects.png
|
|
*/
|
|
public class ObjectTestRender {
|
|
|
|
static final String ROOT = "/home/elias/Dokumente/mcTestServer/plugins/PixelPics";
|
|
|
|
/** Server-free BlockData stand-in: material + blockstate string are all the model registry needs. */
|
|
static BlockData block(Material m, String state) {
|
|
String s = "minecraft:" + m.getKey().getKey() + (state == null ? "" : "[" + state + "]");
|
|
return (BlockData) Proxy.newProxyInstance(ObjectTestRender.class.getClassLoader(),
|
|
new Class<?>[]{BlockData.class}, (p, meth, a) -> switch (meth.getName()) {
|
|
case "getMaterial" -> m;
|
|
case "getAsString" -> s;
|
|
case "equals" -> p == a[0];
|
|
case "hashCode" -> System.identityHashCode(p);
|
|
case "toString" -> s;
|
|
default -> {
|
|
Class<?> rt = meth.getReturnType();
|
|
yield rt == boolean.class ? false : (rt.isPrimitive() ? 0 : null);
|
|
}
|
|
});
|
|
}
|
|
|
|
static ObjectState obj(ObjectState.Kind k, Affine a, BlockData b, String item, List<String> lines, int bg) {
|
|
return switch (k) {
|
|
case BLOCK -> ObjectState.block(a, b, null);
|
|
case ITEM -> ObjectState.item(a, new ItemSpec(item, b, null, false), "none", false);
|
|
case TEXT -> ObjectState.text(a, lines, 200, 0xFFFFFFFF, bg, true);
|
|
case LEASH -> ObjectState.leash(new double[6]);
|
|
};
|
|
}
|
|
|
|
public static void main(String[] args) throws Exception {
|
|
Logger log = Logger.getLogger("test");
|
|
ResourcePack pack = ResourcePackLoader.load(new File(ROOT, "resourcepack"), log).orElseThrow();
|
|
AssetReader reader = new AssetReader(pack);
|
|
TextureCache textures = new TextureCache(pack);
|
|
BlockModelRegistry registry = new BlockModelRegistry(reader, textures);
|
|
BiomeTintProvider tint = new BiomeTintProvider(textures);
|
|
var geo = new eu.mhsl.minecraft.pixelpics.render.entity.cem.CemModelLoader();
|
|
var font = eu.mhsl.minecraft.pixelpics.assets.font.FontLoader.load(pack, textures, log);
|
|
SkinCache skins = new SkinCache();
|
|
var baker = new eu.mhsl.minecraft.pixelpics.render.entity.cem.CemBaker(geo, textures, skins);
|
|
var beBaker = new eu.mhsl.minecraft.pixelpics.render.entity.cem.BlockEntityBaker(geo, textures, skins, font);
|
|
geo.load(new java.io.FileInputStream("src/main/resources/cem/cem_template_models.json"), log);
|
|
geo.load(new java.io.FileInputStream("src/main/resources/cem/vanilla_entity_models.json"), log);
|
|
DefaultScreenRenderer renderer = new DefaultScreenRenderer(registry, tint, textures, baker, beBaker, log);
|
|
|
|
List<ObjectState> objs = new ArrayList<>();
|
|
// Block displays: plain grass block (tinted), rotated + scaled stairs.
|
|
objs.add(obj(ObjectState.Kind.BLOCK, Affine.translation(0, 0, 0), block(Material.GRASS_BLOCK, "snowy=false"), null, List.of(), 0));
|
|
objs.add(obj(ObjectState.Kind.BLOCK,
|
|
Affine.translation(2, 0, 0).mul(Affine.rotY(Math.toRadians(30))).mul(Affine.scale(0.75)),
|
|
block(Material.OAK_STAIRS, "facing=north,half=bottom,shape=straight,waterlogged=false"), null, List.of(), 0));
|
|
// Item displays: a flat item and a block item (centred).
|
|
objs.add(obj(ObjectState.Kind.ITEM, Affine.translation(0.5, 2.0, 0.5), null, "diamond_sword", List.of(), 0));
|
|
objs.add(obj(ObjectState.Kind.ITEM, Affine.translation(2.5, 2.0, 0.5).mul(Affine.scale(0.6)),
|
|
block(Material.OAK_LOG, "axis=y"), "oak_log", List.of(), 0));
|
|
// Text display (facing the camera side), opaque background.
|
|
objs.add(obj(ObjectState.Kind.TEXT,
|
|
Affine.translation(1.5, 3.0, 0).mul(Affine.rotY(Math.PI)).mul(Affine.scale(0.025)), null, null,
|
|
List.of("Hallo PixelPics!", "Zeile zwei äöü"), 0xFF203040));
|
|
// Text seen from the BACK (front faces +Z, camera is on -Z) on the vanilla default 25% black
|
|
// background (blended), and a shield item.
|
|
objs.add(obj(ObjectState.Kind.TEXT, Affine.translation(-0.5, 3.0, 0).mul(Affine.scale(0.025)), null, null,
|
|
List.of("Rueckseite"), 0x40000000));
|
|
objs.add(obj(ObjectState.Kind.ITEM, Affine.translation(4, 1.0, 0.5), null, "shield", List.of(), 0));
|
|
// Dropped item (flat) on the ground.
|
|
objs.add(obj(ObjectState.Kind.ITEM, Affine.translation(-1, 0.3, 0.5).mul(Affine.scale(0.5)), null, "apple", List.of(), 0));
|
|
|
|
BlockData air = block(Material.AIR, null);
|
|
WorldSnapshot empty = new WorldSnapshot(Map.of(), 0, 1, air);
|
|
SkyContext sky = new SkyContext(6000, 0, 6000);
|
|
int W = 480, H = 360;
|
|
Vector cam = new Vector(1.5, 3.2, -6.5);
|
|
Location loc = new Location(null, cam.getX(), cam.getY(), cam.getZ());
|
|
loc.setDirection(new Vector(1.2, 1.3, 0.5).subtract(cam));
|
|
List<Vector> rayMap = EntityTestRender.buildRayMap(loc, W * 3, H * 3);
|
|
RenderJob job = new RenderJob(empty, rayMap, cam, W, H, sky, List.of(), List.of(), List.of(), objs);
|
|
BufferedImage img = renderer.execute(job);
|
|
File out = new File("/home/elias/Dokumente/PixelPics-Entity-Renders/objects.png");
|
|
ImageIO.write(img, "png", out);
|
|
System.out.println("WROTE " + out);
|
|
}
|
|
}
|