ThreeJS/Panolens: direction of the camera when panorama entered? - javascript

I'm trying to throw an equirectangular image into Panolens and simply 1st get the same panorama viewer as can be visible below:
https://threejs.org/examples/webgl_panorama_equirectangular.html
https://www.chiefarchitect.com/products/360-panorama-viewer/
Since Panolens.js is a wrapper of Three.js I expected the same result as when I throw my image into the 1st link above. (drag & drop it) - camera looks into the center of the image.
What I get instead is : camera looks into the left most area of the panorama image.
I solve this using
panorama.addEventListener( 'enter-fade-start', function() {
viewer.getControl().target.set(10, -2, 0);
viewer.getControl().update();
//viewer.tweenControlCenter( new THREE.Vector3(2, -1, 1), 2000 );
});
But when I move to another panorama and come back, this code does not seem to have any effect (althought event is properly triggered).
How can I make the camera look into the same direction each time I come back to my panorama? (I'm switching between multiple panoramas).
Basically I don't seem to understand vectors properly and where 0,0,0 is each time I come back to panorama, since It seems to be working differently based on where the camera is facing.
Any tips/links/explanations very much welcome.

I over complicated things it seems. The solution is to only use:
viewer.tweenControlCenter( new THREE.Vector3(10, -2, 0), 0 );
inside "enter-fade-start". And that's it.
Much of docs is a bit misleading with saying you have to call .update() on control and setting .target properly etc, but that does not seem to work as I expected.
Relevant example also here: https://codepen.io/pchen66/pen/LLgxME

Related

Reposition camera to object & lookAt() (React three fiber)

I am trying to transition camera.position and camera.lookAt smoothly between "zoomed out" and "zoomed in" views of individual, randomly placed objects.
The positioning works great. Lerping the lookAt(), however, doesn't seem to be playing nicely with other solutions for traditional ThreeJS ( see #bovesan's answer here) nor addressed by the relevant example on the react-three-fiber docs (link).
Zooming in past the z axis flips the camera around, and at the corners it's wildly distored.
You can see my progress here : https://codesandbox.io/s/three-fiber-zoom-to-object-rlme0?file=/src/App.js
With the relevant bit of code being in App.js on line 63 :
useFrame((state) => {
const step = 0.05;
// `focus` is a state variable that sends a Vec3 of the objects position
zoom ? vec.set(focus.x, focus.y, focus.z + 0.2) : vec.set(0, 0, 5);
// HERE, looking for a way to lerp camera lookAt in a way that can toggle.
state.camera.lookAt(0, 0, 0);
state.camera.position.lerp(vec, step);
state.camera.updateProjectionMatrix();
});
I've spent hours looking for relevant examples/tutorials, but haven't come up with much. I'm afraid I don't have enough ThreeJs experience to be looking in the right direction, though, so any help in any direction would be most welcome.
To anyone who happens upon this later, the solution was figured out over at by #drcmda.
You can find a working example here :
https://codesandbox.io/s/three-fiber-zoom-to-object-camera-controls-solution-final-sbgx0?file=/src/App.js
This is just a slight change on #drcmda 's implementation of camera-controls with normal lerping to move the camera. It’s not perfect (for one, the transition time in camera controls doesn’t seem to be editable, so there’s a weird swing-around thing that happens, when you’re zooming back out) but it definitely solves the problem. (Many thanks to #looeee and #forerunrun for additional help.)
If you'd rather not use another library, #forerunrun's answer in the original thread also works well, but I wasn't able to debug it enough to have it be reliable. (See convo.)

Three.js - Using box3 to scale and translate an object

I'm currently working on a piece of code that loads up a 3D image which initially isn't visible. It is supposed to be visible, however, after scaling and translating it, but no matter what I do, the screen remains black and I cannot see the 3D image.
I won't post the entire code but here's the section about the scaling and translating (the code portions that I've commented out is what I tried to implement as the solution):
const box = new THREE.Box3().setFromObject(object);
// object.scale.set( 2, 2, 2 );
// box.getCenter(object.position);
// object.geometry.center();
scene.add( object );
I'm confused whether I'm misunderstanding Box3, whether it has to do with the order in which I'm scaling/centering, or if it's my values, or something trivial that I'm forgetting to add.
EDIT: I believe that I need to properly size the bounding box around the image, and use that to scale the tiger. I'm still confused about this, because I assumed this line already did that:
const box = new THREE.Box3().setFromObject(object);
So I'm not sure how I can change the size of the bounding box so it is correct, and then scale it to the size I want.

Drag and mouseover in snap.svg

I'm relatively new to javascript, and am learning about drag and drop using snap.svg. My problem is in the drop. I can't tell if the dragged element is over the drop target. In this code, I want to drag the circle over the square, and thought I could use mouseover. My (distilled) example may also be a simpler version of this post.
var paper = Snap(300, 300);
var square = paper.rect(100, 100, 40, 40).attr({fill:"blue"});
var circle = paper.circle(50, 50, 20).attr({fill:"red"});
circle.drag();
square.mouseover(
function() {
console.log("Over the square");
}
);
As written, the mouseover will fire when you move the pointer over the blue square, but not when you drag the red circle over the blue square. If you reverse the creation of the square and circle, the mouseover fires either way, but of course the circle is behind the square.
Evidently the event gets caught in the view hierarchy (or something) and doesn't propagate. There must be an easy way around this. Any help?
(And if the best answer is, "use jQuery," fine, but I'd love to learn how to make this work directly, since snap.svg makes dragging so easy.)
Addition: The direction I'm hoping for: the snap.svg documentation for Element.drag() says, in part, "When Element is dragged over another element, drag.over.<id> fires as well." A fine, event-based direction, which would let me (for example) highlight the drop target without a lot of fuss.
But I haven't figured out how to listen for that event! Any help or advice?
Only quick way without collision or element detection from points that I can think of, is to place an almost invisible clone in front of the object, later in the DOM that you can't really see, eg ...
paper.append( square.clone().attr({ opacity: 0.000001 }) )
jsfiddle
Depends how complex your svgs are going to be as to whether this would work I guess, you also have a slight issue if you drop the element over it, your redrag start won't get picked up, so you would need to code around that as well. I think some testing is probably going to be the most bug free solution (there are a few solutions on S.O for getElementFromPoint or hit detection type solutions).
jsfiddle workaround for point above

Three.js custom geometry raycaster catches wrong object

I need to use my own gemetry since the default cube does not look like it should in wireframe mode (now it is made of triangles instead of squares).
So I made my own geometry and it looks ok, but the raycaster does not work as good with my own objects as it does with the built-in cubes.
var cube = new THREE.Line( getCube( 5,5, 5), new THREE.LineDashedMaterial( { color: 0x000000,dashSize: 1, gapSize: 0.1, linewidth: 2 } ),THREE.LinePieces );
where getCube() returns
var geometry = new THREE.Geometry()
See example:
http://jsfiddle.net/QHjSM/12/
6 colour filled box on the top are the defalt THREE.CubeGeometry boxes, and selecting them with raycaster works perfect, 6 wireframe are my custom geometry.
Issues:
If you try to click outside the box, but pretty close to it it will catch the box, and if you click inside the box (in the middle of it) it will not catch it neither.
But the most annoying thing is that if you click inside one box, but close to another one sometimes it catches not the wrong one.
I'm not sure can it be done better, tried all the geometry.compute... methods, but still no effect.
Good day, your custom cubes are not in fact cubes. They are just a stack of lines with no cooresponding faces. Your selection is not returning as expected due to the fact that your "cubes" indeed have gapping holes right threw them. What you can do is in your getCube function after you've built the vertices you can then build all your faces in a similar way.
Have a look at this example: Issue with custom geometry and face normal
Generally you'll need to carefully pattern out every 3 set of vertices so that when you build the faces there in a clock-wise direction so that the normals will be computerd correctly. Here's a basic example of adding a face.
geometry.faces.push(new THREE.Face3(1,2,3));
BUT! Note that this will result in the same aforementioned diagonal lines through your wireframe. So, for your use case why not simply use both the basic cube mesh with picking and remove the wireframe then overlay the line drawn boxes as your custom wireframe. Best of both worlds.
FYI, you probably already know but Face4 is gone, so you'll need to use Face3 and some sort of custom wireframe to do this anyway.
Edit:
I did a little test to your fiddle, noticed something strange. Using the CanvasRender, even with the wireframe off the default cube you still see the diagonal lines! I try WebGLRenderer and it's fine. I'll have to look into that one further.
CanvasRenderer
http://jsfiddle.net/QHjSM/13/
WebGLRenderer
http://jsfiddle.net/QHjSM/14/
Me again, hmm it appears those ghosted face lines are visible in all the CanvasRenderer examples that use a MeshBasicMaterial on the Three.js site. The only thing I was able to do was simply reduce the opacity of the cube mesh material to 0.1 to lessen the effect. I suppose the only other method is to switch to the WebGLRenderer but I look forward to being wrong on this :) Here's the last test
http://jsfiddle.net/QHjSM/16/

How to set default view in OpenLayers, WITHOUT restricting bounds?

Based on samples, I can see that you can set a default view in OpenLayers by saying something along the lines of:
var bounds = new OpenLayers.Bounds(-125, 25, -65, 50);
var map = new OpenLayers.Map('map', {restrictedExtent: bounds });
However, this also (as the name implies), restricts me to be able to ONLY navigate within these bounds. I can zoom out and see things outside of these bounds, but I can't then zoom back onto them, or scroll to them.
I've tried not having any restrictedExtent (or making it the entire map), but then I can't get it to focus on the area I want. I tried using:
map.setCenter(new OpenLayers.LonLat(0,0), 3);
console.log(map.getCenter());
To set the zoom and the center...but it doesn't seem to do ANYTHING, other than set the variable "center" which I can then read from map.getCenter() (if I don't set it, it's null, if I do set it, I can see it...but the map itself stays fully extended and it's center doesn't seem to change at all...)
The Map layer I am using is:
OpenLayers.Layer.OSM.Mapnik
with displayOutsideMaxExtent set to true... I'm really at a loss here.
My goal is to have a default region of the world zoomed in to and in view (such as the United States), with the option of viewers being able to go outside the default to view things.
I think I've figured it out. For whatever reason, the zoom was never changing, but the center apparently WAS moving (it was just so zoomed out I couldn't tell). Add to the fact that I needed to transform the center to use the google projection, and it seems to work just fine.
What I ended up doing was:
var lonlat = new OpenLayers.LonLat(20,37).transform(new OpenLayers.Projection("EPSG:4326"),new OpenLayers.Projection("EPSG:900913"));
map.setCenter(lonlat);
map.zoomTo(4);

Categories