Skip to content

Instantly share code, notes, and snippets.

@markstrefford
Created April 30, 2021 19:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save markstrefford/fdb61b2d2ea1fec3760d7834422eef1f to your computer and use it in GitHub Desktop.
Save markstrefford/fdb61b2d2ea1fec3760d7834422eef1f to your computer and use it in GitHub Desktop.
Using videos as textures in three.js
<video id="video" crossorigin="anonymous" style="display: none; position: absolute; left: 15px; top: 75px;"
type="video/mp4"
src="Video-url.mp4" controls="false" autoplay="true">
</video>
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader'
import Stats from 'three/examples/jsm/libs/stats.module'
import { GUI } from 'three/examples/jsm/libs/dat.gui.module'
// import { config } from './config';
const scene = new THREE.Scene();
const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);
scene.background = new THREE.Color('black');
let light
light = new THREE.PointLight();
light.position.set(2.5, 7.5, 15);
scene.add(light);
light = new THREE.AmbientLight( 0x404040 ); // soft white light
light.intensity = 2.0;
light.position.set(2, 8, 15);
scene.add( light );
const ambiLight = new THREE.AmbientLight(0x141414);
scene.add(ambiLight);
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0.8, 1.4, 1.0);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const controls = new OrbitControls(camera, renderer.domElement);
controls.screenSpacePanning = true;
controls.target.set(0, 1, 0);
let mixer = THREE.AnimationMixer;
let modelReady = false;
let animationActions = new Array();
let activeAction = THREE.AnimationAction;
let lastAction = THREE.AnimationAction;
const fbxLoader = new FBXLoader();
const rotateObject = (object, degreeX=0, degreeY=0, degreeZ=0) => {
object.rotateX(THREE.Math.degToRad(degreeX));
object.rotateY(THREE.Math.degToRad(degreeY));
object.rotateZ(THREE.Math.degToRad(degreeZ));
}
const createVideoWall = (video, yRotation) => {
const geometry = new THREE.PlaneGeometry( 9, 5, 32 );
const material = new THREE.MeshBasicMaterial({map: videoTexture});
const plane = new THREE.Mesh( geometry, material );
rotateObject(plane, 0, yRotation, 0)
return plane
}
console.log('Loading video stream');
let plane;
const arena = new THREE.Group();
const video = document.getElementById('video');
const videoTexture = new THREE.VideoTexture(video);
// const geometry = new THREE.PlaneGeometry( 9, 5, 32 );
// const material = new THREE.MeshBasicMaterial({map: videoTexture});
// const plane = new THREE.Mesh( geometry, material );
plane = createVideoWall(videoTexture, 0);
plane.position.set(0, 0, -4.5);
arena.add(plane);
plane = createVideoWall(videoTexture, 180);
plane.position.set(0, 0, 4.5);
arena.add(plane);
plane = createVideoWall(videoTexture, 90);
plane.position.set(-4.5, 0, 0);
arena.add(plane);
plane = createVideoWall(videoTexture, -90);
plane.position.set(4.5, 0, 0);
arena.add(plane);
scene.add(arena);
video.play();
console.log('Video loaded!');
fbxLoader.load(
'man.fbx',
(object) => {
object.scale.set(.005, .005, .005);
mixer = new THREE.AnimationMixer(object);
let animationAction = mixer.clipAction((object).animations[0]);
animationActions.push(animationAction);
animationsFolder.add(animations, "default");
activeAction = animationActions[0];
scene.add(object);
// add an animation from another file
fbxLoader.load('man@running.fbx',
(object) => {
console.log("loaded running")
let animationAction = mixer.clipAction(object.animations[0]);
animationActions.push(animationAction)
console.log(animations);
animationsFolder.add(animations, "running")
//add an animation from another file
fbxLoader.load('man@hiphop.fbx',
(object) => {
console.log("loaded hiphop")
let animationAction = mixer.clipAction(object.animations[0]);
animationActions.push(animationAction)
animationsFolder.add(animations, "hiphop")
//add an animation from another file
fbxLoader.load('man@walking.fbx',
(object) => {
console.log("loaded walking");
object.animations[0].tracks.shift() //delete the specific track that moves the object forward while running
//console.dir((object as any).animations[0])
let animationAction = mixer.clipAction(object.animations[0]);
animationActions.push(animationAction)
animationsFolder.add(animations, "walking")
modelReady = true
},
(xhr) => {
console.log('walking: ' + (xhr.loaded / xhr.total * 100) + '% loaded')
},
(error) => {
console.log('walking: ' + error);
}
)
},
(xhr) => {
console.log('hiphop: ' + (xhr.loaded / xhr.total * 100) + '% loaded')
},
(error) => {
console.log('hiphop: ' + error);
}
)
},
(xhr) => {
console.log('running: ' + (xhr.loaded / xhr.total * 100) + '% loaded')
},
(error) => {
console.log('running: ' + error);
}
)
},
(xhr) => {
console.log((xhr.loaded / xhr.total * 100) + '% loaded')
},
(error) => {
console.log(error);
}
)
window.addEventListener('resize', onWindowResize, false)
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
render();
}
const stats = Stats()
document.body.appendChild(stats.dom)
const animations = {
default: function () {
setAction(animationActions[0])
},
running: function () {
setAction(animationActions[1])
},
hiphop: function () {
setAction(animationActions[2])
},
walking: function () {
setAction(animationActions[3])
},
}
const setAction = (toAction) => {
if (toAction != activeAction) {
lastAction = activeAction
activeAction = toAction
lastAction.stop()
//lastAction.fadeOut(1)
activeAction.reset()
//activeAction.fadeIn(1)
activeAction.play()
}
}
const gui = new GUI()
const animationsFolder = gui.addFolder("Animations")
animationsFolder.open()
const clock = new THREE.Clock()
const animate = () => {
requestAnimationFrame(animate)
controls.update()
if (modelReady) mixer.update(clock.getDelta());
render()
stats.update()
};
function render() {
renderer.render(scene, camera)
}
animate();
@markstrefford
Copy link
Author

Loads video as three.is textures and loads animated FBX character such as those from mixamo.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment