Three.js - Things disappear when zooming out - javascript

In my three.js project I use a high z position for my camera.
When the z position is too high my scene becomes black.
So, when I zoom out it becomes black. But I don't want that to happen.
This is how it is with camera.position.z = 3000;
And when I zoom out, just one zoom, it is like this:
For the controls I use OrbitControls, My camera is like:
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 3000);
camera.position.z = 3000;
And here the code for the planet and some planets' orbits:
var scene = new THREE.Scene();
var material = new THREE.MeshLambertMaterial({
map: THREE.ImageUtils.loadTexture("assets/img/sun.jpg")
});
var sun = new THREE.Mesh(new THREE.SphereGeometry(200, 50, 50), material);
scene.add(sun);
var orbitLine = function(radius,y)
{
var segments = 64,
line_material = new THREE.LineBasicMaterial( { color: 0xffffff } ),
geometry = new THREE.CircleGeometry( radius, segments );
geometry.vertices.shift();
var orbit = new THREE.Line( geometry, line_material );
if(y)
orbit.position.y=y;
else if(!y)
orbit.position.y=0;
scene.add(orbit);
};
var Mercury_orbit = orbitLine(400,-70);
var Venus_orbit = orbitLine(700,70);
var Earth_orbit = orbitLine(900,70);
var Mars_orbit = orbitLine(1250,70);
var Jupiter_orbit = orbitLine(3000,70);
Couldn't provide a fiddle as for some reason it didn't work.
If you need more code tell me in the comments and I will add it.
Any ideas?
thanks.

Your camera's far plane is at 3000 which means everything that is 3000 units away will be clipped and not drawn.
At the same time you have placed your camera at (0,0,3000) so you are right on the position where things will start to disappear.

Related

How to load all models with the same size and the same camera position?

I'm setting up a website that loads 3d models in ply format, and I'm using Three.js with his PLYLOADER to do that.
My problem is that every model is loading in a different position. I've managed to make them load in a perpendicular way with the ground, but some of them are looking, some are looking far away from the camera and others look like they turn around a Y axis (not their center).
This is my HTML div:
<div id="WebGL-output"></div>
This is my JS code:
<script type="text/javascript">
var lesson7 = {
scene: null,
camera: null,
renderer: null,
container: null,
controls: null,
clock: null,
stats: null,
init: function() { // Initialization
// create main scene
this.scene = new THREE.Scene();
this.scene.fog = new THREE.FogExp2(0xcce0ff, 0.0003);
var SCREEN_WIDTH = '800',
SCREEN_HEIGHT = '600';
// prepare camera
var VIEW_ANGLE = 60, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 0.1, FAR = 20000;
this.camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR);
this.scene.add(this.camera);
this.camera.position.set(0, 0, 300);
this.camera.lookAt(new THREE.Vector3(0,0,0));
// prepare renderer
this.renderer = new THREE.WebGLRenderer({ antialias:true });
this.renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
this.renderer.setClearColor(this.scene.fog.color);
this.renderer.shadowMapEnabled = true;
this.renderer.shadowMapSoft = true;
// prepare container
this.container = document.getElementById('WebGL-output');
this.container.appendChild(this.renderer.domElement);
// events
THREEx.WindowResize(this.renderer, this.camera);
// prepare controls (OrbitControls)
this.controls = new THREE.OrbitControls(this.camera, this.renderer.domElement);
this.controls.target = new THREE.Vector3(0, 0, 0);
this.controls.maxDistance = 20000;
// prepare clock
this.clock = new THREE.Clock();
this.scene.add( new THREE.AmbientLight(0xFFFFFF) );
// light
var dirLight = new THREE.DirectionalLight(0x606060);
dirLight.position.set(200, 200, 1000).normalize();
this.camera.add(dirLight);
this.camera.add(dirLight.target);
// load models
this.loadModels();
},
loadModels: function() {
// prepare PLY loader and load the model
var scene = new THREE.Scene();
var oPlyLoader = new THREE.PLYLoader();
oPlyLoader.load("../models/{{ $analysis->three_d_model }}", function(geometry) {
var material = new THREE.MeshPhongMaterial( { color: 0xAAAAAA, specular: 0x111111, shininess: 0 } );
var meshMaterial = material;
// if (geometry.hasColors) { // to fix when models will have colors
meshMaterial = new THREE.MeshPhongMaterial({ opacity: 1, vertexColors: THREE.VertexColors });
// }
var mesh = new THREE.Mesh(geometry, meshMaterial);
// Solution: center mesh to world origin
mesh.geometry.computeBoundingBox();
var bbox = mesh.geometry.boundingBox;
var centerVec = new THREE.Vector3();
bbox.getCenter(centerVec); // get center of bbox into centerVec
// move mesh so that center of bbox is placed to world origin
mesh.applyMatrix(new THREE.Matrix4().makeTranslation(-centerVec.x, -centerVec.y, -centerVec.z));
// proceed doing stuff
// mesh.position.set(0, -6, 0);
// mesh.scale.set(5, 5, 5);
lesson7.scene.add(mesh);
});
}
};
// Animate the scene
function animate() {
requestAnimationFrame(animate);
render();
update();
}
// Update controls and stats
function update() {
lesson7.controls.update(lesson7.clock.getDelta());
// lesson7.stats.update();
}
// Render the scene
function render() {
if (lesson7.renderer) {
lesson7.renderer.render(lesson7.scene, lesson7.camera);
}
}
// Initialize lesson on page load
function initializeLesson() {
lesson7.init();
animate();
}
if (window.addEventListener)
window.addEventListener('load', initializeLesson, false);
else if (window.attachEvent)
window.attachEvent('onload', initializeLesson);
else window.onload = initializeLesson;
</script>
I need help to make them all load with the same camera position, looking centred and in the same size.
PS: If i can have better results loading in different extension, I'm up for it.
Thanks in advance
EDIT:
I updated the code with the help of #alex. Now my models are very well centered. The only thing missing now si a fixed camera position however the model was saved
Currently see two solutions here ( if i understand correctly )
You objects are not centered correctly. The solution would be to open the model files in a 3d editor and set them all to the same size and make their center points consistent.
Once you load the model add it to an Object3D and find its center.
Docs about that here: https://threejs.org/docs/#api/en/core/Object3D
the below code this.objectAll is the Object3D. Which is put into a box and we make the controls look at the center of that box. If all model are consistent then this should work.
this.boundingBox = new THREE.Box3();
this.boundingBox.setFromObject(this.objectAll);
this.boundingBox.center(this.controls.target);
Best of luck!

ThreeBSP wrong result

I'm having some troubles with a tube in Three.JS. I have to cut it at 45 degrees and then connect this tube with another one (a connection with "L" form).
My idea is this:
- I create a cube
- I change the position of the cube
- I use a substration between the tube and the cube to get the result
I found that the "subtract" function gives to me a strange result.
Here there is the simplified code (here the cube is not rotated but I will need to rotate it to get my result) and the image the with the undesired result (inside the yellow rectangle).
var cube = new THREE.CubeGeometry(25, 25, 25);
var cMesh = new THREE.Mesh(cube);
cMesh.position.y=100;
cMesh.updateMatrix();
var path = new THREE.LineCurve3(new THREE.Vector3(0, 100, 0), new THREE.Vector3(0,-100, 0));
var geometry = new THREE.TubeGeometry(path, 20, 2, 18, false);
material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
mesh = new THREE.Mesh(geometry, material);
var geom1 = new ThreeBSP(mesh);
var geom2=new ThreeBSP(cMesh);
var geomF=geom1.subtract(geom2);
mesh = geomF.toMesh();
problem detail

three.js skybox: obvious corners and lots of distortion

Today I've been experimenting with building my first ever skybox in three.js. I've read a lot of tutorials and the code I've ended up with is based on this one: http://learningthreejs.com/blog/2011/08/15/lets-do-a-sky/
I did make a few changes in order to allow for the images to load first, and to make it compatible with the version of three.js which I am using.
I've overcome a lot of small problems to get to the point I am currently at, but cannot find any answer to my current issue despite having searched quite hard. My problem is that despite using purpose-built skybox textures downloaded from the internet, it is glaringly obvious that my skybox is a cube with corners and edges. The textures appear heavily distorted and are not at all convincing.
Here is a screenshot of how my skybox looks:
And here is a link to the site from which I downloaded the images:
http://www.humus.name/index.php?page=Cubemap&item=Yokohama3
As you can see, in their preview it looks much better.
I've tried this with a few different downloaded textures and every time it is very obvious that you are looking at the inside of a cube.
Here's my code (I'm including all my code, not just the section which creates the skybox):
var scene;
var camera;
var renderer;
function createRenderer () {
renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0x000000, 1.0)
renderer.setSize(window.innerWidth, window.innerHeight)
renderer.shadowMapEnabled = true;
//renderer.shadowCameraNear = 0.5;
//renderer.shadowCameraFar = 500;
}
function createCamera () {
camera = new THREE.PerspectiveCamera(
45,
window.innerWidth/window.innerHeight,
0.1, 1000
);
camera.position.x = 50;
camera.position.y = 30;
camera.position.z = 40;
camera.lookAt(scene.position);
}
function createPlane () {
var material = new THREE.MeshLambertMaterial({
color: 0xcccccc,
})
var geometry = new THREE.PlaneGeometry(40, 40)
var plane = new THREE.Mesh(geometry, material)
plane.receiveShadow = true;
plane.rotation.x = -Math.PI/2
plane.position.y = -6;
scene.add(plane)
}
function createLight () {
var spotLight = new THREE.DirectionalLight(0xffffff);
spotLight.position.set( 0, 50, 20 );
spotLight.shadowCameraVisible = true;
spotLight.shadowDarkness = 0.5
spotLight.shadowCameraNear = 0;
spotLight.shadowCameraFar = 100;
spotLight.shadowCameraLeft = -50;
spotLight.shadowCameraRight = 50;
spotLight.shadowCameraTop = 50;
spotLight.shadowCameraBottom = -50;
spotLight.castShadow = true;
scene.add(spotLight);
}
function createSkyboxAndSphere () {
var urlPrefix = "Yokohama3/";
var urls = [ urlPrefix + "posx.jpg", urlPrefix + "negx.jpg",
urlPrefix + "posy.jpg", urlPrefix + "negy.jpg",
urlPrefix + "posz.jpg", urlPrefix + "negz.jpg" ];
var textureCube = THREE.ImageUtils.loadTextureCube( urls , undefined, function () {;
var shader = THREE.ShaderLib["cube"];
var uniforms = THREE.UniformsUtils.clone( shader.uniforms );
shader.uniforms['tCube'].value = textureCube; // textureCube has been init before
var material = new THREE.ShaderMaterial({
fragmentShader : shader.fragmentShader,
vertexShader : shader.vertexShader,
uniforms : shader.uniforms,
depthWrite : false,
side: THREE.BackSide,
});
var geometry = new THREE.BoxGeometry(100, 100, 100)
var skybox = new THREE.Mesh(geometry, material)
scene.add(skybox)
var material = new THREE.MeshPhongMaterial({
color: "red",
envMap: textureCube,
reflectivity: 0.3,
})
var geometry = new THREE.SphereGeometry(6, 30, 15)
var sphere = new THREE.Mesh(geometry, material)
sphere.castShadow = true;
sphere.receiveShadow = true;
scene.add(sphere)
});
}
function init () {
scene = new THREE.Scene();
createRenderer();
createCamera();
createLight();
createPlane ();
createSkyboxAndSphere ();
document.getElementById("container").appendChild(renderer.domElement)
render ()
}
function render () {
renderer.render(scene, camera)
requestAnimationFrame(render);
}
window.onload = function () {
init ();
}
I suspect I am fundamentally misunderstanding something about how cubemapping and skyboxes work - I am very new to this in particular and javascript in general and am aware of huge gaps in my knowledge.
My apologies if the answer to this is obvious and/or the question has been asked before, and a pre-emptive thanks for your help!
Your camera needs to be in the center of the skybox -- or at least near the center.
So either move your camera very close to the box center, or update the box position every frame to match the camera position.
Or make the skybox much bigger relative to the camera offset from the origin.
Or place the skybox in a separate scene and have two cameras and two render passes, as in this example.
three.js r.74

three.js edges and text jagged/blurry on rotation

I'm a three.js beginner. Trying to apply an html canvas as texture to plane geometry. Works fine when there is no rotation. When rotated, a) outside edges of the mesh become jagged (edges/lines within the image are fine) and b) text becomes blurry.
What do I have to do to keep outside edges and text crisp?
My texture is power-of-two (128 x 512). Turning antialiasing on doesn't help.
Here is a screenshot without rotation
And here with rotation.
Code looks like this:
var eltTexture = toTexture2(d, this, go.w, go.Res.ow[0]);
// map texture to material
var material = new THREE.MeshBasicMaterial(
{ map : eltTexture } );
//define sub image of texture to be applied to mesh
var cutout = [
new THREE.Vector2(0, (128 - go.Res.ow[0])/128),
new THREE.Vector2(go.w/512, (128 - go.Res.ow[0])/128),
new THREE.Vector2(go.w/512, 1),
new THREE.Vector2(0, 1)];
// geometry and UV mapping
var geometry = new THREE.PlaneGeometry (go.w, go.Res.ow[0]);
geometry.faceVertexUvs[0] = []; // initialize
geometry.faceVertexUvs[0][0] =
[cutout[3], cutout[0], cutout[2]];
geometry.faceVertexUvs[0][1] =
[cutout[0], cutout[1], cutout[2]];
var mesh = new THREE.Mesh( geometry, material );
mesh.position.set(d.threeX, d.threeY, d.threeX);
mesh.rotation.set(0,0.6,0);
scene.add( mesh );
});
renderer.render( scene, camera );
function toTexture2 (d, svgNode, svgWidth, svgHeight){
// step 1: serialize eltSVG to xml
var eltXML = new XMLSerializer().serializeToString(svgNode);
eltXML = 'data:image/svg+xml;charset = utf8,' + eltXML;
// step 2: draw eltXML to image
var eltImage = document.body.appendChild(
document.createElement("img"));
eltImage.id = "eltImage";
eltImage.style.display = "none";
eltImage.width = svgWidth;
eltImage.height = svgHeight;
eltImage.src = eltXML;
// step 3: draw image to canvas
// NOTE: define canvas parameters position, width and
// height in html, NOT IN CSS, otherwise image
// will become blurry - don't ask why!
var eltCanvas = document.body.appendChild(
document.createElement("canvas"));
eltCanvas.id = "eltCanv";
eltCanvas.style.display = "none";
eltCanvas.width = 512;
eltCanvas.height = 128;
// get context
var ctx = eltCanvas.getContext("2d", {alpha: false});
// draw svg element to canvas, not including portrait image
ctx.drawImage(eltImage, parseInt(0), parseInt(0),
svgWidth, svgHeight);
// draw portrait image to canvas
var portrait = document.getElementById(d.nameConcat + "Img");
ctx.globalAlpha = 0.6; // opacity of portrait image
ctx.drawImage(portrait, go.Res.strw[0], go.Res.strw[0],
go.Res.iw[0], go.Res.iw[0]);
var texture = new THREE.Texture(eltCanvas);
texture.needsUpdate = true;
return texture;
} // function toTexture2
Many thanks in advance for your help!
Even though it's been a long time since you've posted this, I have the solution in case anyone else is experiencing the same issue.
Add this to your renderer:
const renderer = new THREE.WebGLRenderer({antialias: true});

Three.js not displaying anything

I have been doing some experiments with three.js. However, when I try to do a simple test, I can't get it to display anything. Here's my code. If someone could tell me what I'm missing it would be really helpful.
//Constant declaration
var RENDER_DIST = 1000,
FOV = 75;
var WIDTH = window.innerWidth,
HEIGHT= window.innerHeight;
//Create the scene
var scene = new THREE.Scene();
//Create the camera
var camera = new THREE.PerspectiveCamera(FOV, WIDTH / HEIGHT, 0.1, RENDER_DIST);
//Pull the camera back a bit
camera.z = 100;
//Then add it to the scene
scene.add(camera);
//Create a renderer
renderer = new THREE.WebGLRenderer();
renderer.setSize(WIDTH,HEIGHT);
renderer.domElement.className = "glMain";
//Container is a div
$("#container").html(renderer.domElement);
//Boilerplate done! Celebrate!
(function init() {
var geometry = new THREE.SphereGeometry(50);
var material = new THREE.MeshBasicMaterial({color: 0xff0000});
var sphere = new THREE.Mesh(geometry, material);
scene.add(sphere);
//debugging
console.log("Sphere at " + sphere.position.x + " " + sphere.position.y + " " + sphere.position.z);
})();
//Our main function
(function loopRun() {
requestAnimationFrame(loopRun);
console.log("rendered");
renderer.render(scene, camera);
})();
On the console log I am getting all the "rendered" messages but nothing is displaying. I have checked that the canvas is the right size and it is, so I have no idea what is wrong. I have tried a few different geometries.
EDIT: I am using Chrome, and online three.js examples work fine. There are no errors on the console log.
//Pull the camera back a bit
camera.position.z = 100;
//Container is a div
document.body.appendChild(renderer.domElement);
you can also try :
$("#container").append(renderer.viewElement);

Categories