multiview. camera controls
This commit is contained in:
184
index.html
184
index.html
@@ -7,127 +7,127 @@
|
||||
body {
|
||||
background: #222;
|
||||
color: #eee;
|
||||
font-family: monospace;
|
||||
padding: 20px;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
#canvas-container {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
margin-top: 20px;
|
||||
main {
|
||||
width: 80ch;
|
||||
margin-inline: auto;
|
||||
}
|
||||
|
||||
canvas {
|
||||
border: 1px solid #444;
|
||||
}
|
||||
|
||||
#webgl-canvas {
|
||||
width: 512px;
|
||||
height: 512px;
|
||||
.figure {
|
||||
width: 100%;
|
||||
height: 20em;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h2>Renderer Data Pipeline Prototype</h2>
|
||||
<div id="output">Loading and building geometry...</div>
|
||||
<main>
|
||||
<h1>Visualizer</h1>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur ullamcorper ut mauris sed tempor. Nunc
|
||||
vehicula tempor purus, non vestibulum libero ornare non. Morbi fringilla sapien diam, sed rhoncus lacus egestas
|
||||
vel.
|
||||
</p>
|
||||
|
||||
<div class="figure" id="demo-1"></div>
|
||||
|
||||
<p>
|
||||
Curabitur vestibulum vitae orci ac laoreet. Donec vel imperdiet tortor. Vestibulum lobortis aliquam tellus,
|
||||
vitae viverra nisi porttitor quis. Pellentesque id efficitur arcu. Nunc laoreet pulvinar ligula eu maximus.
|
||||
Mauris ullamcorper accumsan dui vel pulvinar.
|
||||
</p>
|
||||
|
||||
<div class="figure" id="demo-2"></div>
|
||||
|
||||
<p>
|
||||
Curabitur tincidunt sapien et diam fringilla, eu accumsan odio faucibus. Orci varius natoque penatibus et magnis
|
||||
dis parturient montes, nascetur ridiculus mus.
|
||||
</p>
|
||||
|
||||
<div id="canvas-container">
|
||||
<canvas id="webgl-canvas" width="1024" height="1024"></canvas>
|
||||
<div id="atlas-container"></div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<script type="module">
|
||||
import {World} from './world.js';
|
||||
import {Renderer} from './renderer.js';
|
||||
import {Engine} from './engine.js';
|
||||
import {Diorama} from './diorama.js';
|
||||
|
||||
async function testPipeline() {
|
||||
async function initDocument() {
|
||||
try {
|
||||
const webglCanvas = document.getElementById('webgl-canvas');
|
||||
const renderer = new Renderer(webglCanvas);
|
||||
// Adjusted camera slightly to see the block underneath
|
||||
renderer.setCamera(-3, 3, -3, 3, 5, 4, 5, 0, 0, 0);
|
||||
// 1. Initialize the global background renderer
|
||||
const engine = new Engine();
|
||||
|
||||
document.getElementById('atlas-container').appendChild(renderer.atlas.canvas);
|
||||
// Append the texture atlas to the bottom for debugging
|
||||
document.getElementById('atlas-container').appendChild(engine.atlas.canvas);
|
||||
|
||||
const world = new World();
|
||||
// 2. Setup Figure 1 (Shared: Wire & Repeater | Unique: Trapdoor)
|
||||
const demo1 = new Diorama('demo-1', engine);
|
||||
// Adjust camera to fit the small viewport
|
||||
demo1.camera.radius = 2;
|
||||
demo1.camera.phi = 10
|
||||
demo1.camera.theta = -5
|
||||
|
||||
// Initial State: Closed trapdoor, no redstone block
|
||||
world.setBlock('minecraft:oak_trapdoor', 0, 0, 0, {
|
||||
facing: 'east',
|
||||
open: 'false',
|
||||
half: 'bottom'
|
||||
demo1.world.setBlock('minecraft:redstone_wire', 0, 0, 0, {
|
||||
east: 'side',
|
||||
west: 'none',
|
||||
north: 'none',
|
||||
south: 'none',
|
||||
power: '15'
|
||||
});
|
||||
demo1.world.setBlock('minecraft:repeater', 1, 0, 0, {
|
||||
facing: 'east',
|
||||
delay: '1',
|
||||
locked: 'false',
|
||||
powered: 'true'
|
||||
});
|
||||
demo1.world.setBlock('minecraft:oak_trapdoor', 2, 0, 0, {facing: 'east', half: 'bottom', open: 'true'});
|
||||
|
||||
world.setBlock('minecraft:coal_block', 0, -1, -3); // north -z
|
||||
world.setBlock('minecraft:diamond_block', 3, -1, 0); // east +x
|
||||
world.setBlock('minecraft:gold_block', 0, -1, 3); // south +z
|
||||
world.setBlock('minecraft:iron_block', -3, -1, 0); // west -x
|
||||
demo1.centerView()
|
||||
|
||||
// NOTE the trapdoor should open AWAY from the diamond block
|
||||
// the repeaters should point "inward"
|
||||
// the pistons should extend "outward"
|
||||
engine.addDiorama(demo1);
|
||||
|
||||
// world.setBlock('minecraft:glass', 1, 0, 0);
|
||||
// world.setBlock('minecraft:glass', 0, 0, 1);
|
||||
world.setBlock('minecraft:coal_block', 0, -1, 0);
|
||||
world.setBlock('minecraft:repeater', 1, -1, 0, {facing: 'west', delay: 1, locked: false, powered: false});
|
||||
world.setBlock('minecraft:comparator', 0, -1, 1, {facing: 'north', mode: 'compare', powered: false});
|
||||
// 3. Setup Figure 2 (Shared: Wire & Repeater | Unique: Piston & Redstone Block)
|
||||
const demo2 = new Diorama('demo-2', engine);
|
||||
// Adjust camera to fit the small viewport
|
||||
demo2.camera.radius = 3;
|
||||
// View from a slightly different angle
|
||||
|
||||
world.setBlock('minecraft:piston', 0, 0, -3, {facing: "north", extended: false})
|
||||
world.setBlock('minecraft:piston', 3, 0, 0, {facing: "east", extended: false})
|
||||
world.setBlock('minecraft:piston', 0, 0, 3, {facing: "south", extended: false})
|
||||
world.setBlock('minecraft:piston', -3, 0, 0, {facing: "west", extended: false})
|
||||
demo2.world.setBlock('minecraft:redstone_wire', 0, 0, 0, {
|
||||
east: 'side',
|
||||
west: 'none',
|
||||
north: 'none',
|
||||
south: 'none',
|
||||
power: '0'
|
||||
});
|
||||
demo2.world.setBlock('minecraft:repeater', 1, 0, 0, {
|
||||
facing: 'east',
|
||||
delay: '4',
|
||||
locked: 'false',
|
||||
powered: 'false'
|
||||
});
|
||||
demo2.world.setBlock('minecraft:piston', 2, 0, 0, {facing: 'east', extended: 'false'});
|
||||
demo2.world.setBlock('minecraft:piston', 2, 0, 1, {facing: 'east', extended: 'true'});
|
||||
demo2.world.setBlock('minecraft:piston', 2, 0, 2, {facing: 'east', extended: 'true'});
|
||||
demo2.world.setBlock('minecraft:piston_head', 2.5, 0, 1, {facing: 'east', short: 'true',type: 'sticky'});
|
||||
demo2.world.setBlock('minecraft:piston_head', 3, 0, 2, {facing: 'east', short: 'false',type: 'normal'});
|
||||
demo2.world.setBlock('minecraft:redstone_block', 3, 0, 0);
|
||||
demo2.world.setBlock('minecraft:redstone_block', 3.5, 0, 1);
|
||||
demo2.world.setBlock('minecraft:redstone_block', 4, 0, 2);
|
||||
|
||||
world.setBlock('minecraft:repeater', 0, 1, -3, {facing: "north", delay: 1, locked: true, powered: false})
|
||||
world.setBlock('minecraft:repeater', 3, 1, 0, {facing: "east", delay: 2, locked: true, powered: false})
|
||||
world.setBlock('minecraft:repeater', 0, 1, 3, {facing: "south", delay: 3, locked: true, powered: false})
|
||||
world.setBlock('minecraft:repeater', -3, 1, 0, {facing: "west", delay: 4, locked: true, powered: false})
|
||||
demo2.centerView()
|
||||
engine.addDiorama(demo2);
|
||||
|
||||
await renderer.updateWorld(world);
|
||||
|
||||
// Render Loop (Static, just drawing the current buffers)
|
||||
function animate() {
|
||||
renderer.render();
|
||||
requestAnimationFrame(animate);
|
||||
}
|
||||
|
||||
animate();
|
||||
|
||||
// --- THE STATE MACHINE LOOP ---
|
||||
let isOpen = false;
|
||||
|
||||
setInterval(async () => {
|
||||
isOpen = !isOpen;
|
||||
|
||||
// 1. Mutate the world data
|
||||
world.updateBlock(0, 0, 0, {open: isOpen.toString()});
|
||||
|
||||
if (isOpen) {
|
||||
world.setBlock('minecraft:redstone_block', 0, -1, 0);
|
||||
world.updateBlock(1, -1, 0, {powered: true})
|
||||
world.updateBlock(0, -1, 1, {powered: true})
|
||||
} else {
|
||||
world.removeBlock(0, -1, 0);
|
||||
world.updateBlock(1, -1, 0, {powered: false})
|
||||
world.updateBlock(0, -1, 1, {mode: 'subtract', powered: false})
|
||||
}
|
||||
|
||||
// 2. Tell the renderer to sync with the new world state
|
||||
await renderer.updateWorld(world);
|
||||
|
||||
document.getElementById('output').innerHTML = `<strong>State Demo:</strong> Trapdoor is ${isOpen ? 'OPEN' : 'CLOSED'}`;
|
||||
|
||||
// await return new Promise((resolve) => setTimeout(resolve, time));
|
||||
|
||||
}, 1000);
|
||||
// 4. Build geometries and draw
|
||||
// We await these so the meshes are fully baked and the atlas is populated
|
||||
await demo1.update();
|
||||
await demo2.update();
|
||||
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
document.getElementById('output').textContent = 'Error: ' + err.message;
|
||||
console.error("Renderer Initialization Failed:", err);
|
||||
}
|
||||
}
|
||||
|
||||
testPipeline();
|
||||
initDocument();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user