Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save ShaneBrumback/b5f7b30dee18e00b79423dd7a9816363 to your computer and use it in GitHub Desktop.
Save ShaneBrumback/b5f7b30dee18e00b79423dd7a9816363 to your computer and use it in GitHub Desktop.
Threejs Examples Loading & Animating Mandalorian Grogu 3D Model
<!--////////////////////////////////////////////////////////////////////////////////////////
/// ///
/// Example Using Three.js Library, HTML, CSS & JavaScript ///
// 3D Interactive Web Apps & Games 2021-2024 ///
/// Contact Shane Brumback https://www.shanebrumback.com ///
/// Send a message if you have questions about this code ///
/// I am a freelance developer. I develop any and all web. ///
/// Apps Websites 3D 2D CMS Systems etc. Contact me anytime :) ///
/// ///
////////////////////////////////////////////////////////////////////////////////////////////-->
<!DOCTYPE html>
<html>
<head>
<title>Three.js Examples - Loading & Animating Mandalorian Grogu 3D Model</title>
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
background-color: black
}
</style>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/three@latest/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@latest/examples/js/controls/OrbitControls.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@latest/examples/js/loaders/GLTFLoader.js"></script>
<script>
// Set up the scene, camera, and renderer
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
var controls;
//Set up the renderer
let renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.toneMapping = THREE.ReinhardToneMapping;
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
renderer.domElement.id = 'renderer';
renderer.setClearColor(0x000000, 1); // Set background color to black
renderer.domElement.style.position = 'fixed';
renderer.domElement.style.zIndex = '-1';
renderer.domElement.style.left = '0';
renderer.domElement.style.top = '0';
document.body.appendChild(renderer.domElement);
// Add ambient light
var ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambientLight);
// Add directional light
var directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
directionalLight.position.set(1, 1, 1);
scene.add(directionalLight);
// Create a grid
var gridHelper = new THREE.GridHelper(100, 100);
scene.add(gridHelper);
// Create a raycaster for interaction
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
// Create a group for the model
var modelGroup = new THREE.Group();
scene.add(modelGroup);
// Create a mixer for the animation
var mixer;
// Load GLTF model
var loader = new THREE.GLTFLoader();
loader.load('../models/glb/fortnite_the_mandalorianbaby_yoda.glb', function (gltf) {
var model = gltf.scene;
model.scale.set(0.25, 0.25, 0.25);
model.position.z = 5.5
modelGroup.add(model);
// Calculate the bounding box of the model
var boundingBox = new THREE.Box3().setFromObject(model);
// Get the center of the bounding box
var center = new THREE.Vector3();
boundingBox.getCenter(center);
// Get the size of the bounding box
var size = new THREE.Vector3();
boundingBox.getSize(size);
// Move the model's origin to the bottom of its bounding box
model.position.y -= boundingBox.min.y;
// Move the model to the scene's origin (0, 0, 0)
model.position.sub(center);
// Move the modelGroup to match the position of the bounding box
modelGroup.position.copy(center);
// Calculate the distance to the model based on the bounding box size
var maxDim = Math.max(size.x, size.y, size.z);
var distance = maxDim / Math.tan(THREE.MathUtils.degToRad(camera.fov * 0.8));
// Adjust the camera position to fit the entire model in the view
var cameraDistance = distance + maxDim;
camera.position.copy(center);
camera.position.z += cameraDistance;
camera.position.y += distance * 0.8; // Adjust the height of the camera to better frame the model
camera.lookAt(center);
// Initialize OrbitControls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.autoRotate = true;
controls.target.copy(center); // Set the controls target to the center of the model
// Get the animations from the GLB model
var animations = gltf.animations;
// Create a mixer and assign it to the global mixer variable
mixer = new THREE.AnimationMixer(model);
// Play the first animation
var action = mixer.clipAction(animations[0]);
action.play();
});
// Handle mouse click
function onMouseClick(event) {
// Calculate mouse position in normalized device coordinates
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
// Update the picking ray with the camera and mouse position
raycaster.setFromCamera(mouse, camera);
// Check for intersections only with the model group
var intersects = raycaster.intersectObjects(modelGroup.children, true);
if (intersects.length > 0) {
//do something when the model is clicked
}
}
// Add event listener for mouse click
window.addEventListener('click', onMouseClick, false);
// Render the scene
function animate() {
requestAnimationFrame(animate);
// Update the mixer
if (mixer) {
mixer.update(0.02);
}
// Update the OrbitControls to enable automatic rotation if the controls variable exists
if (controls) {
controls.update();
}
renderer.render(scene, camera);
}
animate();
// Add window resize event listener
window.addEventListener('resize', onWindowResize);
// Function to handle window resize event
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment