Sphere object deformation after changing position of sphere - three.js

I have two sphere objects on the scene. Both of them been made with default position (scene center). There is no problem when objects are in the middle, however when I want to move one to the right and second to the left, strange deformation has a place. When spheres moving away from the center on X axis they seems to be more squeezed on Y axis. It is kind of "FishEye" lens effect. Is it possible that some default cameras value is interfering to make such a result? FOV value does not bring solution for that, and I did not find information about camera lens properties. What is wrong with that?
I have tried to play with Vector3 as a position provider and spheres has the same result.
I have tried object.position.set(vector3) with no result.
Also object.position.copy(vector3) gave the same result.
Trying translate position without animation gave the same result.
Playing with FOV parameter in camera object also did not solve the problem.
// init
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(100, window.innerWidth/window.innerHeight, 0.1,10000);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
//creating sphere
var geometry = new THREE.SphereGeometry(6, 16, 16);
var material = new THREE.MeshBasicMaterial({color: 0xffffff, wireframe: true});
var sphere = new THREE.Mesh(geometry, material);
//earth
var geometry = new THREE.SphereGeometry(3, 16, 16);
var material = new THREE.MeshBasicMaterial({color: 0x0000ff, wireframe: true});
var earth = new THREE.Mesh(geometry, material);
scene.add(sphere, earth);
camera.position.z = 10;
var animation = function(){
requestAnimationFrame(animation);
update();
renderer.render(scene,camera);
}
var update = function(){
earth.rotation.y +=0.001;
sphere.rotation.y -=0.001;
sphere.rotation.x -=0.001;
sphere.position.x +=0.001;
}
I expect to move sphere.postion.x -=1; and earth.position.x+=1; without squeezing and deformation of spheres on Y axis.

Welcome to Stack Overflow. Thank you for taking the time to take the tour, and for including your code.
The fish-eye effect is likely being caused by your camera defintion:
var camera = new THREE.PerspectiveCamera(100, window.innerWidth/window.innerHeight, 0.1,10000);
The 100 is the FOV (Field of View) for your camera, and is quite wide. In a PerspectiveCamera, the wider your FOV, the more distortion you'll see for objects closer to the edges. Try setting it lower to get a more natural effect.
Do some searches for "Perspective Distortion" and you should find a host of articles on why it happens and how to mitigate it. For starters, here's the Wikipedia page: https://en.wikipedia.org/wiki/Perspective_distortion_(photography) which has a nice animation of changing the FOV for an image of a house.

Related

Three.js: Calling lookAt() method causes mesh to disappear

I'm trying to use the three.js lookAt() method on a meshes (from CylinderBufferGeometry) so that it is oriented toward a point, but when I use the .lookAt() method, it causes the mesh to disappear from view.
The cylinder shows up fine if I comment out the .lookAt() method. I'm using a THREE.PerspectiveCamera and the THREE.WebGLRenderer incase that could have anything to do with the issue.
// Build cylinder
var cylinderRadius = 0.15
var cylinderHeight = 20
var geometry = new THREE.CylinderBufferGeometry(cylinderRadius, cylinderRadius, cylinderHeight);
var material = new THREE.MeshBasicMaterial({color: 0xffffff});
var cylinder = new THREE.Mesh(geometry, material);
// Point the cylinder up
cylinder.geometry.rotateX( Math.PI / 2);
cylinder.geometry.translate(0,0, cylinderHeight/2 );
// Move cylinder to position
cylinder.position.x = 10;
cylinder.position.y = 10;
// Look at point
cylinder.lookAt(0,0,15); // <-- ISSUE OCCURS HERE
scene.add(cylinder);
render();
Use cylinder.lookAt(new THREE.Vector3(0,0,15)); instead of cylinder.lookAt(0,0,15);

Displacement map on BoxGeometry only moves edges?

I'm just starting to get my bearings with threejs and I'm having an issue using Displacement Maps.
http://codepen.io/jpschwinghamer/pen/BWPebJ
I have a simple BoxGeometry that I'm trying to apply textures to a phong material. All seem to work correctly except for the displacement map. I made sure to add segments to the BoxGeometry instantiation. Is there some bit of magic that I'm missing to make my displacement map work correctly?
Consider this code:
var animate, camera, displacement, geometry, light, light1, map, material, mesh, normal, reflection, renderer, roughness, textureLoader;
renderer = new THREE.WebGLRenderer({
canvas: document.querySelector('canvas'),
antialiased: true
});
renderer.setClearColor(0xfff000);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
camera = new THREE.PerspectiveCamera(35, window.innerWidth / window.innerHeight, 0.1, 3000);
window.scene = new THREE.Scene();
light = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(light);
light1 = new THREE.PointLight(0xffffff, 0.6);
scene.add(light1);
textureLoader = new THREE.TextureLoader();
textureLoader.setCrossOrigin("anonymous");
map = textureLoader.load("https://s3-us-west-2.amazonaws.com/s.cdpn.io/65874/WoodFlooring044_COL_2K.jpg");
normal = textureLoader.load("https://s3-us-west-2.amazonaws.com/s.cdpn.io/65874/WoodFlooring044_NRM_2K.jpg");
roughness = textureLoader.load("https://s3-us-west-2.amazonaws.com/s.cdpn.io/65874/WoodFlooring044_GLOSS_2K.jpg");
reflection = textureLoader.load("https://s3-us-west-2.amazonaws.com/s.cdpn.io/65874/WoodFlooring044_REFL_2K.jpg");
displacement = textureLoader.load("https://s3-us-west-2.amazonaws.com/s.cdpn.io/65874/WoodFlooring044_DISP_2K.jpg");
geometry = new THREE.BoxGeometry(100, 100, 100, 10, 10, 10);
material = new THREE.MeshPhongMaterial({
map: map,
normalMap: normal,
normalScale: new THREE.Vector2(30, -1),
roughnessMap: roughness,
reflectionMap: reflection,
displacementMap: displacement,
displacementScale: 1,
displacementBias: 0
});
mesh = new THREE.Mesh(geometry, material);
mesh.position.set(0, 0, -700);
scene.add(mesh);
animate = function() {
mesh.rotation.x += 0.01;
mesh.rotation.y += 0.01;
requestAnimationFrame(animate);
return renderer.render(scene, camera);
};
animate();
The problem with your displacement map is that there is very little variation in the shades of grey (see it here).
The lowest points should be black and the highest should be white (or the other way around, I forget).
You would also need to have enough verticies for this to affect.
I think though that this map should be assigned to the bump map.
But... you probably don't want to use a bump map and normal map. it's usually one or the other.
But, having a look at the normal map you are loading, it is having no effect because it is all the same color. (see it here), so therefore, it's only the bump map that you need.
Also, MeshPhongMaterial does not seem to have roughnessMap or reflectionMap uniforms/properties, so these are doing nothing.
So basically, you only need to load you map and your displacement map, but put the displacement map on the bump map instead.
Maybe also your roughness image putting it on your specularMap.
EDIT.
Embedding code here does not seem to run because of CORS on the images.
See a FIDDLE HERE
textureLoader = new THREE.TextureLoader();
textureLoader.setCrossOrigin("anonymous");
map = textureLoader.load("https://s3-us-west-2.amazonaws.com/s.cdpn.io/65874/WoodFlooring044_COL_2K.jpg");
//normal = textureLoader.load("https://s3-us-west-2.amazonaws.com/s.cdpn.io/65874/WoodFlooring044_NRM_2K.jpg");
roughness = textureLoader.load("https://s3-us-west-2.amazonaws.com/s.cdpn.io/65874/WoodFlooring044_GLOSS_2K.jpg");
//reflection = textureLoader.load("https://s3-us-west-2.amazonaws.com/s.cdpn.io/65874/WoodFlooring044_REFL_2K.jpg");
displacement = textureLoader.load("https://s3-us-west-2.amazonaws.com/s.cdpn.io/65874/WoodFlooring044_DISP_2K.jpg");
// Create material
material = new THREE.MeshPhongMaterial({
map: map,
//normalMap: normal,
//normalScale: new THREE.Vector2(30, -1),
//roughnessMap: roughness,
//reflectionMap: reflection,
bumpMap: displacement,
bumpScale: 100,
//displacementBias: 0
specularMap: roughness
});
I believe the problem is that the BoxGeometry only contains 4 vertices per side. When you apply a displacement map, you actually move the positions of the vertices where a normal map would "fake" this on a fragment level.
To solve your problem, I would try with a geometry with a higher number of vertices. A sphere works fine for testing. Then import/generate a box geometry with more vertices.
Hope this helps!

Three.VRControls initial rotation

I've been doing through this Unable to change camera position when using VRControls and Three.js - VRControls integration - How to move in the scene? but it's not quite doing what I need.
I have a VR video app and I've just switched to VRControls with the WebVR polyfill from something old and custom. This is working well, however I'm really struggling to set the initial camera angle.
I.e. I want the camera to start pointing at a particular angle, and then rotate with the controls - however the controls always override this angle.
I've tried adding the camera to a Dolly Group or Persepective Camera, and it seems like I can move the camera but not set the initial viewing angle.
Here is how the camera is set up
container = document.getElementById('container');
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 1024);
scene = new THREE.Scene();
target = new THREE.Vector3();
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
container.appendChild(renderer.domElement);
var vrEffect = new THREE.VREffect(renderer);
vrEffect.setSize(window.innerWidth, window.innerHeight);
var params = {
hideButton: false, // Default: false.
isUndistorted: false // Default: false.
};
manager = new WebVRManager(renderer, vrEffect, params);
dolly = new THREE.PerspectiveCamera();
dolly.add( camera );
//scene.add( dolly );
controls = new THREE.VRControls(camera);// (I've tried using Dolly here)
controls.standing = true;
And I've tried various ways to rotate the camera, dolly or scene
camera.position.y = currentScene.pan * Math.PI/180;
//controls.resetPose();
//dolly.position.x = currentScene.tilt * Math.PI/180;
//camera.updateProjectionMatrix();
I can rotate the mesh, but then all the objects inside the mesh are in the wrong place.. I could try moving them but this seems like the wrong approach to point the camera to the place I want it..
The camera was getting re-added to the scene at a later time, overriding the dolly. It's working now.

Why does this ThreeJs plane appear to get a kink in it as the camera moves down the y-axis?

I have an instance of THREE.PlaneBufferGeometry that I apply an image texture to like this:
var camera, scene, renderer;
var geometry, material, mesh, light, floor;
scene = new THREE.Scene();
THREE.ImageUtils.loadTexture( "someImage.png", undefined, handleLoaded, handleError );
function handleLoaded(texture) {
var geometry = new THREE.PlaneBufferGeometry(
texture.image.naturalWidth,
texture.image.naturalHeight,
1,
1
);
var material = new THREE.MeshBasicMaterial({
map: texture,
overdraw: true
});
floor = new THREE.Mesh( geometry, material );
floor.material.side = THREE.DoubleSide;
scene.add( floor );
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, texture.image.naturalHeight * A_BUNCH );
camera.position.z = texture.image.naturalWidth * 0.5;
camera.position.y = SOME_INT;
camera.lookAt(floor.position);
renderer = new THREE.CanvasRenderer();
renderer.setSize(window.innerWidth,window.innerHeight);
appendToDom();
animate();
}
function handleError() {
console.log(arguments);
}
function appendToDom() {
document.body.appendChild(renderer.domElement);
}
function animate() {
requestAnimationFrame(animate);
renderer.render(scene,camera);
}
Here's the code pen: http://codepen.io/anon/pen/qELxvj?editors=001
( Note: ThreeJs "pollutes" the global scope, to use a harsh term, and then decorates THREE using a decorator pattern--relying on scripts loading in the correct order without using a module loader system. So, for brevity's sake, I simply copy-pasted the source code of a few required decorators into the code pen to ensure they load in the right order. You'll have to scroll down several thousand lines to the bottom of the code pen to play with the code that instantiates the plane, paints it and moves the camera. )
In the code pen, I simply lay the plane flat against the x-y axis, looking straight up the z-axis, as it were. Then, I slowly pan the camera down along the y-axis, continuously pointing it at the plane.
As you can see in the code pen, as the camera moves along the y-axis in the negative direction, the texture on the plane appears to develop a kink in it around West Texas.
Why? How can I prevent this from happening?
I've seen similar behaviour, not in three.js, not in a browser with webGL but with directX and vvvv; still, i think you'll just have to set widthSegments/heightSegments of your PlaneBufferGeometry to a higher level (>4) and you're set!

How to draw a costom cube in three.js?

I just want to draw one cube, such as one building(I got the places on the ground which is consisted of four points),and I also knew the height of the building. So how to draw? Thanks very much.
This is pretty straightforward:
http://threejs.org/docs/#Reference/Extras.Geometries/CubeGeometry
var building = new THREE.CubeGeometry(width, height, depth, 1, 1, 1);
var material = new THREE.MeshLambertMaterial({ color: 0xFF0000 });
var mesh = new THREE.Mesh(building, material);
scene.add(mesh);

Resources