Building 3D Medical Simulations With Three.js

Loading Model...

ESC - Menu
WASD / ARROWS - Move


Introduction to 3D Medical Simulations

The world of web-based medical education has seen tremendous growth thanks to WebGL and the powerful Three.js library. Three.js is a JavaScript 3D library that makes it possible to create complex, high-performance, interactive 3D environments that run smoothly in any modern web browser without plugins or installations. This technology is revolutionizing medical training by allowing educators and developers to build realistic simulated environments where medical students, residents, and practicing professionals can practice procedures, explore human anatomy in three dimensions, and experience realistic clinical scenarios in a completely safe, repeatable, and cost-effective way.

Using Three.js, developers can load detailed 3D models of hospital operating rooms, surgical tools, patient avatars, and anatomical structures. The library supports physically-based rendering, advanced lighting, shadows, particle systems, and real-time animations — all essential for creating believable medical training simulations. Trainees can walk through a virtual operating theater using first-person controls, interact with equipment, practice sterile techniques, or even rehearse complex surgical steps before ever touching a real patient.

Step-by-Step Instructions (Exact Code From This Page)

Step 1: Scene & Camera Setup

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, .1, 1000);
camera.position.set(1, 1.5, 1);
camera.near = .015;
camera.updateProjectionMatrix();
Explanation: Creates the 3D world (scene) and the virtual camera. The camera position and near clipping plane are optimized for comfortable first-person navigation inside the medical environment.

Step 2: Renderer Setup

var renderer = new THREE.WebGLRenderer({ alpha: true, depth: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.toneMapping = THREE.ReinhardToneMapping;
renderer.setClearColor(0x000000, 0);
renderer.domElement.style.position = 'fixed';
renderer.domElement.id = 'renderer';
renderer.domElement.style.zIndex = '-1';
renderer.domElement.style.left = '0';
renderer.domElement.style.top = '0';
document.body.appendChild(renderer.domElement);
Explanation: Creates the WebGL canvas and configures it to render the 3D scene as a background layer with proper resolution and tone mapping for realistic medical visuals.

Step 3: PointerLockControls & Grid

var controls = new THREE.PointerLockControls(camera, document.body);
controls.mouseSensitivity = 0.005;
var gridHelper = new THREE.GridHelper(20, 20);
scene.add(gridHelper);
scene.add(controls.getObject());
Explanation: Enables immersive mouse-look controls and adds a helper grid for development (you can remove the grid in production).

Step 4: Lighting

var ambientLight = new THREE.AmbientLight(0xffffff, 2);
scene.add(ambientLight);
Explanation: Provides even illumination across the entire operating room so all details of the medical model are clearly visible.

Step 5: Keyboard Movement Variables

var moveForward = false;
var moveBackward = false;
var moveLeft = false;
var moveRight = false;
Explanation: These flags track which movement keys are pressed so the animation loop can respond smoothly.

Step 6: Load Medical Model

var loader = new THREE.GLTFLoader();
loader.load(
    '../models/charite_university_hospital_-_operating_room.glb',
    function (gltf) {
        abandonedBuilding = gltf.scene;
        abandonedBuilding.position.y = 0.009;
        scene.add(abandonedBuilding);
        playButton.innerText = "Click To Explore";
    },
    function (xhr) { console.log((xhr.loaded / xhr.total * 100) + '% loaded'); },
    function (error) { console.error('An error occurred:', error); }
);
Explanation: Loads the detailed 3D operating room model and updates the button text once loading is complete.

Step 7: Keyboard Controls

var onKeyDown = function (event) {
    switch (event.keyCode) {
        case 38: case 87: moveForward = true; break;
        case 37: case 65: moveLeft = true; break;
        case 40: case 83: moveBackward = true; break;
        case 39: case 68: moveRight = true; break;
    }
};
var onKeyUp = function (event) {
    switch (event.keyCode) {
        case 38: case 87: moveForward = false; break;
        case 37: case 65: moveLeft = false; break;
        case 40: case 83: moveBackward = false; break;
        case 39: case 68: moveRight = false; break;
    }
};
document.addEventListener('keydown', onKeyDown);
document.addEventListener('keyup', onKeyUp);
Explanation: Listens for key presses and releases to control movement direction in real time. Supports both arrow keys and WASD.

Step 8: Collision Detection

function checkCollision(position) {
    var gridSize = 20;
    var halfGridSize = gridSize / 2;
    var margin = 0.1;
    if (position.x < -halfGridSize + margin || position.x > halfGridSize - margin ||
        position.z < -halfGridSize + margin || position.z > halfGridSize - margin) {
        return true;
    }
    return false;
}
Explanation: Keeps the user inside the training area by detecting when they try to walk outside the defined boundaries.

Step 9: Animation Loop

function animate() {
    requestAnimationFrame(animate);
    if (controls.isLocked) {
        var acceleration = 0.003;
        var maxSpeed = 0.05;
        if (moveForward) {
            controls.speed = Math.min(controls.speed + acceleration, maxSpeed);
            controls.moveForward(controls.speed);
            if (checkCollision(controls.getObject().position)) {
                controls.moveForward(-controls.speed);
            }
        } else if (moveBackward) {
            controls.speed = Math.min(controls.speed + acceleration, maxSpeed);
            controls.moveForward(-controls.speed);
            if (checkCollision(controls.getObject().position)) {
                controls.moveForward(controls.speed);
            }
        } else if (moveLeft) {
            controls.speed = Math.min(controls.speed + acceleration, maxSpeed);
            controls.moveRight(-controls.speed);
            if (checkCollision(controls.getObject().position)) {
                controls.moveRight(controls.speed);
            }
        } else if (moveRight) {
            controls.speed = Math.min(controls.speed + acceleration, maxSpeed);
            controls.moveRight(controls.speed);
            if (checkCollision(controls.getObject().position)) {
                controls.moveRight(-controls.speed);
            }
        } else {
            controls.speed = 0;
        }
    }
    renderer.render(scene, camera);
}
animate();
Explanation: The heart of the simulation — runs every frame, processes movement with acceleration, applies collision detection, and renders the scene.

Complete HTML File - Copy & Paste Ready

Copy the complete HTML file below. This is a fully functional template with all 9 steps integrated.

Loading complete template...

✓ How to use: Copy all the code above, create a new .html file, paste the code, update the model path, and open in your browser.