Last active
March 19, 2024 05:17
-
-
Save ShaneBrumback/b5f7b30dee18e00b79423dd7a9816363 to your computer and use it in GitHub Desktop.
Threejs Examples Loading & Animating Mandalorian Grogu 3D Model
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!--//////////////////////////////////////////////////////////////////////////////////////// | |
/// /// | |
/// 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