I currently have a cube that I'm trying to rotate on a corner. I need it to spin on the corner like the photo below.
http://www.flickr.com/photos/fiu/2198328580/
I'm new to Three.js, so I'm sorry if this is a dumb question.
Here's the code for what I currently have
var geometry= new THREE.CubeGeometry (200,200,200, 4, 4, 4);
// material
var material = new THREE.MeshLambertMaterial({
map: THREE.ImageUtils.loadTexture('inc/cube.jpg'), overdraw: true
});
cube = new THREE.Mesh( geometry, material );
cube.overdraw = true;
cube.position.y = 80;
cube.position.x = 5;
cube.position.z = 6;
cube.rotation.z = 14.9;
cube.rotation.y = 0 ;
cube.rotation.x = 0 ;
scene.add(cube);
On another note.... since I have the cube.jpg texture on the cube, if I have the values for the THREE.CubeGeometry set to (200,200,200) without the 4's, the texture warps... Anyone know how to stop the warping?
This is what I'm using to render:
renderer = new THREE.CanvasRenderer();
renderer.setClearColorHex(0xffffff, 0);
renderer.setSize( window.innerWidth, window.innerHeight ); container.appendChild( renderer.domElement );
It seems to work across most browsers, but if I use the WebGL renderer, it gives me issues with the Opacity of the Canvas.
To see the Project as it stands right now, its at http://fiudevspace.com/spincube
Conceptually all you need is to rotate the cube 45 degrees on a different axis from the 45 degrees you have already rotated - I do not use THREE as it would get between me and my solution more than it helps - remember the rule of thumb on object rotations : first translate the center of the object back to the origin (if not already there) then rotate about each axis you need, then finally translate the object back into position (reverse of previous translation) - hope this helps
Related
I am using Three.js and PointerLockControls to create simple FPS game. What I am trying to do is to attach a weapon to the camera/controls.
I was able to position the gun in front of the camera and move it along on the x/y axis, but it does not move along the z axis (up/down).
function updateGun() {
if (weapon) {
const yaw = controls.getObject();
weapon.position.set(
yaw.position.x - Math.sin(yaw.rotation.y) * 3,
yaw.position.y - 1,
yaw.position.z - Math.cos(yaw.rotation.y) * 3);
weapon.rotation.set(
yaw.rotation.x,
(yaw.rotation.y - Math.PI),
yaw.rotation.z);
}
}
If you are using PointerLockControls and want to add an object that remains in front of the camera, you can use this pattern:
var mesh = new THREE.Mesh( new THREE.SphereGeometry( 5, 16, 8 ), new THREE.MeshNormalMaterial() );
mesh.position.z = - 100; // some negative number
camera.add( mesh );
If you are not using PointerLockControls, you can still use the same technique, you just have to be sure to add the camera as a child of the scene.
scene.add( camera );
camera.add( mesh );
three.js r.84
I have a ribbon that displays a few thumbnails. Just to give a background, the thumbnail images are painted on a canvas, which is then added to Texture.
var texture = new THREE.Texture(textureCanvas);
The mesh is created as follows
loader.load('mesh_blender.js', function(geom) {
var mesh = new THREE.Mesh(geom, new THREE.MeshLambertMaterial({
color: 0xffffffff,
opacity: 0.7,
overdraw: 0.21,
side: THREE.DoubleSide,
transparent: true,
//shading: THREE.SmoothShading,
map: texture
}));
Everything till here is fine. The ribbon is created as follows
I have no complaints with this. But I need this additional effect you see in the image below. As it can be seen, the thumbnail that is in the centre (focus) needs to have a darker effect to show it is being highlighted/selectable. All the remaining thumbnails have a transparent effect depicting they are not selectable.
I am trying to wrap my head around this using Lights in Threejs but not very successful. I thought of using an AmbientLight to throw light on the entire ribbon and then an additional SpotLight only on the centre image (with a darker color maybe) to achieve the desired effect. But that didn't work. I have got something like this
But the centre focused image has no effect. As you can see in the image, I have used a helper to show the Light direction but I can't really see any light on the image. This is the code I use to develop that SpotLight
var spotLight = new THREE.SpotLight( 0xffeedd );
spotLight.position.set( 0, -50, 50 );
spotLight.castShadow = true;
//spotLight.penumbra = 0.2;
spotLight.decay = 2;
spotLight.distance = 300;
spotLight.angle = 0.5;
var helper = new THREE.SpotLightHelper( spotLight, 2.5 );
scene.add(helper);
scene.add( spotLight );
I am very new to Threejs and 3d graphics. Any help will be appreciated. Thanks.I am open to any other suggestion as well, if Lights are not to be used to achieve the end result.
You have given the opacity of the material as 0.7 so adding another light will not exactly give you the expected result. I would suggest using a raycaster to identify the object in the center and making the opacity of that object as 1 and the rest as 0.7.
var intersects = raycaster.intersectObjects( objects );
use this to get the objects that are intersecting in an array. And in the renderer function set the opacity of the first element in the array that is the object in the middle to 1. This only works if the thumbnails are all separate objects.
//set as the center of you vision
var mouse = new THREE.Vector2();
mouse.x = 0;
mouse.y = 0;
function highlightObject() {
// update the picking ray with the camera and mouse position
raycaster.setFromCamera( mouse, camera );
// calculate objects intersecting the picking ray
var intersects = raycaster.intersectObjects( scene.children );
//sets the object in the center opacity = 0.2
if(intersects.length > 0) {
intersects[0].object.material.opacity = 0.2;
}
//sets the opacity of the rest of the objects in scene to opacity = 1.0
for (var i = scene.children.length - 1; i >= 0; i--) {
var obj = scene.children[i];
obj.material.opacity = 1.0;
}
}
Is there a way in three.js to turn a cube mesh shape into a diamond shape doing something like rotating the axis of the scale and then scaling it? I'm trying to create a flat-ish diamond shape, something like x50,y50,x10. If not, then what's the best way to create a diamond mesh, or a triangle mesh shape?
If you just turn the cube on its end and scale x you'll still have a (now imbalanced) rectangle shape, but if you turn it on it's end, reorient the axis of scale somehow so it's stretching across the middle from point to point, now you could just squeeze the cube with scale x, and you'd have a nice diamond shape with a thin waist.
For clarification, here's a pic of the mesh shape I am trying to make, ideally the diamond shape on the left, but the triangle shape will do also.
So, is there some way to rotate the axis of the scale? Is that what new THREE.Matrix4().makeTranslation is for? How do I use that in this context?
See plunker of my attempt here. Clearly my cube.scale.x = 0.5; code is not working and needs the axis of transform to be shifted.
Here's the js:
cube = new THREE.Mesh( geometry, material );
cube.rotation.z = Math.PI / 4 ;
cube.position.y = 35;
cube.scale.x = 0.5;
scene.add( cube );
If you want to convert your cube or box into a diamond shape, then the easiest method is to transform your geometry using a pattern like this one:
var geometry = new THREE.BoxGeometry( 100, 100, 20 );
geometry.applyMatrix( new THREE.Matrix4().makeRotationZ( Math.PI / 4 ) );
geometry.applyMatrix( new THREE.Matrix4().makeScale( 1, 2, 1 ) ); // optional
Once you create your mesh, you still have the option of further scaling the mesh, itself.
mesh = new THREE.Mesh( geometry, material );
mesh.scale.set( sz, sy, sz );
scene.add( mesh );
three.js r.71
What you need to do is to create a hierarchy of objects, the inner object will rotate around the z-axis and the outer object will scale on the x-axis.
mesh = new THREE.Mesh(geometry, material);
mesh.rotation.z = Math.PI / 4; // rotate by 45 degrees
var group = new THREE.Group();
group.add( mesh );
group.scale.x = 0.5; // scale by 0.5
scene.add( group );
Here is a fiddle: http://jsfiddle.net/3gxqboer/
I am making this program where you can click on an object, zoom to it, then look at it from all angles by holding the right mouse button and dragging. I need the camera to be going around the object, not rotate the object with the camera looking at it. I honestly just have no idea how to math it out!
For testing there is already a game object with an xyz we have selected and are looking at
var g = new GameObject(500, 0, 0);//The game object with xyz
this.selected = g;//set selected to g
//Create and set the camera
this.camera = new THREE.PerspectiveCamera(45, w/h, 1, 10000);
this.camera.position.x = 0;
this.camera.position.y = 0;
this.camera.position.z = 0;
//set camera to look at the object which is 500 away in the x direction
this.camera.lookAt(new THREE.Vector3(this.selected.x, this.selected.y, this.selected.z));
So the radius between the camera and the object is 500 and while selected and rotating, the camera should always be 500 away.
I update the scene here:
Main.prototype.update = function(){
this.renderer.render(this.scene, this.camera);//scene is just some ambient lighting
//what to do when mouse right is held down
if(this.rightMouseDown){
//placeholder functionality, needs to rotate around object based on mouse movements
this.camera.position.x -= 5;
}
}
How do I rotate this camera around g with a radius of 500?!?!
As gaitat mentioned, trackball controls are the best place to start with many configurable parameters to make camera rotation/revolution easy. One enormous potential benefit of this method ( especially for your project ) is avoiding "gimbal lock" which is the source of much frustration when working with rotations. Here's a link that might help you with Trackball controls and Orbitcontrols:
Rotate camera in Three.js with mouse
Another option would be setting camera coordinates yourself in the animation loop which is actually quite simple:
var angle = 0;
var radius = 500;
function animate() {
...
// Use Math.cos and Math.sin to set camera X and Z values based on angle.
camera.position.x = radius * Math.cos( angle );
camera.position.z = radius * Math.sin( angle );
angle += 0.01;
...
}
Another option would be to connect the camera to a pivot object and just rotate the pivot:
var camera_pivot = new THREE.Object3D()
var Y_AXIS = new THREE.Vector3( 0, 1, 0 );
scene.add( camera_pivot );
camera_pivot.add( camera );
camera.position.set( 500, 0, 0 );
camera.lookAt( camera_pivot.position );
...
camera_pivot.rotateOnAxis( Y_AXIS, 0.01 ); // radians
If you pursue this option, be aware that the camera object is in "camera pivot space", and might be more challenging to manipulate further.
I think this is really simple question (I'm just learning three.js) and I'm failing to find the right words to search by, but here we go.
I'm working on animated a spinning Earth. I want the Earth to always start its rotation from the same point when the viewer loads the page. Since I'm learning as I go along, I started with a boilerplate from http://jeromeetienne.github.com/threejsboilerplatebuilder/ and have subtracted elements I don't require and tried to add things that I need based on other examples found around the web. The animation works fine other than the initial direction issue. Right now if I reload the animation, the globe position picks up where it was before I hit reload instead of reseting to an initial position. Here's my script:
var scene, renderer, composer;
var camera, cameraControl;
var globe;
if( !init() ) animate();
// init the scene
function init(){
if( Detector.webgl ){
renderer = new THREE.WebGLRenderer({
antialias : true, // to get smoother output
});
}else{
renderer = new THREE.CanvasRenderer();
}
renderer.setSize( 567,567 );
document.getElementById('Stage_globe3d').appendChild(renderer.domElement);
// create a scene
scene = new THREE.Scene();
// put a camera in the scene
var cameraH = 3;
var cameraW = cameraH / 567 * 567;
camera = new THREE.OrthographicCamera( -cameraW/2, +cameraW/2, cameraH/2, -cameraH/2, -10000, 10000 );
camera.position.set(0, 0, 5);
scene.add(camera);
// here you add your objects
var light = new THREE.DirectionalLight(0xffffff, 2 );
light.position.set( 0,0,10 ).normalize();
scene.add( light );
var geometry = new THREE.SphereGeometry( 1.45, 50, 50 );
var material = new THREE.MeshLambertMaterial({map: THREE.ImageUtils.loadTexture("images/world.jpg")});
var globe = new THREE.Mesh( geometry, material );
// tried adding this, but it didn't work
//globe.rotation.y = 100;
scene.add( globe );
}
// animation loop
function animate() {
// loop on request animation loop
// - it has to be at the begining of the function
// - see details at http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
requestAnimationFrame( animate );
// do the render
render();
}
// render the scene
function render() {
var PIseconds = Date.now() * Math.PI;
// animation of all objects
for( var i = 0; i < scene.objects.length; i ++ ){
scene.objects[ i ].rotation.y = PIseconds*0.00003 * (i % 2 ? 1 : 1);
}
// actually render the scene
renderer.render( scene, camera );
}
I thought it might have to do with the rotation animation being based on the current time (which I got from the boilerplate) but I've seen other examples that do something similar but still always start from the same initial position (Walt Disney head from the three.js examples on github, for example). Could someone tell me what I'm doing wrong and steer me in the right direction?
Thanks.
In your init() routine set
globe.rotation.y = initialValueInRadians;
Then in your render() loop, set
globe.rotation.y += delta;
where delta is defined as a constant, like 0.01, or as a function of elapsed time.