I am playing around with the WebGL Globe and have got it to rotate, but can't figure out how to position it so that it is not in the center of the scene.
I have altered the code at https://code.google.com/r/fxnstyling-webgl-globe-autospin/source/browse/ to be:
mesh = new THREE.Mesh(geometry, material);
mesh.position = new THREE.Vector3(1000, 500, 300)
mesh.matrixAutoUpdate = false;
scene.addObject(mesh);
How can I change the position of the globe?
You have matrixAutoUpdate set to false, so the position isn't going to be updated until you explicitly call update again. Try calling mesh.updateMatrix() when you need the position to be updated.
Related
I am looking to produce an effect very similar to the following example:
https://threejs.org/examples/?q=trails#webgl_trails
However, I would like to make the old trail fade into the background over time -- rather than just persist into an increasingly messy screen.
It seems that the following code will allow you to draw over previous frames without clearing them:
renderer = new THREE.WebGLRenderer( { preserveDrawingBuffer: true } );
renderer.autoClearColor = false;
But I am unsure how to make each frame fade into the background as new frames a drawn on top. It seems like painting over the screen with a somewhat transparent color would work, but I'm not sure how to approach that.
There's now an example using the postprocessing EffectComposer and AfterImagePass.
https://threejs.org/examples/webgl_postprocessing_afterimage.html
You could easily take the example you showed above, and create a very faint black plane that sits directly in front of the camera:
// Make highly-transparent plane
var fadeMaterial = new THREE.MeshBasicMaterial({
color: 0x000000,
transparent: true,
opacity: 0.01
});
var fadePlane = new THREE.PlaneBufferGeometry(1, 1);
var fadeMesh = new THREE.Mesh(fadePlane, fadeMaterial);
// Create Object3D to hold camera and transparent plane
var camGroup = new THREE.Object3D();
var camera = new THREE.PerspectiveCamera();
camGroup.add(camera);
camGroup.add(fadeMesh);
// Put plane in front of camera
fadeMesh.position.z = -0.1;
// Make plane render before particles
fadeMesh.renderOrder = -1;
// Add camGroup to scene
scene.add(camGroup);
This will make sure that every time the scene is rendered, it'll slowly fade the previously-rendered particles to black. You'll need to play with the opacity of fadeMaterial and position of fadeMesh to get the desired effect.
renderOrder = -1; makes sure that you render the plane first (fading out previous particles), and then render the particles, to avoid covering the newest ones.
I'm trying to create a very simple scene containing a triangular planar face continuously rotating about the x axis.
Here's the code creating the geometry object, as indicated in this previous SO question:
// create triangular plane geometry
var geometry_1 = new THREE.Geometry();
var v1 = new THREE.Vector3(0,0,0);
var v2 = new THREE.Vector3(3,0,0);
var v3 = new THREE.Vector3(0,3,0);
geometry_1.vertices.push(v1);
geometry_1.vertices.push(v2);
geometry_1.vertices.push(v3);
geometry_1.faces.push(new THREE.Face3(0, 1, 2));
The animation function renders the scene and adds a small rotation to the mesh:
function animate() {
requestAnimationFrame( animate );
mesh_1.rotation.x += 0.005;
renderer.render( scene, camera );
}
Everything works fine until the value of mesh.rotation.x goes into the [Math.PI, 2*Math.PI] interval, at which point it disappears for exactly half of the cycle. This JSFiddle replicates the behavior I'm observing.
This is not a light problem, as there are an ambient light and a directional light supposed to illuminate the mesh at all points of it revolution.
This should not be a material problem, as I did set its side property to THREE.DoubleSide and in fact in the interval mesh.rotation.x into [0, Math.PI] I already observe both faces.
I tried adding another face to the same geometry with geometry_1.faces.push(new THREE.Face3(0, 2, 1)); but that still didn't solve the problem.
Adding a second geometry with an opposite face geometry_2.faces.push(new THREE.Face3(0, 2, 1)); and having the mesh rotate negatively mesh_2.rotation.x -= 0.005; allows me to observe the desired result because the two geometries are now disappearing in opposite halves of the [0, 2*Math.PI] interval. This however is a hacky and not ideal solution.
So what is going on? How can I solve it? Thanks!
Documentation says:
OrthographicCamera( left, right, top, bottom, near, far )
so, set your camera like this:
camera = new THREE.OrthographicCamera(-FRUSTUM_SIDE/2, FRUSTUM_SIDE/2,
FRUSTUM_SIDE/2, -FRUSTUM_SIDE/2);
thus you'll have default near and far camera frustrum planes (0.1 and 2000).
Explanation: You set your cam at z-position, which is equal to FRUSTRUM_SIDE/2 and also you set your far camera frustrum plane with the same value. So you see everything between your cam position and the distance from it, which is FRUSTRUM_SIDE/2. In world coordinates, your far plane is at point (0, 0, 0). That's why your triangle disappears when it goes further then the distance of FRUSTRUM_SIDE/2 from your cam.
Extending the answer from #prisoner849, the problem shown in the JSFiddle has nothing to do with the geometry or the material of the mesh, but with the shape and extension of the frustum defined by the OrthographicCamera.
As explained nicely in this video tutorial and in the documentation the frustum of an OrthographicCamera is a rectangular parallelepiped defined by the values left, right, top, bottom, near, far:
The camera should effectively be thought of as being attached to the surface on the near side and facing towards negative values of the z axis.
Once the frustum's shape is defined with:
FRUSTUM_SIDE = 20;
camera = new THREE.OrthographicCamera(
-FRUSTUM_SIDE/2, FRUSTUM_SIDE/2,
FRUSTUM_SIDE/2, -FRUSTUM_SIDE/2,
-FRUSTUM_SIDE/2, FRUSTUM_SIDE/2);
we will be able to see in our image all the objects in the scene which are entirely contained in it.
However, after defining the frustum the position of the camera is changed: camera.position.z = FRUSTUM_SIDE/2; (line 24 of the fiddle). This effectively moves the whole frustum and not just the location of the image, so while previously any object in (0,0,0) was in the center of the frustum, now it will lie on the very far end plane of it.
The animation function:
function animate() {
requestAnimationFrame( animate );
mesh_1.rotation.x += 0.005;
renderer.render( scene, camera );
}
rotates the triangle towards the image plane, but for angles between [Math.PI, 2*Math.PI] the plane is effectively pointing outside of the frustum and thus becomes invisible.
Removing the camera.position.z = FRUSTUM_SIDE/2; line, or defining a different frustum, or moving the mesh position to the middle of the new frustum are all possible solutions. I.e. corrected fiddle.
Well, here is the problem,
Actually what I try to achieve is to place, at some places, some spotlights in a basic three.js example.
Here is the way I try to set the spotlight target position :
var light = new THREE.SpotLight(0xFFFFFF);
light.position.set(0,130,0);
light.target.position.set(200,-130,400);
scene.add(light);
The spotlight (light) keeps lighting the point (0,0,0) even if, when I console.log the target.position.(x,y,z) it gives me the right values...
Here is a quick fiddle I did with my full example.
http://jsfiddle.net/1xfno37y/7/
You have to update your light.target after changing (eg. setting position):
light.target.updateMatrixWorld();
Or just add your light.target to the scene:
scene.add( light.target );
Three.js r.71
http://jsfiddle.net/1xfno37y/19/
Further reading: Critical bug with spotLight.target.position #5555
I'm developing for the OculusRift using the OculusRiftEffect from https://github.com/mrdoob/three.js/blob/master/examples/js/effects/OculusRiftEffect.js and am using Sprites. The problem is the sprites don't appear in the correct position in each eye as in the screenshot. You can see the house sprite is in different positions in each eye and causes a 'double vision' effect in the oculus. While playing around with the code (have a demo plunker here) you can notice that near the edges of the screen the positioning is more accurate but I need it nearer the center of the screen where the positioning is off. I assume this has something to do with the shading/rendering in OculusRiftEffect but don't know enough about it to break it down, any direction would be appreciated, thanks!
Sample code:
var _scene, _camera, _renderer, _effect, _sprite;
function init() {
_scene = new THREE.Scene();
_camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, .1, 100000);
_camera.lookAt(new THREE.Vector3());
_renderer = new THREE.WebGLRenderer({
antialias: true,
canvas: document.getElementById('legit')
});
_renderer.setSize(window.innerWidth, window.innerHeight);
_effect = new THREE.OculusRiftEffect(_renderer, {
worldScale: 1000
});
_effect.setSize(window.innerWidth, window.innerHeight);
THREE.ImageUtils.crossOrigin = 'anonymous';
_sprite = new THREE.Sprite(
new THREE.SpriteMaterial({
map: new THREE.Texture(document.getElementById('icon')),
color: 0xff0000
})
);
_sprite.scale.set(200, 200, 1);
_sprite.position.set(500, 800, 1);
_scene.add(_sprite);
_scene.add(new THREE.Mesh(
new THREE.SphereGeometry(3000, 64, 32),
new THREE.MeshBasicMaterial({
color: 0xffffff,
wireframe: true,
side: THREE.DoubleSide
})
));
animate();
}
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
_renderer.render(_scene, _camera);
_effect.render(_scene, _camera);
}
document.addEventListener('DOMContentLoaded', init);
I am not that familiar with the Oculus plugin but I think your understanding of how sprites work is wrong.
Sprite is a rendering technique - a renderable rasterized surface... It can still be anywhere in space, and space is a relative term.
Is your house aware that it's part of the HUD and not part of a particle system somewhere in the distance?
One way to achieve what you want would be to overlay a copy at equal distance from the two points that represent the center of each eye, all in screen space. I think that this would give the effect that you are looking for.
That's as far as the positioning goes. Orientation wise, i'm not sure if they are actually properly aligned in your image above but the fish-eye effect is kicking in.
My reading of Three.js sprites indicates that they are positioned using screen coordinates, not in-scene geometry. Because of this they're ignoring the per-eye projection matrix offset that is imposed on the scene. I don't believe they will function properly in combination with the Oculus Rift distortion effect because of this.
As pailhead and Jherico mentioned this is not possible with the Oculus plugin. A workaround I found effective is to simply use a PlaneGeometry and set it as a child of the camera. Set it to look at the camera's position and it will act just like a sprite and render correctly for the OculusRiftEffect. Basic example (assuming camera and scene):
var sprite = new THREE.Mesh(
new THREE.PlaneGeometry(100, 100),
new THREE.MeshBasicMaterial({color: 0xffffff})
);
//assuming camera is at (0,0,0) we need to offset it
sprite.position.set(20, 20, -100);
sprite.lookAt(camera.position);
camera.add(sprite);
//normally camera doesnt need to be added
//but if it has child meshes it is necessary
scene.add(camera);
Since the plane is a child of the camera once its offset is positioned correctly it will follow the camera wherever it goes. The caveat is that it won't function exactly the same as a Sprite in that you can't move it independently around the scene but it's the closest solution I've found.
I have a really simple scene which has one .dae mesh in it, and a 7000*7000 plane underneath the mesh. I'd like it to be lit by a high SpotLight, so the mesh throws a shadow on the ground. But, something seems to be broken! No matter how high I put the SpotLight, it never lights up the plane! Also, it lights the mesh up only a little, while it is in a small square (perimeter).
You can see the situation here:
As soon as I move the mesh (a monster) around, it wont be lit anymore.
This is how I instantiate the light:
// create a spotlight
self.spotLight = new THREE.SpotLight();
// set its position
self.spotLight.position.y = 1000; //I recon it needs to be relatively high so it lights up everything
self.spotLight.position.x = 0; //(0, 0) are the coordinates where the mesh is spawned, and are the center of the plane
self.spotLight.position.z = 0;
self.spotLight.castShadow = true;
This is how the plane is made:
//The plane.
self.plane = new THREE.Mesh(new THREE.PlaneGeometry(self.groundSize, self.groundSize), new THREE.MeshLambertMaterial({color: 0x5C8A00}));
self.plane.receiveShadow = true;
self.plane.position.x = 0;
self.plane.position.y = -26;
self.plane.position.z = 0;
Also, here's another picture, this time, I've added a lot of PointLights:
You can see how the shadow still disappears!
Now, what am I doing wrong here? AFAIK, light should disperse equally in all directions! And also, there is another problem, I seem to be unable to add multiple SpotLights on the scene! Everything slows down completely if I do so - is this intended? Maybe it's because I enabled shadows on all of them...
#Neil, the same thing happens in your code as well!
I have created a jsfiddle showing a plane with Lambert material and a rotating cube that is casting a shadow, maybe you can see what is different to yours.
edit
Try playing about with some of the params, I can stop the clipping on my demo with:
spotLight.shadowCameraFov = 70;
update demo and moving demo