Three.js & Dat.gui - TrackballControls renderer.domElement disables rotate and pan - three.js

I am trying to use dat.gui with a very simple three.js (r73) scene but am running into an issue with rotate and pan not working after adding "renderer.domElement" to the trackballControls initialization. Zoom works as expected.
Without renderer.domElement, I get a working rotate, zoom, pan functionality but the dat.gui interface sliders "latch" when clicked, which is just annoying and not functional. The issue as described here: Issue while using dat.GUI in a three.js example.
Looked over more info here but didn't see a great resolution: https://github.com/mrdoob/three.js/issues/828
Also found this issue. Defining the container element aka renderer.domElement doesn't work. I am unable to click within outside of the canvas area without the scene rotating.
Allow mouse control of three.js scene only when mouse is over canvas
Has anyone run into the same thing recently? If so, what workarounds are possible? Any help is appreciated.
-
The code is setup as follows:
// setup scene
// setup camera
// setup renderer
// ..
var trackballControls = new THREE.TrackballControls(camera, renderer.domElement);
trackballControls.rotateSpeed = 3.0;
trackballControls.zoomSpeed = 1.0;
trackballControls.panSpeed = 1.0;
// ..
// render loop
var clock = new THREE.Clock();
function render() {
stats.update();
var delta = clock.getDelta();
trackballControls.update(delta);
requestAnimationFrame( render );
renderer.render( scene, camera );
}

I debugged the issue with the help of this post: Three.js Restrict the mouse movement to Scene only.
Apparently, if you append the renderer.domElement child after initializing the trackballControls, it doesn't know anything about the renderer.domElement object. This also does something strange to dat.gui as described previously.
Basically, make sure this line:
document.getElementById("WebGL-output").appendChild(renderer.domElement);
appears before this line:
var trackballControls = new THREE.TrackballControls(camera, renderer.domElement);

Make sure the renderer DOM element is added to the html before it is being used as a reference.
document.body.appendChild(renderer.domElement);

Related

Zooming in camera make some meshes not visible

Im using OrbitControls and when i zoom in or move camera on some angles some of the meshes disappear.
This is my camera configuration right now :
camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight,0.1, 3000 );
I tried to decrease the near plane but it doesnt work, i also add to the meshes materials that are disappearing THREE.DoubleSide and nothing seems to work. They are also animated via new way to animate fbx.
object.mixer = new THREE.AnimationMixer( object );
mixers.push( object.mixer );
var action = object.mixer.clipAction( object.animations[ 0 ] );
action.play();
dont know if that has anything relationship with the issue.

Function LookAt to turn around an object ?

as part of a project, I have to turn the camera around an object (position 0, 0,0) which remains to him still. For this, I want to know if the LookAt function is the one that is best suited , And also how does it work?
Integrating OrbitControls should be done with a few lines of code. So, the basic lines of code should be:
// init
var controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.enableZoom = false; // optional
controls.enablePan = false; // optional
controls.center.set(0,0,0); // should be initially 0,0,0
controls.addEventListener( 'change', render ); // if you are not using requestAnimationFrame()
camera.position.z = 500; // should be bigger than the radius of your sphere
// render
function render() {
renderer.render(scene, camera);
}
<script src="js/controls/OrbitControls.js"></script>
Now, you should be able to rotate the camera around your sphere using your mouse.
All the other essential stuff (camera, renderer) can be found at the example: https://threejs.org/examples/#misc_controls_orbit

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.

Exporting a simple model with texture from Blender to three.js

Note: I want to avoid modifying the model in the javascript code and do all the model design inside Blender.
Note #2: While this question is long, it is actually a basic problem (title says it all). The below is "walk-through" to the problem.
I am trying export Blender models to threejs.org as DAE model but have problem with models with texture (I have tried JSON and OBJ+MTL format too):
To make things simpler, here are the steps I perform (and fail) to add texture to simple "Startup file" which contains a cube, camera, and light:
Select the cube
In the Materials panel, make sure the default Material for the cube is selected.
In the Texture panel, make sure "Tex" (the default texture for the material) is selected.
For this texture, set Type to "Image or Movie"
In the Image section of panel, open a grass1.jpg (a 512x512 image) as the texture.
In the Mapping section, change the Coordinates to UV.
Export the model as Collada model, checking "Include UV Textures", "Include Material Textures", and "Copy" checkboxes.
You can download blend, dae, and texture file mentioned in these steps.
Then I use the following code to load the DAE model, but I get this error and the cube is not shown:
256 [.WebGLRenderingContext]GL ERROR :GL_INVALID_OPERATION :
glDrawElements: attempt to access out of range vertices in attribute 2
WebGL: too many errors, no more errors will be reported to the console for this context.
<script src="js/three.min.js"></script>
<script src="js/OrbitControls.js"></script>
<script src="js/ColladaLoader.js"></script>
<script>
var scene, camera, renderer;
init();
animate();
function init() {
scene = new THREE.Scene();
var WIDTH = window.innerWidth,
HEIGHT = window.innerHeight;
renderer = new THREE.WebGLRenderer({antialias:true});
renderer.setSize(WIDTH, HEIGHT);
document.body.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(45, WIDTH / HEIGHT, 0.1, 10000);
camera.position.set(10,10,10);
scene.add(camera);
window.addEventListener('resize', function() {
var WIDTH = window.innerWidth,
HEIGHT = window.innerHeight;
renderer.setSize(WIDTH, HEIGHT);
camera.aspect = WIDTH / HEIGHT;
camera.updateProjectionMatrix();
});
var loader = new THREE.ColladaLoader();
loader.load( 'models/untitled.dae', function(geometry) {
dae = geometry.scene;
scene.add(dae);
var gridXZ = new THREE.GridHelper(100, 10);
gridXZ.setColors( new THREE.Color(0x8f8f8f), new THREE.Color(0x8f8f8f) );
gridXZ.position.set(0,0,0);
scene.add(gridXZ);
});
controls = new THREE.OrbitControls(camera, renderer.domElement);
}
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
controls.update();
}
</script>
And here is the screenshot of Blender after mentioned 7 steps:
Update: Exporting as js file using JSON exporter for Blender doesn't work either and resulted the very same error.
Update 2: Same error after exporting to OBJ+MTL and loading them with OBJMTLLoader.
The problem is you have not set up UV coordinates for your model. By default, each face applies the whole texture, but in blender the UVs are blank when exporting.
You want to specifically set up your UV coordinates. These are coordinates that show how to apply a texture to each face.
Make sure to UV unwrap your model in blender. Go to edit mode (tab), select all faces, press "u", and click "unwrap". Then try to re-export.
Unwrap is just 1 method, there are many. Experiment with different methods in blender to get the results you want (possibly the "reset" option).

three.js in,Sprite.render Depth attribute is not supported

This is my code:
var sprite = new THREE.Sprite(material);
sprite.renderDepth = 10;
The above renderDepth setting is invalid, it does not work for sprites.
How to solve this problem?
You want one sprite to always be on top.
Since SpriteMaterial does not support a user-specified renderDepth, you have to implement a work-around.
Sprites are rendered last when using WebGLRenderer.
The easiest way to do what you want is to have two scenes and two render passes, with one sprite in the second scene like so:
renderer.autoClear = false;
scene2.add( sprite2 );
then in the render loop
renderer.render( scene, camera );
renderer.clearDepth();
renderer.render( scene2, camera );
three.js r.64

Resources