How to create a 360 video from fisheye projection - javascript

I am trying to render a 360 video from a 360 fisheye projection, using Three.js (Just an example to clear up what type of projection this is: http://www.huwpenson.com/wp-content/uploads/2014/03/FISHEYE-15.jpg)
Now, I have been successfully rendering 360 videos from an equiangular projection. But I can't figure out how to set the projection type on Three.js
Here is my base code for the 360 video player:
var container, mesh;
container = document.getElementById( 'container' );
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 1100 );
camera.target = new THREE.Vector3( 0, 0, 0 );
scene = new THREE.Scene();
var geometry = new THREE.SphereGeometry( 500, 60, 40 );
geometry.scale( - 1, 1, 1 );
var video = document.createElement( 'video' );
video.width = 640;
video.height = 360;
video.autoplay = true;
video.loop = true;
video.src = "textures/pano.webm";
var texture = new THREE.VideoTexture( video );
texture.minFilter = THREE.LinearFilter;
var material = new THREE.MeshBasicMaterial( { map : texture } );
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );

Related

spotLight not attached to camera properly

I'm still struggling with getting spotLight to stick to the camera. I can see the light but looks like it stays at one place (?).
See the video for reference
//Camera
camera = new THREE.PerspectiveCamera( 90, window.innerWidth / window.innerHeight, 0.1, 1000 );
camera.position.set( 0, 1, 0 );
//spotLight attached to camera
spotlight = new THREE.SpotLight( 0xffffff, 55 );
spotlight.angle = 0.20*(Math.PI / 3);
spotlight.penumbra = 0.1;
spotlight.decay = 2;
spotlight.distance = 200;
camera.add( spotlight);
camera.add( spotlight.target );
spotlight.target.position.set( 0, 0, 1 );
spotlight.target=camera;
spotlight.position.copy( camera.position );
controls = new PointerLockControls( camera, document.body );
//adding first person camera from PointerLockControls
scene.add( controls.getObject() );
I also tried grouping camera and spotlight:
const group = new THREE.Group();
group.add(camera);
group.add(spotlight);
spotlight.target=camera;
spotlight.position.copy( camera.position );
controls = new PointerLockControls( group, document.body );
but that did not work either. What should I change? What's missing here?
//edit this is what my current code looks like
import * as THREE from "../node_modules/three/build/three.module.js";
import { GUI } from './jsm/libs/dat.gui.module.js';
let renderer, scene, camera, gui;
let spotlight, lightHelper;
function init() {
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 90, window.innerWidth / window.innerHeight, 0.1, 1000 );
camera.position.set(0,0,1);
const boxgeometry = new THREE.BoxGeometry( 25, 25, 25 );
const boxmaterial = new THREE.MeshBasicMaterial( {color: 0x00ff00} );
const cube = new THREE.Mesh( boxgeometry, boxmaterial );
scene.add( cube );
cube.position.set(-20,0,1);
const ambient = new THREE.AmbientLight( 0xffffff, 0.2 );
scene.add(ambient);
**scene.add(camera);
spotlight = new THREE.SpotLight(0xffffff, 55, 80, 0.8*Math.PI);
camera.add(spotlight);
camera.add(spotlight.target);**
let material = new THREE.MeshPhongMaterial( { color: 0x808080, dithering: true } );
let geometry = new THREE.PlaneGeometry( 2000, 2000 );
let floor= new THREE.Mesh( geometry, material );
floor.position.set( 0, - 1, 0 );
floor.rotation.x = - Math.PI * 0.5;
floor.receiveShadow = true;
scene.add(floor);
render();
window.addEventListener( 'resize', onWindowResize );
}
function animate()
{
requestAnimationFrame( animate );
camera.rotation.y+=0.01;
renderer.render( scene, camera );
}
animate();
The setup should look like so:
let camera, scene, renderer;
init();
function init() {
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.01, 10);
camera.position.z = 1;
scene = new THREE.Scene();
scene.add(camera);
const ambientLight = new THREE.AmbientLight(0xffffff, 0.4);
scene.add(ambientLight);
const spotLight = new THREE.SpotLight(0xffffff, 0.6, 0, Math.PI * 0.05);
camera.add(spotLight);
const geometry = new THREE.PlaneGeometry();
const material = new THREE.MeshPhongMaterial();
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setAnimationLoop(animation);
document.body.appendChild(renderer.domElement);
}
function animation(time) {
const t = time * 0.001;
camera.position.x = Math.sin(t) * 0.25;
camera.position.y = Math.cos(t) * 0.25;
renderer.render(scene, camera);
}
body {
margin: 0;
}
<script src="https://cdn.jsdelivr.net/npm/three#0.134.0/build/three.min.js"></script>
It's important to add the spot light as a child to the camera and the camera itself to the scene.

Rotate a face in a Three.js geometry

Hi I'm trying to make a torsional distortion using threejs. What I have is a cylinder where I want to rotate one of its end and let the other fixed, so I can recreate this effect.
What I have: Current shape
What I want: Desired shape
What I want to know is if there is a function that I can use to make the desired modification over the geometry, I have tried and I didn't find any.
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
camera.position.z = 100;
var renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
var geometry = new THREE.CylinderGeometry(50, 50, 1000, 20);
var material = new THREE.MeshBasicMaterial({wireframe: true});
var cylinder = new THREE.Mesh( geometry, material );
cylinder.rotation.z = Math.PI/2;
scene.add( cylinder );

Three js load Img in Scene

i would like to load a image in my 360 degree Scene but it dosen't work.
My Code:
<script>
var controls, camera, scene, renderer, element;
var container;
var sceneCube;
init();
animate();
function init() {
// CAMERAS
camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 100000 );
camera.position.set( 0, 0, 1000 );
cameraCube = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 100000 );
//
renderer = new THREE.WebGLRenderer();
renderer.autoClear = false;
renderer.setSize( window.innerWidth, window.innerHeight );
element = renderer.domElement;
container = document.getElementById('webglviewer');
container.appendChild(element);
//
controls = new THREE.OrbitControls( camera, element );
controls.noPan = true;
controls.noZoom = true;
// SCENE
scene = new THREE.Scene();
sceneCube = new THREE.Scene();
// Textures
var r = "textures/cube/Bridge2/";
var urls = [ r + "face_4_2048.jpg", r + "face_2_2048.jpg",
r + "face_6_2048.jpg", r + "face_5_2048.jpg",
r + "face_1_2048.jpg", r + "face_3_2048.jpg" ];
textureCube = THREE.ImageUtils.loadTextureCube( urls );
textureCube.format = THREE.RGBFormat;
textureCube.mapping = THREE.CubeReflectionMapping;
// Materials
var cubeShader = THREE.ShaderLib[ "cube" ];
var cubeMaterial = new THREE.ShaderMaterial( {
fragmentShader: cubeShader.fragmentShader,
vertexShader: cubeShader.vertexShader,
uniforms: cubeShader.uniforms,
depthWrite: true,
side: THREE.BackSide
} );
cubeMaterial.uniforms[ "tCube" ].value = textureCube;
// Skybox
cubeMesh = new THREE.Mesh( new THREE.BoxGeometry( 100, 100, 100 ), cubeMaterial );
sceneCube.add( cubeMesh );
var materials = THREE.ImageUtils.loadTexture('badge.png');
myImg = new THREE.Mesh(
new THREE.BoxGeometry( 562, 562, 562, 1, 1, 1 ),
new THREE.MeshFaceMaterial( materials ) );
sceneCube.add( myImg );
//INIT END
}
function onWindowResize() {
var width = container.offsetWidth;
var height = container.offsetHeight;
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
cameraCube.aspect = window.innerWidth / window.innerHeight;
cameraCube.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
//
function animate() {
requestAnimationFrame( animate );
render();
controls.update();
}
function render() {
var timer = -0.0002 * Date.now();
camera.lookAt( scene.position );
cameraCube.rotation.copy( camera.rotation );
renderer.render( sceneCube, cameraCube );
renderer.render( scene, camera );
}
At this position:
var materials = THREE.ImageUtils.loadTexture('badge.png');
myImg = new THREE.Mesh(
new THREE.BoxGeometry( 562, 562, 562, 1, 1, 1 ),
new THREE.MeshFaceMaterial( materials ) );
sceneCube.add( myImg );
Got this error message:
three.min.js:538 Uncaught TypeError: Cannot read property 'visible' of undefined
Many thanks for help!
Your code and the version of three.js that you are using are not the same. Your code looks like it could be compatible with three.js version r72.

Stripped shadows on collada objects

I have a scene with two collada objects and a directional light.
The first collada is pretty much a plane, and the second one is made of multiple boxes.
It appears that when the scene is rendered, some "side" shadows are really stripped, although the shadows casted on ground are pretty well rendered.
.
As I was searching for an answer, I figured out it might be a problem with my collada, so I added a basic cube to the scene (the big one above all), but it seems it has the same problem.
Does anyone have a tip or know this problem already?
I'm using the last three.js revision atm (r71), tested on Google Chrome and Mozilla Firefox (MacOS).
I already tried to tweak pretty much all the shadow* attributes of the directional light, except the ones related with shadowCascade (which I don't use).
I also tested to tweak shadow-related renderer's attributes.
Here's my light setup:
var directionalLight = new THREE.DirectionalLight( 0xffffff, 1 );
directionalLight.target.position = THREE.Vector3(0, 0, 0);
directionalLight.position.set( 250, 500, 250 );
directionalLight.castShadow = true;
directionalLight.shadowCameraNear = 100;
directionalLight.shadowCameraFar = 1000;
directionalLight.shadowMapWidth = 2048;
directionalLight.shadowMapHeight = 2048;
directionalLight.shadowBias = 0.0001;
directionalLight.shadowDarkness = 0.5;
directionalLight.shadowCameraLeft = -300;
directionalLight.shadowCameraRight = 300;
directionalLight.shadowCameraTop = 300;
directionalLight.shadowCameraBottom = -300;
directionalLight.shadowCameraVisible = true;
My collada objects are kind of big, so are my shadowCamera bounds.
My renderer setup:
renderer = new THREE.WebGLRenderer( {antialias: true} );
renderer.setClearColor(0x222222);
renderer.shadowMapEnabled = true;
renderer.shadowMapSoft = true;
renderer.shadowMapType = THREE.PCFSoftShadowMap;
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
Here's another view of the scene
(mostly showing my light setup).
EDIT: Here's a snippet:
var container;
var camera, scene, renderer, controls;
var particleLight;
scene = new THREE.Scene();
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 );
camera.position.set( 300, 100, 0 );
// Controls
controls = new THREE.OrbitControls( camera );
// Cube
var geometry = new THREE.BoxGeometry( 100, 100, 100 );
var material = new THREE.MeshLambertMaterial();
var cube = new THREE.Mesh( geometry, material );
cube.position.y = 50;
cube.rotation.y = 0.8;
cube.castShadow = true;
cube.receiveShadow = true;
scene.add( cube );
// Plane
var planeGeometry = new THREE.PlaneBufferGeometry( 300, 300, 300 );
var plane = new THREE.Mesh( planeGeometry, material );
plane.position.set( 0, 0, 0 );
plane.rotation.x = -1.6;
plane.castShadow = true;
plane.receiveShadow = true;
scene.add( plane );
// Light
var directionalLight = new THREE.DirectionalLight( 0xffffff, 1 );
directionalLight.target.position = THREE.Vector3(0, 0, 0);
directionalLight.position.set( 250, 500, 250 );
directionalLight.castShadow = true;
directionalLight.shadowCameraNear = 100;
directionalLight.shadowCameraFar = 1000;
directionalLight.shadowMapWidth = 2048;
directionalLight.shadowMapHeight = 2048;
directionalLight.shadowBias = 0.0001;
directionalLight.shadowDarkness = 0.5;
directionalLight.shadowCameraLeft = -300;
directionalLight.shadowCameraRight = 300;
directionalLight.shadowCameraTop = 300;
directionalLight.shadowCameraBottom = -300;
directionalLight.shadowCameraVisible = true;
scene.add( directionalLight );
scene.add( new THREE.AmbientLight( 0x555555 ) );
renderer = new THREE.WebGLRenderer( {antialias: true} );
renderer.setClearColor(0x222222);
renderer.shadowMapEnabled = true;
renderer.shadowMapSoft = true;
renderer.shadowMapType = THREE.PCFSoftShadowMap;
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
requestAnimationFrame( animate );
render();
}
var clock = new THREE.Clock();
function render() {
var timer = Date.now() * 0.0005;
camera.lookAt(new THREE.Vector3(0, 0, 0));
renderer.render( scene, camera );
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r71/three.min.js"></script>
<script src="http://threejs.org/examples/js/controls/OrbitControls.js"></script>
Thanks in advance.
You are getting self-shadowing because the rays of the directional light are exactly parallel to some of the faces of your geometry. Move the directional light to a slightly different location. For example,
directionalLight.position.set( 250, 500, 200 );
Usually, light.shadow.bias is used to remedy self-shadowing problems, but it is not going to be effective when the light ray and face are parallel, as in your case.
Also, set shadow.bias to be negative to help alleviate artifacts on other faces.
directionalLight.shadow.bias = - 0.01;
This unfortunately will result, as it usually does, in another artifact: "Peter Panning".
These kinds of trade-offs are common. You are just going to have to find an acceptable compromise. (Maybe set the bias based on camera position.)
three.js r.75

Strange overlapping rendering in THREE.js (and some shadow issues)

This is my second foray into the world of THREE.js, the first being a short one. I just set up this scene to try some things out. It's a flat box mesh with three box meshes sitting on it. For some reason, the boxes on top are being rendered behind certain polygons of the ground mesh. Anyone have any idea why this is? Does it have something to do with the scale of the scene, or some setting I'm missing? Thanks.
While I have you, does anyone know why the meshes aren't casting directional light shadows onto the ground mesh?
Fiddle: http://jsfiddle.net/k8E43/1/
var scene, camera, renderer;
var material;
var player, ground, mesh1, mesh2;
var directionalLight, spotLight, ambientLight;
init();
animate();
function init() {
renderer = new THREE.CanvasRenderer();
renderer.shadowMapEnabled = true;
renderer.shadowMapSoft = true;
renderer.setSize( window.innerWidth, window.innerHeight );
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.x = 0;
camera.position.y = 450;
camera.position.z = 750;
camera.lookAt( new THREE.Vector3( 0, 150, 0 ) );
material = new THREE.MeshLambertMaterial( { color: 0xffffff } );
// Meshes
player = new THREE.Mesh( new THREE.BoxGeometry( 70, 160, 70 ), material );
player.position.y = 80;
player.castShadow = true;
player.receiveShadow = true;
scene.add( player );
ground = new THREE.Mesh( new THREE.BoxGeometry( 1000, 10, 600 ), material );
ground.position.y = -5;
ground.receiveShadow = true;
scene.add( ground );
mesh1 = new THREE.Mesh( new THREE.BoxGeometry( 100, 40, 100 ), material );
mesh1.position.x = -150;
mesh1.position.y = 20;
mesh1.position.z = 100;
mesh1.castShadow = true;
mesh1.receiveShadow = true;
scene.add( mesh1 );
mesh2 = new THREE.Mesh( new THREE.BoxGeometry( 100, 200, 100 ), material );
mesh2.position.x = 150;
mesh2.position.y = 100;
mesh2.position.z = -100;
mesh2.castShadow = true;
mesh2.receiveShadow = true;
scene.add( mesh2 );
// Lights
directionalLight = new THREE.DirectionalLight( 0xffffff, 0.5 );
directionalLight.position.x = -1000;
directionalLight.position.y = 500;
directionalLight.position.z = -1000;
directionalLight.target.position.x = 1000;
directionalLight.target.position.y = -500;
directionalLight.target.position.z = 1000;
directionalLight.castShadow = true;
scene.add( directionalLight );
ambientLight = new THREE.AmbientLight( 0x404040 );
scene.add( ambientLight );
document.body.appendChild( renderer.domElement );
}
var lightIncreasing = false;
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
}

Categories

Resources