Limit maximum zoom for a scene in Three.js - three.js

I have a Three.js App and I wanna limit the zoom for the scene, because logically at some zoom the user can get inside of my 3D object, which in my oppinion is not a really good UX.
I tried scene.maxZoom = number; but did not work. What can I do?
Here is the code: https://github.com/AlinAlexandruPeter/code/blob/main/code.js

You don't need Three.js to limit the range of numbers, just simple JavaScript. Use Math.min(a, b) to get the lower of the two values.
const MAX_ZOOM = 2.5;
// Clamp user input to 2.5 and below
camera.zoom = Math.min(userInput, MAX_ZOOM);
With this approach, if userInput = 3, it will get clamped at 2.5. There's also Math.max() if you want to clamp it on the lower range.

Related

How to scale a camera?

I'm trying to make a 3D scene where you can walk around the world, but my objects currently look way too small, and my camera's perspective is like from a Godzilla's. I tried to scale the camera on XYZ axis, but the view got distorted, also FOV doesn't help too.
Is there a solution to this? The only option I could think of now is to scale all of the objects instead. The problem is, there are over 100 objects, and I would have to change their parameters individually.
You can scale the scene
scene.scale.x = scene.scale.y = scene.scale.z = 10;
Or add objects to a group and scale that group:
const group = new THREE.Group();
// I guess that you're using some kind of loop for adding your objects?
group.add(objectA);
group.add(ObjectB);
// scale the group
group.scale.x = group.scale.y = group.scale.z = 10;
scene.add(group);

Change facing direction of CSS3DObject

I have a 3D scene with a bunch of CSS object that I want to rotate so that they are all pointing towards a point in the space.
My CSS objects are simple rectangles that are a lot wider than they are high:
var element = document.createElement('div');
element.innerHTML = "test";
element.style.width = "75px";
element.style.height = "10px";
var object = new THREE.CSS3DObject(element);
object.position.x = x;
object.position.y = y;
object.position.z = z;
Per default, the created objects are defined as if they are "facing" the z-axis. This means that if I use the lookAt() function, the objects will rotate so that the "test" text face the point.
My problem is that I would rather rotate so that the "right edge" of the div is pointing towards the desired point. I've tried fiddling with the up-vector, but I feel like that wont work because I still want the up-vector to point up. I also tried rotating the object Math.PI/2 along the y axis first, but lookAt() seems to ignore any prior set rotation.
It seems like I need to redefine the objects local z-vector instead, so that it runs along with the global x-vector. That way the objects "looking at"-direction would be to the right in the scene, and then lookAt() would orient it properly.
Sorry for probably mangling terminology, newbie 3D programmer here.
Object.lookAt( point ) will orient the object so that the object's internal positive z-axis points in the direction of the desired point.
If you want the object's internal positive x-axis to point in the direction of the desired point, you can use this pattern:
object.lookAt( point );
object.rotateY( - Math.PI / 2 );
three.js r.84

Shadow aliasing with ShaderMaterial on three.js

Here a picture of my problem, like you can see my shadows aren't smooth on my ShaderMaterial wich is a copy of PhongMaterial.
For the moment I have try all of these solution find on internet but nothing seems to work :
groundGeometry.computeFaceNormals();
groundGeometry.computeVertexNormals();
groundGeometry.verticesNeedUpdate = true;
renderer.shadowMapType = THREE.PCFShadowMap; //And all options possible
renderer.shadowMapCullFace = THREE.CullFaceBack; //And the other one
renderer = new THREE.WebGLRenderer({ antialias : true });
I also play with the different parameters of my SpotLight (also try with Directional light:
shadowMapWidth
shadowMapHeight
shadowCameraLeft
shadowCameraRight
shadowCameraBottom
shadowCameraTop
shadowCameraNear
shadowCameraFar
shadowBias
To be honest I don't know what to do now :/
So any help would be very appreciate !
Probably it is causes by self-shadowing. Try to set a small value of shadowBias like 0.05 or -0.05.
If your scene permits, reduce as much as possible the shadowmap frustum, changing the value of shadowCamera options to fit exactly the objects that you want.
If the angle between the light and normal at some point of the object is nearly 90 degrees, you can try to scale the bias depending of slope. There is an approach called slope scaled bias that consist in scale the bias depending of the angle between light vector and normal vector. The formula is:
float slope_bias = bias * tan(acos(dot(normal,-lightDirection)));
I hope it helps a little bit.

Openlayers WMS layer not zooming properly

I developed an script to display 2 layers ob base map.
but it is not zooming properlly.
I am using following code
can you please suggest me
<script type="text/javascript">
var map, layer, select, hover, control;
function init(){
map = new OpenLayers.Map('map', {
controls: [
new OpenLayers.Control.PanZoom(),
new OpenLayers.Control.Permalink(),
new OpenLayers.Control.Navigation()
]
});
layer = new OpenLayers.Layer.WMS(
"States WMS/WFS",
"http://localhost:8080/geoserver/topp/wms",
{layers: 'topp:india_road',transparent: true}
);
select = new OpenLayers.Layer.Vector("Selection", {styleMap:
new OpenLayers.Style(OpenLayers.Feature.Vector.style["select"])
});
hover = new OpenLayers.Layer.Vector("Hover");
map.addLayers([layer, hover, select]);
var wmsLayer = new OpenLayers.Layer.Google('Google Layer',{} );
map.addLayer(wmsLayer);
map.setCenter(new OpenLayers.Bounds(143.83482400000003,-43.648056,148.47914100000003,-39.573891).getCenterLonLat(), 5);
}
</script>
What do you mean by not zooming properly?
Are you finding that they are not matching up with the google maps when zooming in as far as you can go, or the zoom work until you try to pan and then the layers don't stay lined up with google maps? If this is the case then you are probably zooming in further than is supported by the Google map service. There is no easy way to fix this and I recommend you alter allowed scales and zoom with the following settings
minScale - float -- the minimum scale value at which the layer should display
maxScale - float -- the maximum scale value at which the layer should display
numZoomLevels - int -- Total number of zoom levels
Also please see this link on more information about google zoom scales.
If you are finding that none of your layers match the google background. I.E. they look like they are zoomed in out or offset then it is likely that your data is in a different projection to the google maps layer. Google maps uses EPSG:900913 as their SRS. The eisiest way to do this is to let geoserver do the re projection for you. Go to your layer setting in geoserver make sure you have the native projection set correctly and set the declared SRS to EPSG:900913.
If that doesn't help then I think we need more information on exactly what the problem is.

Google maps polygon optimization

I extracted country outline data from somewhere and successfully managed to convert it into an array of lat-lng coordinates that I can feed to Google maps API to draw polyline or polygons.
The problem is that that there are about 1200+ points in that shape. It renders perfectly in Google maps but I need to reduce the number of points from 1200 to less than 100. I don't need a very smooth outline, i just need to throw away the points that I can live without. Any algorithm or an online tool that can help me reduce the number of points is needed.
Found this simple javascript by Bill Chadwick. Just feed in the LatLng to an array and pass in to the source arguments in a function here Douglas Peucker line simplification routine
it will output an array with less points for polygon.
var ArrayforPolygontoUse= GDouglasPeucker(theArrayofLatLng,2000)
var polygon=new google.maps.Polygon({
path:ArrayforPolygontoUse,
geodesic:true,
strokeColor:"#0000FF",
strokeOpacity:0.8,
strokeWeight:2,
fillColor:"#0000FF",
fillOpacity:0.4,
editable:true
});
theArrayofLatLng is an array of latlng that you collected using google maps api.
The 2000 value is kink in metres. My assumption is, the higher the value, more points will be deleted as an output.
For real beginners:
Make sure you declare the js file on your html page before using it. :)
<script type="text/javascript" src="js/GDouglasPeucker.js"></script>
I think MapShaper can do this online
Otherwise, implement some algorithm
If you can install postgis which i think is easy as they provide an installer then you can import the data and execute snaptogrid() or st_simplify() for which i cannot find an equivalent in mysql.If you decide to go with postgis which i recommend cause it will help you down the road i can provide you with the details.
Now for an easy custom solution you can reduce size by cutting or rounding some of the last digits of the coords and then merge the same coords resulting actually in a simple snaptogrid().
Hope it helps
I was looking for exactly the same thing and found Simplify.js. It does exactly what you want and is incredibly easy to use. You simply pass in your coordinates and it will remove all excess points.
simplify(points, tolerance, highQuality)
The points argument should contain an array of your coordinates formatted as {x: 123, y: 123}. (Afterwards you can convert it back to the format you wish.)
The tolerance should be the precision in decimal degrees. E.g. 0.0001 for 11 meters. Increasing this number will reduce the output size.
Set highQuality to true for better results if you don't mind waiting a few milliseconds longer.
Mostly likely what you want to divide the points into 2 half and want to try my Javascript function:
function shortenAndShow ( polyline, color ) {
var dist = 0, copyPoints = Array ( );
for ( var n = 0, var end = polyline.getVertexCount ( ) - 1; n < end ; n++ ) {
dist += polyline.getVertex ( n ).distanceFrom ( polyline.getVertex ( n +1 ) );
copyPoints.push ( polyline.getVertex (n) );
}
var lastPoint = copyPoints [copyPoints.length-1];
var newLine = new GPolyline (copyPoints, color, 2, 1);
gmap2.addOverlay ( newLine );
}
I agree the Unreason's anwser,The website support GeoJson,I used it in my website,and it cut down my geoJson ,But I think you also need this world country geo Json

Resources