I've got full equirectangular images working well with Three.js:
scene = new THREE.Scene();
geometry = new THREE.SphereBufferGeometry( 500, 60, 40 );
geometry.scale(-1, 1, 1);
material = new THREE.MeshBasicMaterial({ map: texture });
mesh = new THREE.Mesh(geometry, material);
mesh.rotation.y = Math.PI;
scene.add( mesh );
But my images actually only contain 180x180 degrees (half the sphere) so I'm trying to get a square texture partially applied on the spherical mesh without stretching the image across the entire sphere. I figure it has something to do with the texture.offset.xyz parameters, but I haven't been successful. While I can continue to pad my images to conform to 2x1 Equirectangular standards, I'd rather cut this step out of my processing workflow.
Below you'll find both the full equirectangular image and the square one I'm trying to get working. Does anyone have any clues on how to accomplish this? Thanks!
SphereBufferGeometry has more optional parameters:
SphereBufferGeometry(radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength)
radius — sphere radius. Default is 50.
widthSegments — number of horizontal segments. Minimum value is 3, and the default is 8.
heightSegments — number of vertical segments. Minimum value is 2, and the default is 6.
phiStart — specify horizontal starting angle. Default is 0.
phiLength — specify horizontal sweep angle size. Default is Math.PI * 2.
thetaStart — specify vertical starting angle. Default is 0.
thetaLength — specify vertical sweep angle size. Default is Math.PI.
you can use phiStart, phiLength, thetaStart and thetaLength to define partial sphere
so to do an half sphere you can try something like:
geometry = new THREE.SphereBufferGeometry( 500, 60, 40, 0, Math.PI, 0, Math.PI );
reference http://threejs.org/docs/#Reference/Extras.Geometries/SphereBufferGeometry
The error is not in source code, it's in texture images: they are both wrong.
A 180 degrees fisheye like this:
reprojected into equirectangular will look like this:
Your textures looks like a mix of 360x180 equirectangular and 270° fisheye, wihich looks like this (with wrong labels/numbers, as I used same 180 FOV fisheye to create it):
Related
I created a full sphere out of sphere tiles, to handle all of them individually when they are inside the FOV.
To do that I divided an equirectangular panorama into a few quadratic images to map them onto these tiles. But somehow the texture is shifted on the highest and lowest row of segments in every tile.
Example with some imported sqare images:
The original test image:
How can I geht the textures map correctly to the tiles? The code for creating the tiles is below:
/*
segment Data:
x/y are generated by a loop
maxX/maxY are the maximum values of these loops
*/
sphere = new THREE.SphereGeometry(radius, 4, 4, segmentData.x * 2 * Math.PI / segmentData.maxX, 2 * Math.PI / segmentData.maxX, segmentData.y * Math.PI / segmentData.maxY, Math.PI / segmentData.maxY);
texture = new THREE.TextureLoader().load(tileImagePath);
material = new THREE.MeshBasicMaterial({map: texture});
mesh = new THREE.Mesh(sphere, material);
scene.add(mesh);
I'm quite new to three.js so maybe this is a very simple problem.
Hopefully somebody can help?
Thanks to ScieCode, it turned out, that the problem was caused by a bug in versions r103 and r104.
It will be fixed in the next release: https://github.com/mrdoob/three.js/issues/16454
I'm working with THREE JS. I have a sphere object (made using THREE.SphereGeometry) and inside this sphere I have another smaller sphere. Both spheres have the same center (so the smaller sphere sits exactly in the middle of the bigger sphere). My camera is located inside the bigger sphere and I can see the inside surface of the bigger sphere (Im inside a 3D shop). Here I create the bigger outer sphere:
setupSphereProjection() {
// creation of a big sphere geometry
//THREE.SphereGeometry(SPHERE RADIUS, WIDTH SEGMENTS, HEIGHT SEGMENTS)
this.sphere = new THREE.SphereGeometry(sphereRadius, 40, 40);
this.sphere.applyMatrix(new THREE.Matrix4().makeScale(-1, 1, 1));
// creation of the sphere material
let sphereMaterial = new THREE.MeshBasicMaterial();
let loader = new THREE.TextureLoader();
loader.crossOrigin = "anonymous";
sphereMaterial.map = loader.load(testImage);
// geometry + material = mesh (actual object)
this.sphereMesh = new THREE.Mesh(this.sphere, sphereMaterial);
this.scene.add(this.sphereMesh);
}
My setup is such that when I click on the surface of the bigger sphere I get an XYZ coordinate of the click on the bigger sphere surface. What I want is for the smaller sphere to rotate to face the location of the XYZ coordinate. (so when the user clicks on the surface of the bigger sphere the smaller sphere rotates to look at the location of the click on the outer sphere). Here is the THREE.Vector3 I get when I click on the surface of the outer sphere (radius is 100):
THREEE.Vector3 {x: -8.755543860298761, y: -2.284054920077946, z: -99.22118491615181}
I'm struggling to convert the XYZ coordinate into a rotation of the inner sphere. I'm not sure if I should use Quaternions or Euler angles or both. I've tried different approaches and none of them have worked so far. Any help/advice would be warmly welcomed.
First time using three.js and I'm doing a very simple particle animation in which I'm mapping 4 different textures. So far everything is working as desired except that I can't figure out how to rotate particles so that they're rendered with a random orientation (upside down, sideways, etc.) Any help would be appreciated!
You can see my progress so far here: http://development.shapes.divshot.io/particles.html
And here is the relevant code:
sprite1 = THREE.ImageUtils.loadTexture( "sprite1.png" );
sprite2 = THREE.ImageUtils.loadTexture( "sprite2.png" );
sprite3 = THREE.ImageUtils.loadTexture( "sprite3.png" );
sprite4 = THREE.ImageUtils.loadTexture( "sprite4.png" );
parameters = [ sprite1, sprite2, sprite3, sprite4];
for ( i = 0; i < parameters.length; i ++ ) {
sprite = parameters[i];
materials[i] = new THREE.PointCloudMaterial( { size: 45, map: sprite, depthTest: false, transparent : true} );
particles = new THREE.PointCloud( geometry, materials[i] );
particles.rotation.x = Math.random() * 60;
particles.rotation.y = Math.random() * 60;
particles.rotation.z = Math.random() * 60;
scene.add( particles );
}
Using three.js r71
AFAIK the three.js PointCloud/PointCloudMaterial particle system uses gl.POINTS to draw the points. Which means it has several limitations.
You can't rotate the points.
You can rotate the UV coordinates in your fragment shader if you write a custom shader but that won't help if your image fills the point because rotating a square texture inside a square will clip the corners as it rotates.
You can't make points larger than the max point side of the GPU/Driver you're on.
WebGL only requires the max size = 1.0 which means there are GPUs/Drivers that only support 1 pixel large points.
Checking webglstats.com it looks like the number of GPUs/Drivers that only support 1 pixel large points has gotten smaller. There's still about 5% of machines that only support points 63 pixels and smaller which should only be an issue if you're flying through a point field.
You can only have square points.
You can't have rectangular point if you wanted something long and thin like a spark for example.
One solution is to make your own particle system that uses quads and can rotate their vertices as well as scale them in multiple directions. This example runs entirely on the GPU. Unfortunately it is not three.js based.
I want to extrude a shape and create an ExtrudeGeometry, but the shape has to be extruded into a certain direction. I have a direction in a Vector3
The shape is drawn in in the x, y plane and normally the z is the extrude direction (extrusion depth). So a direction vector (0,0,1) would result in the default extrusion. But for example a (0,0,-1) would extrude the shape in the other direction.
I first tried to use an extrude path to achieve this, but when using a path the shape is allowed to "spin" freely and the initial orientation is arbitrary. This is not what I need, the shape must stay oriented as is. You can read details on this here in my previous question.
I already came up with the idea of applying a matrix to the second half of the vertices of the resulting ExtrudedGeometry, but I cannot seem to get the geometry I want. Maybe it is my clumsy use of matrices, but I think that the face normals are pointing inside out after this trick.
Note The direction vector will never be orthogonal to the z axis since this would give invalid shapes
So the question:
How do I get a reliable solution to extrude my shape into the given direction. Here an example. The shape is a square in the x,y plane (width and length 2000) the extrusion depth is also 2000 and three different vectors with a drawing of the expected result seen in 2D (front view) and 3D.
Extrude your geometry in the usual way by specifying an extrusion depth, and then apply a shear matrix to your geometry.
Here is how to specify a shear matrix that will tilt a geometry.
var matrix = new THREE.Matrix4();
var dir = new THREE.Vector3( 0.25, 1, 0.25 ); // you set this. a unit-length vector is not required.
var Syx = dir.x / dir.y,
Syz = dir.z / dir.y;
matrix.set( 1, Syx, 0, 0,
0, 1, 0, 0,
0, Syz, 1, 0,
0, 0, 0, 1 );
geometry.applyMatrix4( matrix );
(The three.js coordinate system has the y-axis up -- unlike in your illustration. You will have to accommodate.)
three.js r.113
There is an online 3d editor where you can edit individual meshes (move, scale, rotate). Ability to edit meshes implemented using custom transform controls which based on threejs's TransformControls code. This is fragment from mousemove event:
var intersect = intersectObjects(pointer, [xzPlane]); // intersect mouse's pointer with horizontal plane
var point = new THREE.Vector3();
point.copy(intersect.point);
point.sub(offset); // coords from mousedown event (from start stretching)
// some code for 'scale' value calculating base on 'point' variable
// var scale = ...;
//
mesh.scale.x = scale;
This code works well if the mesh does not rotate.
Requires scaling always happened to the world coordinate system. This is programming question
For example, from this:
To this:
P.S. I think that custom mesh matrix must be created, but I have very little experience with matrices
Thanks!
Instead of setting the rotation, like so:
mesh.rotation.set( Math.PI/4, 0, 0 );
apply the identical rotation to the geometry, instead:
var euler = new THREE.Euler( Math.PI / 4, 0, 0 );
mesh.geometry.applyMatrix( new THREE.Matrix4().makeRotationFromEuler( euler ) );
Now, you can set the scale and get the result you want.
mesh.scale.z = 2;
fiddle: http://jsfiddle.net/Tm7Ab/5/
three.js r.67