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();
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);
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());
Step 4: Lighting
var ambientLight = new THREE.AmbientLight(0xffffff, 2);
scene.add(ambientLight);
Step 5: Keyboard Movement Variables
var moveForward = false;
var moveBackward = false;
var moveLeft = false;
var moveRight = false;
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); }
);
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);
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;
}
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();