Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save ShaneBrumback/9b0e864813d0ec3f13aa664b397a5dd5 to your computer and use it in GitHub Desktop.
Save ShaneBrumback/9b0e864813d0ec3f13aa664b397a5dd5 to your computer and use it in GitHub Desktop.
Threejs Examples Loading and Animating 3D Characters

<!DOCTYPE html>
<html>
<head>
<title> Loading and Animating 3D Characters Using Threejs</title>
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
</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);
//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);
// Initialize OrbitControls
var controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.autoRotate = true; // Enable auto-rotation
controls.autoRotateSpeed = 2; // Set auto-rotation speed
// Create a grid
var gridHelper = new THREE.GridHelper(10, 50);
scene.add(gridHelper);
// Create a group for the model
var modelGroup = new THREE.Group();
scene.add(modelGroup);
// Create a mixer for the animation
var mixer;
var center = new THREE.Vector3(); // Declare the center variable outside the loader callback
// Load GLTF model
var loader = new THREE.GLTFLoader();
loader.load('https://www.shanebrumback.com/models/glb/swat/swat-character.glb', function (gltf) {
var model = gltf.scene;
modelGroup.add(model);
// Calculate the bounding box of the model
var boundingBox = new THREE.Box3().setFromObject(model);
// Get the center of the bounding box
boundingBox.getCenter(center);
// Get the size of the bounding box
var size = new THREE.Vector3();
boundingBox.getSize(size);
// Get the animations from the GLTF model
var animations = gltf.animations;
// Create a mixer and assign it to the global mixer variable
mixer = new THREE.AnimationMixer(model);
// Play all animations
animations.forEach(function (animation) {
mixer.clipAction(animation).play();
});
// Fly around the model at random distances
flyAroundModel();
});
// Function to fly around the model
function flyAroundModel() {
// Set the maximum angle to 54 degrees (π/3 radians)
var maxAngle = Math.PI / 6;
// Randomly set camera position around the model within the specified angle limit
var angle = Math.random() * maxAngle * 2 - maxAngle; // Random angle between -maxAngle and +maxAngle
var radius = Math.random() * 3 + 3; // Random distance between 5 and 15
var targetPos = new THREE.Vector3(
center.x + radius * Math.cos(angle),
center.y + radius * Math.cos(angle),
center.z + radius * Math.sin(angle)
);
// Smoothly interpolate camera position towards the target position
var duration = 2000; // Duration of the lerp animation in milliseconds
var start = new THREE.Vector3().copy(camera.position);
var startTime = performance.now();
function lerpPosition() {
var elapsed = performance.now() - startTime;
var t = Math.min(1, elapsed / duration); // Ensure t doesn't exceed 1
camera.position.lerpVectors(start, targetPos, t);
// Look at the center of the model
camera.lookAt(center);
// Render the scene
renderer.render(scene, camera);
if (t < 1) {
// Continue lerping until t reaches 1
requestAnimationFrame(lerpPosition);
} else {
// Call this function again after a random time interval between 2 to 5 seconds
var randomTimeInterval = Math.random() * 3000 + 2000;
setTimeout(flyAroundModel, randomTimeInterval);
}
}
// Start the lerping animation
lerpPosition();
}
// Render the scene
function animate() {
requestAnimationFrame(animate);
// Update the mixer
if (mixer) {
mixer.update(0.02);
}
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