Why is my camera facing backwards at the start of my zoom? - javascript

I have a basic function to move my camera as it scrolls but it starts facing backwards and as soon as I do the first scroll it flips around the right way and works as intended. (I'm also very new to coding)
NOTE : there is much more code for other functions and stuffs that I have left out.
const scene = new THREE.Scene();
//Camera
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
//Renderer
const renderer = new THREE.WebGLRenderer({
canvas: document.querySelector('#bg'),
});
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
camera.position.setZ(30);
renderer.render( scene, camera );
//Scrolling to move
function moveCamera(){
const t = document.body.getBoundingClientRect().top;
camera.position.z = t * -0.01;
camera.position.x = t * -0.0002;
camera.rotation.y = t * -0.0002;
}
document.body.onscroll = moveCamera```

I figured it using a simple method :
console.log(camera.position.z) to see where the camera was at each scroll.
It was dipping into the negatives so I wrote a simple if statement to set it back to 0.1 if it ever gets < 0.1
if(camera.position.z < 0.1){
camera.position.z = 0.1
}

Related

Inverted background color in mobile and desktop

so I am a newbie towards threejs and basically have just started to learn and develop in threejs. I do understand due to limitations on mobile browsers there are some characteristics that is not present on desktop may be present on mobile. I however have run into a problem that I cant seem to google or find as to why it happened. I have created a very basic scene with the background color of black ‘0x000000’ and in this scene I have a sphere with wireframe as its material and its color is set to white. On desktop this renders perfect and shows up exactly as black background scene with white sphere geometry. However once Ive test deployed on a domain and accessing it through mobile, the scene and sphere color are totally inverted. I am still unsure what is causing it and any answer would be greatly appreciated. Thanks in advance!
This below code is how I create a canvas and a scene and a sphere.
import "../css/style.css";
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import * as dat from "dat.gui";
// Debug
// const gui = new dat.GUI();
// Canvas
const canvas = document.querySelector("canvas.main-bg");
// Scene
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x000000);
// Objects
const geometry = new THREE.SphereBufferGeometry(0.5, 15, 8);
// Materials
const material = new THREE.MeshBasicMaterial({
color: 0xffffff,
wireframe: true,
});
// Mesh
const sphere = new THREE.Mesh(geometry, material);
// Lights
// Point light
const pointLight = new THREE.PointLight(0x252525, 0.1);
pointLight.position.x = 2;
pointLight.position.y = 3;
pointLight.position.z = 4;
scene.add(pointLight);
// Sizes
const sizes = {
width: window.innerWidth,
height: window.innerHeight,
};
window.addEventListener("resize", () => {
// Update sizes
sizes.width = window.innerWidth;
sizes.height = window.innerHeight;
// Update camera
camera.aspect = sizes.width / sizes.height;
camera.updateProjectionMatrix();
// Update renderer
renderer.setSize(sizes.width, sizes.height);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
});
// Base camera
const camera = new THREE.PerspectiveCamera(
75,
sizes.width / sizes.height,
0.1,
100
);
camera.position.x = 0;
camera.position.y = 0;
camera.position.z = 2;
scene.add(camera);
// Controls
// const controls = new OrbitControls(camera, canvas)
// controls.enableDamping = true
// Renderer
const renderer = new THREE.WebGLRenderer({
canvas: canvas,
});
renderer.setSize(sizes.width, sizes.height);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
const clock = new THREE.Clock();
const animate = () =>
const elapsedTime = clock.getElapsedTime();
// Update objects
sphere.rotation.y = -0.2 * elapsedTime;
sphere2.rotation.y = 0.1 * elapsedTime;
sphere3.rotation.x = 0.7 * elapsedTime;
sphere.rotation.x += 0.5 * (targetY - sphere.rotation.x);
sphere.rotation.y += 0.5 * (targetX - sphere.rotation.y);
sphere.position.z += -0.5 * (targetY - sphere.rotation.x);
// Render
renderer.render(scene, camera);
// Call animate again on the next frame
window.requestAnimationFrame(animate);
};
animate();
Nothing else besides this is altering the scene.background color. This is how it looks like on desktop.
desktop image
And this is how it looks like on mobile.mobile
Nothing else is setting the canvas color however the colors are inverted on mobile, Any help is greatly appreciated! Thank you
You have added the CSS rule mix-blend-mode: exclusion to your <canvas>. For some reason, Safari is the only browser that's respecting that rule, and that's why it's showing inverted colors on mobile.
If you want a black background with white wireframes, just get rid of any mix-blend-modes in CSS so you get exactly the color you're defining.

three.js - how to render scene.background before a mesh?

I am a novice to Javascript and ThreeJS. I have a 3D rotating cube that appears on top of a static background, but one frustrating property is that the cube typically appears first and then the background image appears. How do I ensure the background is rendered first? Specifically, I always want the background image to appear before the cube.
My code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>My first three.js app</title>
<style>
body { margin: 0; }
</style>
</head>
<body>
<script src="js/three.js"></script>
<script>
function resize() {
var aspect = window.innerWidth / window.innerHeight;
let texAspect = bgWidth / bgHeight;
let relAspect = aspect / texAspect;
bgTexture.repeat = new THREE.Vector2( Math.max(relAspect, 1), Math.max(1/relAspect,1) );
bgTexture.offset = new THREE.Vector2( -Math.max(relAspect-1, 0)/2, -Math.max(1/relAspect-1, 0)/2 );
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = aspect;
camera.updateProjectionMatrix();
}
const scene = new THREE.Scene();
// Arguments:
// 1) Field of Value (degrees)
// 2) Aspect ratio
// 3) Near clipping plane
// 4) Far clipping plane
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
const renderer = new THREE.WebGLRenderer();
// Need to set size of renderer. For performance, may want to reduce size.
// Can also reduce resolution by passing false as third arg to .setSize
renderer.setSize( window.innerWidth, window.innerHeight );
// Add the rendered to the HTML
document.body.appendChild( renderer.domElement );
// A BoxGeometry is an object that contains all points (vertices) and fill (faces)
// of the cube
const geometry = new THREE.BoxGeometry();
// Determines surface color (maybe texture?)
const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
// Mesh takes a geometry and applies the material to it
const cube = new THREE.Mesh( geometry, material );
// Add background image
const loader = new THREE.TextureLoader();
bgTexture = loader.load('https://images.pexels.com/photos/1205301/pexels-photo-1205301.jpeg' ,
function(texture) {
// Resize image to fit in window
// Code from https://stackoverflow.com/a/48126806/4570472
var img = texture.image;
var bgWidth = img.width;
var bgHeight = img.height;
resize();
});
scene.background = bgTexture;
// By default, whatever we add to the scene will be at coordinates (0, 0, 0)
scene.add( cube );
camera.position.z = 5;
// This somehow creates a loop that causes the rendered to draw the scene
// every time the screen is refreshed (typically 60fps)
function animate() {
requestAnimationFrame( animate );
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render( scene, camera );
}
animate();
</script>
</body>
</html>
This is happening because the texture is taking longer to load than it takes for Three.js to set up the rest of the scene. You already have a handler for the onLoad callback of TextureLoader.load(), so we can use that to adjust the behavior.
Before scene.add( cube );, add a new line:
cube.visible = false;
Now the cube will still be added to the scene, but it won't be visible. Now after the resize() call at the end of function(texture), add
cube.visible = true;
While testing the problem and solution locally, I ran into a few other, less significant issues with your code. You can see all of the changes I had to make to get it running properly at this Gist.

How to make 3D objects jump smoothly apart from each other upon click? Three.JS

I'm very new to Three.JS and 3D web dev in general what I'm trying to do is mimic this action: https://www.youtube.com/watch?v=HWSTxPc8npk&feature=youtu.be&t=7s Essentially this is a set of 3D planes and upon click the whole stack reacts and gives space around the one that's clicked.
For now, my base case is 3 planes and figuring first out if I can click the the middle one, how do I get the others to jump back smoothly as if they were pushed rather than instant appear and disappear as they do now on the click of a button.
The long term goal is to have a separate button for every plane so that on click, the selected plane will have padding around it and the rest of the planes in stack move accordingly.
I've looked into Tween.js, and CSS3D but pretty overwhelmed as a newbie. Any tutorials or tips would be greatly appreciated!
// Our Javascript will go here.
window.addEventListener( 'resize', onWindowResize, false );
function onWindowResize(){
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
var geometry = new THREE.PlaneGeometry( 3, 3, 1 );
var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
var plane = new THREE.Mesh( geometry, material );
plane.rotation.y = -.7;
var material2 = new THREE.MeshBasicMaterial( { color: 0x0000ff } );
var material3 = new THREE.MeshBasicMaterial( { color: 0xff0000 } );
var plane2 = new THREE.Mesh(geometry, material2 );
plane2.rotation.y = -.7;
plane2.position.x = 1;
var plane3 = new THREE.Mesh(geometry, material3);
plane3.rotation.y = -.7;
plane3.position.x = -1;
scene.add( plane, plane2, plane3 );
camera.position.z = 5;
function render() {
requestAnimationFrame( render );
// cube.rotation.x += 0.1;
// cube.rotation.y += 0.1;
renderer.render( scene, camera );
}
render();
function clickFirst() {
TWEEN.removeAll();
var tween = new TWEEN.Tween(plane3.position).to({x: -2}, 1000).start();
tween.easing(TWEEN.Easing.Elastic.InOut);
render();
}
</script>
<button onclick="clickFirst();" style="background-color: white; z-index: 9999;">Click me</button>
First, you need to locate the 2 planes.
Second, you need to make the planes clickable:
https://threejs.org/examples/#webgl_interactive_cubes
https://github.com/josdirksen/learning-threejs/blob/master/chapter-09/02-selecting-objects.html
Third, you should use Tween.js for the transition.
after picking the right plane, make a tween for the other planes with a tween, all to move on the same Axis:
example:
createjs.Tween.get(plane3.position.z).to(
plane3.position.z + 100
, 1000, createjs.Ease.cubicOut)
If you will add some code here after starting to implement i would be able to help more.

three.js cordova apk for android

I'm developed simple 3D android app using cordova and three.js. Its is not working on few device(HTC one X, Samsung S6) and works perfectly in few device(ASUS, One + one). I have no idea why it is not working and It is showing blank white screen. Here is my js code
var renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
$('#wrapper').html(renderer.domElement);
element = renderer.domElement;
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(100, window.innerWidth / window.innerHeight, 0.1, 10000);
camera.position.set(0, 0, 0);
var effect = new THREE.StereoEffect(renderer);
effect.setSize( window.innerWidth, window.innerHeight );
var axis = new THREE.AxisHelper(70000.5);
//scene.add(axis);
var cube = new THREE.Mesh( new THREE.CubeGeometry( 2.5, 4, 2.5 ), new THREE.MeshNormalMaterial() );
cube.position.z=-4;
scene.add( cube );
var lastTimeMsec = null;
function animate(timestamp) {
effect.render( scene, camera );
requestAnimationFrame(animate);
}
animate();
Can any one please let me know the issue.
Thanks in advance
We need to install one cordova plugin(cordova-plugin-crosswalk-webview
) before build. This allows three.js to support all the device.

Two planes which very close to each other [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
i have got a problem with 2 planes which are very close to each other.
One of the planes is causing glitches or even disappearing on certain point of view.
Here is the code:
var renderer, scene, camera, controls, mesh;
init();
animate();
function init() {
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 16, window.innerWidth / window.innerHeight, 1, 50000 );
camera.position.set(8000, 4000, 13000);
controls = new THREE.OrbitControls( camera );
controls.target = new THREE.Vector3(0,0,0);
controls.minPolarAngle = 0
controls.maxPolarAngle = (Math.PI / 2) - 0.05;
mesh = new THREE.Mesh( new THREE.PlaneBufferGeometry( 7000, 7000 ), new THREE.MeshBasicMaterial);
mesh.position.y = 0;
mesh.rotation.x = - Math.PI / 2;
mesh.receiveShadow = true;
scene.add( mesh );
mesh = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2000, 2000 ), new THREE.MeshBasicMaterial({color:0x00ff00}));
mesh.position.y = 5;
mesh.rotation.x = - Math.PI / 2;
mesh.receiveShadow = true;
scene.add( mesh );
}
function animate() {
requestAnimationFrame( animate );
controls.update();
renderer.render( scene, camera );
}
Here is the fiddle: http://jsfiddle.net/mae1storm/2hLjn1t5/1/
What can i do to fix this problem?
Sorry for my bad english, Thank You.
The problem comes from the depth testing. These planes are so close together that their depth values are the same at some points, so the rasterizer can't really decide which one is in front of which. To solce this problem you have to either increase the distance between the two planes, or cur a whole in the bigger plane with the size of the smaller plan. Or in this case specifically, use a texture instead.
Also your scene is huge, which contributes to the precision issues. Scale it way down and you should be fine again. If your scene would be like 1/100th of the size it will work a lot better.

Categories

Resources