wip model resolver
This commit is contained in:
15
index.html
15
index.html
@@ -24,13 +24,16 @@
|
||||
|
||||
<mc-diorama>
|
||||
<script type="text/mc-world">
|
||||
p stone
|
||||
p stone
|
||||
p stone
|
||||
p 0 0 0 stone
|
||||
p 1 0 0 stone
|
||||
p 2 0 0 stone
|
||||
p 3 0 0 stone
|
||||
p 4 0 0 stone
|
||||
p 5 0 0 stone
|
||||
p 6 0 0 stone
|
||||
|
||||
p stone_bricks
|
||||
|
||||
p deepslate axis=z
|
||||
<!-- p 0 0 0 stone_bricks-->
|
||||
<!-- p 0 0 0 deepslate axis=z-->
|
||||
</script>
|
||||
</mc-diorama>
|
||||
|
||||
|
||||
@@ -1 +1,124 @@
|
||||
{"gui_light":"side","display":{"gui":{"rotation":[30,225,0],"translation":[0,0,0],"scale":[0.625,0.625,0.625]},"ground":{"rotation":[0,0,0],"translation":[0,3,0],"scale":[0.25,0.25,0.25]},"fixed":{"rotation":[0,0,0],"translation":[0,0,0],"scale":[0.5,0.5,0.5]},"on_shelf":{"rotation":[0,180,0],"translation":[0,0,0],"scale":[1,1,1]},"thirdperson_righthand":{"rotation":[75,45,0],"translation":[0,2.5,0],"scale":[0.375,0.375,0.375]},"firstperson_righthand":{"rotation":[0,45,0],"translation":[0,0,0],"scale":[0.4,0.4,0.4]},"firstperson_lefthand":{"rotation":[0,225,0],"translation":[0,0,0],"scale":[0.4,0.4,0.4]}}}
|
||||
{
|
||||
"gui_light": "side",
|
||||
"display": {
|
||||
"gui": {
|
||||
"rotation": [
|
||||
30,
|
||||
225,
|
||||
0
|
||||
],
|
||||
"translation": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"scale": [
|
||||
0.625,
|
||||
0.625,
|
||||
0.625
|
||||
]
|
||||
},
|
||||
"ground": {
|
||||
"rotation": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"translation": [
|
||||
0,
|
||||
3,
|
||||
0
|
||||
],
|
||||
"scale": [
|
||||
0.25,
|
||||
0.25,
|
||||
0.25
|
||||
]
|
||||
},
|
||||
"fixed": {
|
||||
"rotation": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"translation": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"scale": [
|
||||
0.5,
|
||||
0.5,
|
||||
0.5
|
||||
]
|
||||
},
|
||||
"on_shelf": {
|
||||
"rotation": [
|
||||
0,
|
||||
180,
|
||||
0
|
||||
],
|
||||
"translation": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"scale": [
|
||||
1,
|
||||
1,
|
||||
1
|
||||
]
|
||||
},
|
||||
"thirdperson_righthand": {
|
||||
"rotation": [
|
||||
75,
|
||||
45,
|
||||
0
|
||||
],
|
||||
"translation": [
|
||||
0,
|
||||
2.5,
|
||||
0
|
||||
],
|
||||
"scale": [
|
||||
0.375,
|
||||
0.375,
|
||||
0.375
|
||||
]
|
||||
},
|
||||
"firstperson_righthand": {
|
||||
"rotation": [
|
||||
0,
|
||||
45,
|
||||
0
|
||||
],
|
||||
"translation": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"scale": [
|
||||
0.4,
|
||||
0.4,
|
||||
0.4
|
||||
]
|
||||
},
|
||||
"firstperson_lefthand": {
|
||||
"rotation": [
|
||||
0,
|
||||
225,
|
||||
0
|
||||
],
|
||||
"translation": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"scale": [
|
||||
0.4,
|
||||
0.4,
|
||||
0.4
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1 +1,43 @@
|
||||
{"parent":"block/block","elements":[{"from":[0,0,0],"to":[16,16,16],"faces":{"down":{"texture":"#down","cullface":"down"},"up":{"texture":"#up","cullface":"up"},"north":{"texture":"#north","cullface":"north"},"south":{"texture":"#south","cullface":"south"},"west":{"texture":"#west","cullface":"west"},"east":{"texture":"#east","cullface":"east"}}}]}
|
||||
{
|
||||
"parent": "block/block",
|
||||
"elements": [
|
||||
{
|
||||
"from": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"to": [
|
||||
16,
|
||||
16,
|
||||
16
|
||||
],
|
||||
"faces": {
|
||||
"down": {
|
||||
"texture": "#down",
|
||||
"cullface": "down"
|
||||
},
|
||||
"up": {
|
||||
"texture": "#up",
|
||||
"cullface": "up"
|
||||
},
|
||||
"north": {
|
||||
"texture": "#north",
|
||||
"cullface": "north"
|
||||
},
|
||||
"south": {
|
||||
"texture": "#south",
|
||||
"cullface": "south"
|
||||
},
|
||||
"west": {
|
||||
"texture": "#west",
|
||||
"cullface": "west"
|
||||
},
|
||||
"east": {
|
||||
"texture": "#east",
|
||||
"cullface": "east"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1 +1,12 @@
|
||||
{"parent":"block/cube","textures":{"particle":"#all","down":"#all","up":"#all","north":"#all","east":"#all","south":"#all","west":"#all"}}
|
||||
{
|
||||
"parent": "block/cube",
|
||||
"textures": {
|
||||
"particle": "#all",
|
||||
"down": "#all",
|
||||
"up": "#all",
|
||||
"north": "#all",
|
||||
"east": "#all",
|
||||
"south": "#all",
|
||||
"west": "#all"
|
||||
}
|
||||
}
|
||||
@@ -1 +1,6 @@
|
||||
{"parent":"minecraft:block/cube_all","textures":{"all":"minecraft:block/smooth_stone"}}
|
||||
{
|
||||
"parent": "minecraft:block/cube_all",
|
||||
"textures": {
|
||||
"all": "minecraft:block/smooth_stone"
|
||||
}
|
||||
}
|
||||
@@ -174,13 +174,16 @@ export class BlockstateResolver {
|
||||
this.pending.delete(id);
|
||||
|
||||
if (this.onResolve) {
|
||||
this.onResolve(id, resolver);
|
||||
this.onResolve(id);
|
||||
}
|
||||
})
|
||||
.catch(reason => {
|
||||
this.resolvers.set(id, this.resolvers.get(':invalid'));
|
||||
this.pending.delete(id);
|
||||
console.log(`failed to resolve blockstate ${id}: ${reason}`);
|
||||
console.warn(`failed to resolve blockstate ${id}: ${reason}`);
|
||||
if (this.onResolve) {
|
||||
this.onResolve(id);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -189,7 +192,26 @@ export class BlockstateResolver {
|
||||
|
||||
resolve(id, pos, state) {
|
||||
const resolver = this.getResolver(id);
|
||||
const hash = pos[0] * 3.236 + pos[1] * 4.854 + pos[2] * 8.090;
|
||||
|
||||
// Read the 3 floats directly as 32-bit integers
|
||||
let buffer = new Float32Array([pos[0], pos[1], pos[2]]).buffer;
|
||||
let uview = new Uint32Array(buffer);
|
||||
|
||||
// Mix using large primes
|
||||
let hash = Math.imul(uview[0], 73856093) ^
|
||||
Math.imul(uview[1], 19349663) ^
|
||||
Math.imul(uview[2], 83492791);
|
||||
|
||||
// Avalanche step: Force high bits to mix into low bits (fixes the % 8 issue)
|
||||
hash ^= hash >>> 16;
|
||||
hash = Math.imul(hash, 0x85ebca6b);
|
||||
hash ^= hash >>> 13;
|
||||
hash = Math.imul(hash, 0xc2b2ae35);
|
||||
hash ^= hash >>> 16;
|
||||
|
||||
// Ensure unsigned 32-bit int
|
||||
hash >>>= 0;
|
||||
|
||||
return resolver(state, hash);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import {BlockstateResolver} from "./blockstate";
|
||||
import {ModelResolver} from "./model";
|
||||
|
||||
export class Renderer {
|
||||
constructor() {
|
||||
@@ -12,26 +13,38 @@ export class Renderer {
|
||||
async function parse(src) {
|
||||
const lines = src.replace(/#.*?(?:\n|$)/, '\n').trim().split(/(?:\n[ \t]*)+/);
|
||||
|
||||
let count = 0;
|
||||
const res = new BlockstateResolver();
|
||||
const bres = new BlockstateResolver();
|
||||
const mres = new ModelResolver();
|
||||
|
||||
function ff() {
|
||||
const drawList = new Map();
|
||||
|
||||
for (const line of lines) {
|
||||
const args = line.split(/[ \t]+/);
|
||||
const cmd = args[0].toLowerCase();
|
||||
|
||||
if (cmd === 'p') {
|
||||
const id = args[1];
|
||||
const hash = count;
|
||||
count += 1;
|
||||
|
||||
console.log(id, JSON.stringify(res.getResolver(id)({}, hash)));
|
||||
const pos = [args[1], args[2], args[3]];
|
||||
const id = args[4];
|
||||
const state = Object.fromEntries(args.slice(5).map(it => it.split('=')));
|
||||
for (const part of bres.resolve(id, pos, state)) {
|
||||
drawList.set(part.model, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const id of drawList.keys()) {
|
||||
const data = mres.get(id);
|
||||
console.log(id, data);
|
||||
}
|
||||
}
|
||||
|
||||
res.onResolve = (id, fn) => {
|
||||
console.log('resolved', id, 'to', fn)
|
||||
bres.onResolve = (id) => {
|
||||
console.log('resolved blockstate', id)
|
||||
ff()
|
||||
}
|
||||
mres.onResolve = (id) => {
|
||||
console.log('resolved model', id)
|
||||
ff()
|
||||
}
|
||||
|
||||
|
||||
58
src/model.js
Normal file
58
src/model.js
Normal file
@@ -0,0 +1,58 @@
|
||||
export class ModelResolver {
|
||||
constructor() {
|
||||
this.models = new Map();
|
||||
this.pending = new Map();
|
||||
|
||||
this.onResolve = undefined;
|
||||
|
||||
const cuboid = {
|
||||
"from": [0, 0, 0],
|
||||
"to": [0, 0, 0],
|
||||
"faces": {
|
||||
"down": {"texture": "#all"},
|
||||
"up": {"texture": "#all"},
|
||||
"north": {"texture": "#all"},
|
||||
"south": {"texture": "#all"},
|
||||
"west": {"texture": "#all"},
|
||||
"east": {"texture": "#all"}
|
||||
}
|
||||
};
|
||||
|
||||
this.models.set(':pending', {"textures": {"all": ":pending"}, "elements": [cuboid]});
|
||||
this.models.set(':missing', {"textures": {"all": ":missing"}, "elements": [cuboid]});
|
||||
}
|
||||
|
||||
get(id) {
|
||||
id = id.includes(":") ? id : `minecraft:${id}`;
|
||||
|
||||
if (this.models.has(id)) {
|
||||
return this.models.get(id);
|
||||
}
|
||||
|
||||
if (!this.pending.has(id)) {
|
||||
const [space, name] = id.split(':');
|
||||
const url = `/assets/${space}/models/${name}.json`;
|
||||
|
||||
this.pending.set(id, fetch(url)
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
this.models.set(id, data)
|
||||
this.pending.delete(id)
|
||||
|
||||
if (this.onResolve) {
|
||||
this.onResolve(id);
|
||||
}
|
||||
})
|
||||
.catch(reason => {
|
||||
this.models.set(id, this.models.get(':invalid'));
|
||||
this.pending.delete(id);
|
||||
console.log(`failed to resolve model ${id}: ${reason}`)
|
||||
if (this.onResolve) {
|
||||
this.onResolve(id);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
return this.models.get(':pending');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user