This demo shows how you can embed ProtoTwin into another application or website using the @prototwin/embed NPM package. This can be used to create custom 3D HMIs, digital shadows, or showcase interactive simulations on an existing website.
npm install
npm startOpen the local URL printed by Vite. The Vite configuration includes the cross-origin isolation headers required by ProtoTwin.
ProtoTwin uses a multithreaded architecture that relies on SharedArrayBuffer. Most browsers will only enable support for SharedArrayBuffer on cross-origin isolated pages. You must serve the page that embeds ProtoTwin with these headers:
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: credentiallessUsing the ProtoTwin Embed package is as simple as installing and importing the package, creating a viewer instance, and issuing commands.
import { embed } from "@prototwin/embed";
const viewer = embed({
element: document.getElementById("viewer")
});
await viewer.openURL("https://example.com/model.ptm");
await viewer.start();Basic commands:
await viewer.start(); // Start the simulation
await viewer.stop(); // Pause/stop the simulation
await viewer.setSpeed(2); // Change the target simulation speed
await viewer.reset(); // Reset the simulation
await viewer.clear(); // Clear the scene
await viewer.controlbar(true); // Enable/display the control bar
await viewer.openURL("https://example.com/model.ptm"); // Load a model from a URL
await viewer.openBuffer(arrayBuffer); // Load a model from an ArrayBufferYou can execute a standalone script:
const response = await viewer.executeScript(`
import type { World } from "prototwin";
export default function(world: World) {
console.log(world.time);
}
`);
console.log(response.diagnostics);
console.log(response.logs);If the script fails to compile or throws at runtime, response.success will be false and the diagnostics/logs will contain the details:
if (response.success === false) {
console.error(response.diagnostics);
console.error(response.logs);
}Signals can be read from the simulation. The readSignals() function returns a ReadBuffer, which contains the values of all the signals in the model in an efficient binary format. You can use the ReadBuffer.get() function to obtain the value for a signal at the specified address.
const signals = await viewer.readSignals();
const value = signals.get(10);Similarly, you can use the writeSignals() function to write a list of signals in a single batch operation.
const writes = new WriteBuffer();
writes.setBit(1, true);
writes.setUint32(2, 42);
writes.setFloat(3, 1.5);
await viewer.writeSignals(writes);Note that the signals API is low-level and does not perform any validation.
Commands resolve with a response object that indicates whether the operation succeeded.
const response = await viewer.start();
if (response.success === false) {
console.error(response.error);
}Remove/shutdown the embedded instance of ProtoTwin:
viewer.dispose();