wip model resolver
This commit is contained in:
15
index.html
15
index.html
@@ -24,13 +24,16 @@
|
|||||||
|
|
||||||
<mc-diorama>
|
<mc-diorama>
|
||||||
<script type="text/mc-world">
|
<script type="text/mc-world">
|
||||||
p stone
|
p 0 0 0 stone
|
||||||
p stone
|
p 1 0 0 stone
|
||||||
p 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 0 0 0 stone_bricks-->
|
||||||
|
<!-- p 0 0 0 deepslate axis=z-->
|
||||||
p deepslate axis=z
|
|
||||||
</script>
|
</script>
|
||||||
</mc-diorama>
|
</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);
|
this.pending.delete(id);
|
||||||
|
|
||||||
if (this.onResolve) {
|
if (this.onResolve) {
|
||||||
this.onResolve(id, resolver);
|
this.onResolve(id);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(reason => {
|
.catch(reason => {
|
||||||
this.resolvers.set(id, this.resolvers.get(':invalid'));
|
this.resolvers.set(id, this.resolvers.get(':invalid'));
|
||||||
this.pending.delete(id);
|
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) {
|
resolve(id, pos, state) {
|
||||||
const resolver = this.getResolver(id);
|
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);
|
return resolver(state, hash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import {BlockstateResolver} from "./blockstate";
|
import {BlockstateResolver} from "./blockstate";
|
||||||
|
import {ModelResolver} from "./model";
|
||||||
|
|
||||||
export class Renderer {
|
export class Renderer {
|
||||||
constructor() {
|
constructor() {
|
||||||
@@ -12,26 +13,38 @@ export class Renderer {
|
|||||||
async function parse(src) {
|
async function parse(src) {
|
||||||
const lines = src.replace(/#.*?(?:\n|$)/, '\n').trim().split(/(?:\n[ \t]*)+/);
|
const lines = src.replace(/#.*?(?:\n|$)/, '\n').trim().split(/(?:\n[ \t]*)+/);
|
||||||
|
|
||||||
let count = 0;
|
const bres = new BlockstateResolver();
|
||||||
const res = new BlockstateResolver();
|
const mres = new ModelResolver();
|
||||||
|
|
||||||
function ff() {
|
function ff() {
|
||||||
|
const drawList = new Map();
|
||||||
|
|
||||||
for (const line of lines) {
|
for (const line of lines) {
|
||||||
const args = line.split(/[ \t]+/);
|
const args = line.split(/[ \t]+/);
|
||||||
const cmd = args[0].toLowerCase();
|
const cmd = args[0].toLowerCase();
|
||||||
|
|
||||||
if (cmd === 'p') {
|
if (cmd === 'p') {
|
||||||
const id = args[1];
|
const pos = [args[1], args[2], args[3]];
|
||||||
const hash = count;
|
const id = args[4];
|
||||||
count += 1;
|
const state = Object.fromEntries(args.slice(5).map(it => it.split('=')));
|
||||||
|
for (const part of bres.resolve(id, pos, state)) {
|
||||||
console.log(id, JSON.stringify(res.getResolver(id)({}, hash)));
|
drawList.set(part.model, null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const id of drawList.keys()) {
|
||||||
|
const data = mres.get(id);
|
||||||
|
console.log(id, data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
res.onResolve = (id, fn) => {
|
bres.onResolve = (id) => {
|
||||||
console.log('resolved', id, 'to', fn)
|
console.log('resolved blockstate', id)
|
||||||
|
ff()
|
||||||
|
}
|
||||||
|
mres.onResolve = (id) => {
|
||||||
|
console.log('resolved model', id)
|
||||||
ff()
|
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