Skip to content

Commit

Permalink
feat: signs rendering support!
Browse files Browse the repository at this point in the history
feat: shulker box rendering support
chore: minor improvements
  • Loading branch information
zardoy committed Oct 7, 2023
1 parent b68ef15 commit 6093437
Show file tree
Hide file tree
Showing 25 changed files with 755 additions and 75 deletions.
3 changes: 2 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{
"extends": "zardoy",
"ignorePatterns": [
"!*.js"
"!*.js",
"prismarine-viewer/"
],
"rules": {
"space-infix-ops": "error",
Expand Down
10 changes: 5 additions & 5 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@
"outFiles": [
"${workspaceFolder}/dist/**/*.js",
// "!${workspaceFolder}/dist/**/*vendors*",
"!${workspaceFolder}/dist/**/*minecraftData*",
"!${workspaceFolder}/dist/**/*mc-data*",
"!**/node_modules/**"
],
"skipFiles": [
// "<node_internals>/**/*vendors*"
"<node_internals>/**/*minecraftData*"
"<node_internals>/**/*mc-data*"
],
"port": 9222,
},
Expand All @@ -36,12 +36,12 @@
"outFiles": [
"${workspaceFolder}/dist/**/*.js",
// "!${workspaceFolder}/dist/**/*vendors*",
"!${workspaceFolder}/dist/**/*minecraftData*",
"!${workspaceFolder}/dist/**/*mc-data*",
"!**/node_modules/**"
],
"skipFiles": [
// "<node_internals>/**/*vendors*"
"<node_internals>/**/*minecraftData*"
"<node_internals>/**/*mc-data*"
],
},
{
Expand All @@ -54,7 +54,7 @@
"webRoot": "${workspaceFolder}/",
"skipFiles": [
// "<node_internals>/**/*vendors*"
"<node_internals>/**/*minecraftData*"
"<node_internals>/**/*mc-data*"
],
},
]
Expand Down
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
"web",
"client"
],
"bin": "./server.js",
"author": "PrismarineJS",
"license": "MIT",
"dependencies": {
Expand Down
6 changes: 3 additions & 3 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pnpm-workspace.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
packages:
- "."
- "prismarine-viewer"
- "prismarine-viewer/viewer/sign-renderer/"
111 changes: 82 additions & 29 deletions prismarine-viewer/examples/playground.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//@ts-check
/* global THREE, fetch */
const _ = require('lodash')
const { WorldView, Viewer, MapControls } = require('../viewer')
const { WorldDataEmitter, Viewer, MapControls } = require('../viewer')
const { Vec3 } = require('vec3')
const { Schematic } = require('prismarine-schematic')
const BlockLoader = require('prismarine-block')
Expand All @@ -10,9 +10,9 @@ const BlockLoader = require('prismarine-block')
const ChunkLoader = require('prismarine-chunk')
/** @type {import('prismarine-world')['default']} */
//@ts-ignore
const WorldLoader = require('prismarine-world');
const WorldLoader = require('prismarine-world')
const THREE = require('three')
const {GUI} = require('lil-gui')
const { GUI } = require('lil-gui')
const { toMajor } = require('../viewer/lib/version')
const { loadScript } = require('../viewer/lib/utils')
globalThis.THREE = THREE
Expand All @@ -26,8 +26,8 @@ const params = {
skip: '',
version: globalThis.includedVersions.sort((a, b) => {
const s = (x) => {
const parts = x.split('.');
return +parts[0]+(+parts[1])
const parts = x.split('.')
return +parts[0] + (+parts[1])
}
return s(a) - s(b)
}).at(-1),
Expand All @@ -39,6 +39,7 @@ const params = {
this.entity = ''
},
entityRotate: false,
camera: ''
}

const qs = new URLSearchParams(window.location.search)
Expand All @@ -59,13 +60,18 @@ const setQs = () => {
async function main () {
const { version } = params
// temporary solution until web worker is here, cache data for faster reloads
if (!window['mcData']['version']) {
const sessionKey = `mcData-${version}`;
const globalMcData = window['mcData'];
if (!globalMcData['version']) {
const major = toMajor(version);
const sessionKey = `mcData-${major}`
if (sessionStorage[sessionKey]) {
window['mcData'][version] = JSON.parse(sessionStorage[sessionKey])
Object.assign(globalMcData, JSON.parse(sessionStorage[sessionKey]))
} else {
await loadScript(`./mc-data/${toMajor(version)}.js`)
sessionStorage[sessionKey] = JSON.stringify(window['mcData'][version])
if (sessionStorage.length > 1) sessionStorage.clear()
await loadScript(`./mc-data/${major}.js`)
try {
sessionStorage[sessionKey] = JSON.stringify(Object.fromEntries(Object.entries(globalMcData).filter(([ver]) => ver.startsWith(major))))
} catch {}
}
}

Expand All @@ -88,20 +94,30 @@ async function main () {
// const data = await fetch('smallhouse1.schem').then(r => r.arrayBuffer())
// const schem = await Schematic.read(Buffer.from(data), version)

const viewDistance = 1
const viewDistance = 2
const center = new Vec3(0, 90, 0)

const World = WorldLoader(version)

// const diamondSquare = require('diamond-square')({ version, seed: Math.floor(Math.random() * Math.pow(2, 31)) })
const targetBlockPos = center

const targetPos = center
//@ts-ignore
const chunk1 = new Chunk()
//@ts-ignore
const chunk2 = new Chunk()
chunk1.setBlockStateId(center, 34)
chunk2.setBlockStateId(center.offset(1, 0, 0), 34)
const world = new World((chunkX, chunkZ) => {
// if (chunkX === 0 && chunkZ === 0) return chunk1
// if (chunkX === 1 && chunkZ === 0) return chunk2
//@ts-ignore
return new Chunk()
const chunk = new Chunk();
return chunk
})

// await schem.paste(world, new Vec3(0, 60, 0))

const worldView = new WorldDataEmitter(world, viewDistance, center)

// Create three.js context, add to page
Expand All @@ -113,29 +129,33 @@ async function main () {
// Create viewer
const viewer = new Viewer(renderer)
viewer.setVersion(version)

viewer.listen(worldView)
// Initialize viewer, load chunks
// Load chunks
worldView.init(center)
window['worldView'] = worldView
window['viewer'] = viewer


// const controls = new MapControls(viewer.camera, renderer.domElement)
// controls.update()
//@ts-ignore
const controls = new THREE.OrbitControls(viewer.camera, renderer.domElement)
controls.target.set(center.x + 0.5, center.y + 0.5, center.z + 0.5)
controls.update()

const cameraPos = center.offset(2, 2, 2)
const pitch = THREE.MathUtils.degToRad(-45)
const yaw = THREE.MathUtils.degToRad(45)
viewer.camera.rotation.set(pitch, yaw, 0, 'ZYX')
viewer.camera.lookAt(center.x + 0.5, center.y + 0.5, center.z + 0.5)
viewer.camera.position.set(cameraPos.x + 0.5, cameraPos.y + 0.5, cameraPos.z + 0.5)

let blockProps = {}
const getBlock = () => {
const getBlock = () => {
return mcData.blocksByName[params.block || 'air']
}
const onUpdate = {
block() {
const {states} = mcData.blocksByStateId[getBlock()?.minStateId] ?? {}
block () {
const { states } = mcData.blocksByStateId[getBlock()?.minStateId] ?? {}
folder.destroy()
if (!states) {
return
Expand All @@ -146,16 +166,16 @@ async function main () {
switch (state.type) {
case 'enum':
defaultValue = state.values[0]
break;
break
case 'bool':
defaultValue = false
break;
break
case 'int':
defaultValue = 0
break;
break
case 'direction':
defaultValue = 'north'
break;
break

default:
continue
Expand All @@ -173,14 +193,14 @@ async function main () {
viewer.entities.clear()
if (!params.entity) return
worldView.emit('entity', {
id: 'id', name: params.entity, pos: targetBlockPos.offset(0, 1, 0), width: 1, height: 1, username: 'username'
id: 'id', name: params.entity, pos: targetPos.offset(0, 1, 0), width: 1, height: 1, username: 'username'
})
}
}


const applyChanges = (metadataUpdate = false) => {
const blockId = getBlock()?.id;
const blockId = getBlock()?.id
/** @type {BlockLoader.Block} */
let block
if (metadataUpdate) {
Expand All @@ -197,14 +217,14 @@ async function main () {
block = Block.fromProperties(blockId ?? -1, blockProps, 0)
}

viewer.setBlockStateId(targetBlockPos, block.stateId)
viewer.setBlockStateId(targetPos, block.stateId)
console.log('up', block.stateId)
params.metadata = block.metadata
metadataGui.updateDisplay()
viewer.setBlockStateId(targetBlockPos.offset(0, -1, 0), params.supportBlock ? 1 : 0)
viewer.setBlockStateId(targetPos.offset(0, -1, 0), params.supportBlock ? 1 : 0)
setQs()
}
gui.onChange(({property}) => {
gui.onChange(({ property }) => {
if (property === 'camera') return
onUpdate[property]?.()
applyChanges(property === 'metadata')
Expand Down Expand Up @@ -233,6 +253,39 @@ async function main () {
})
animate()

// #region camera rotation
if (params.camera) {
const [x, y] = params.camera.split(',')
viewer.camera.rotation.set(parseFloat(x), parseFloat(y), 0, 'ZYX')
controls.update()
console.log(viewer.camera.rotation.x, parseFloat(x))
}
const throttledCamQsUpdate = _.throttle(() => {
const { camera } = viewer
// params.camera = `${camera.rotation.x.toFixed(2)},${camera.rotation.y.toFixed(2)}`
setQs()
}, 200)
controls.addEventListener('change', () => {
throttledCamQsUpdate()
animate()
})
// #endregion

window.onresize = () => {
// const vec3 = new THREE.Vector3()
// vec3.set(-1, -1, -1).unproject(viewer.camera)
// console.log(vec3)
// box.position.set(vec3.x, vec3.y, vec3.z-1)

const { camera } = viewer
viewer.camera.aspect = window.innerWidth / window.innerHeight
viewer.camera.updateProjectionMatrix()
renderer.setSize(window.innerWidth, window.innerHeight)

animate()
}
window.dispatchEvent(new Event('resize'))

setTimeout(() => {
// worldView.emit('entity', {
// id: 'id', name: 'player', pos: center.offset(1, -2, 0), width: 1, height: 1, username: 'username'
Expand Down
3 changes: 2 additions & 1 deletion prismarine-viewer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
"pretest": "npm run lint",
"lint": "standard",
"fix": "standard --fix",
"postinstall": "tsx viewer/prepare/generateTextures.ts && node buildWorker.mjs"
"postinstall": "pnpm generate-textures && node buildWorker.mjs",
"generate-textures": "tsx viewer/prepare/generateTextures.ts"
},
"author": "PrismarineJS",
"license": "MIT",
Expand Down
22 changes: 20 additions & 2 deletions prismarine-viewer/viewer/lib/models.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//@ts-nocheck
import { Vec3 } from 'vec3'
import { BlockStatesOutput } from '../prepare/modelsBuilder'
import { World } from './world'

const tints = {}
let blockStates: BlockStatesOutput
Expand Down Expand Up @@ -367,7 +368,7 @@ function renderElement (world, cursor, element, doAO, attr, globalMatrix, global
}
}

export function getSectionGeometry (sx, sy, sz, world) {
export function getSectionGeometry (sx, sy, sz, world: World) {
const attr = {
sx: sx + 8,
sy: sy + 8,
Expand All @@ -380,14 +381,31 @@ export function getSectionGeometry (sx, sy, sz, world) {
t_normals: [],
t_colors: [],
t_uvs: [],
indices: []
indices: [],
// todo this can be removed here
signs: {}
}

const cursor = new Vec3(0, 0, 0)
for (cursor.y = sy; cursor.y < sy + 16; cursor.y++) {
for (cursor.z = sz; cursor.z < sz + 16; cursor.z++) {
for (cursor.x = sx; cursor.x < sx + 16; cursor.x++) {
const block = world.getBlock(cursor)
if (block.name.includes('sign')) {
const key = `${cursor.x},${cursor.y},${cursor.z}`
const props = block.getProperties();
const facingRotationMap = {
"north": 2,
"south": 0,
"west": 1,
"east": 3
}
const isWall = block.name.endsWith('wall_sign') || block.name.endsWith('hanging_sign');
attr.signs[key] = {
isWall,
rotation: isWall ? facingRotationMap[props.facing] : +props.rotation
}
}
const biome = block.biome.name
if (block.variant === undefined) {
block.variant = getModelVariants(block)
Expand Down
Loading

0 comments on commit 6093437

Please sign in to comment.