I want to display a photograph in my THREE.js scene. The size of the geometry is based on on the window and the photograph, which added as Texture should cover the geometry. Basically what I want is background-size: cover in CSS, but in THREE.js, so that I can add some more transformations to this geometry.
This is my code so far:
const txture = this.loader.load('/site/themes/pride/img/home_1.jpg');
const material = new MeshBasicMaterial({
map: txture,
transparent: true,
opacity: 1,
});
const geom = new BoxBufferGeometry( window.innerWidth, window.innerHeight, 0.0001 );
const plane = new Mesh(geom, material);
plane.overdraw = true;
plane.position.set(0,0,0);
Is this even possible or should I do it in a complete other way?
Related
For example, in the case of level 2, the texture of one face of a cube is composed of 16 separate images.
How should I render 96(6x16) or more images onto a sphere?
I used cubeTexture to merge the image of level 1, but there was an error when I rendered it to the sphere.
An Error
Demo
const cubeLoader = new THREE.CubeTextureLoader();
cubeLoader.setPath('/texture/');
const skybox = cubeLoader.load([
'/skybox/sky_pos_x.png', '/skybox/sky_neg_x.png',
'/skybox/sky_pos_y.png', '/skybox/sky_neg_y.png',
'/skybox/sky_pos_z.png', '/skybox/sky_neg_z.png'
]);
scene.background = skybox;
const earthGeo = new THREE.SphereGeometry(5, 640, 320);
// earthMaterial.shadowSide=THREE.DoubleSide;
const earthMaterial = new THREE.MeshPhysicalMaterial({
envMap: cubeLoader.load([
'/moon/surface_diff_pos_x.png', '/moon/surface_diff_neg_x.png',
'/moon/surface_diff_pos_y.png', '/moon/surface_diff_neg_y.png',
'/moon/surface_diff_pos_z.png', '/moon/surface_diff_neg_z.png'
]),
bumpMap: cubeLoader.load([
'/moon/surface_bump_pos_x.png', '/moon/surface_bump_neg_x.png',
'/moon/surface_bump_pos_y.png', '/moon/surface_bump_neg_y.png',
'/moon/surface_bump_pos_z.png', '/moon/surface_bump_neg_z.png'
]),
normalMap: cubeLoader.load([
'/moon/surface_norm_pos_x.png', '/moon/surface_norm_neg_x.png',
'/moon/surface_norm_pos_y.png', '/moon/surface_norm_neg_y.png',
'/moon/surface_norm_pos_z.png', '/moon/surface_norm_neg_z.png'
])
});
console.log(earthMaterial);
const earth = new THREE.Mesh(earthGeo, earthMaterial);
However, there is no error when applying texture to envMap or skyBox to map
Applying a texture to a cylinder geometry in THREE JS causes some weird distortion of the texture as can be seen in this image:
The shape is created like so:
var cylinderGeo = new THREE.CylinderGeometry(0.1, 1, 1, 4, 1, false, Math.PI / 4);
cylinderGeo.computeFlatVertexNormals();
var mesh = new THREE.Mesh(cylinderGeo);
mesh.position.x = 10;
mesh.scale.set(10, 5, 10);
mesh.material = new THREE.MeshLambertMaterial();
// LOAD TEXTURE:
textureLoader.load("/textures/" + src + ".png", function (texture) {
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
texture.repeat.set(2,2);
texture.needsUpdate = true;
mesh.material.map = texture;
mesh.material.needsUpdate = true;
});
The texture seems to be applied per polygon and not per face? How can i make it wrap around the cylinder without any such artifacts?
EDIT: The texture is 256x256
Each side of your pyramid is composed of two triangles. You can see this quite clearly in the example on the CylinderGeometry documentation page.
Each triangle has UVs which are created based on the assumption that both triangles will be the same scale, like they are in the example. By making one end of your cylinder smaller, you're changing the scale of the triangles, but your UVs are remaining the same.
You can either edit the UVs to make up for the difference, or (and I recommend) create your own geometry with proper UVs defined.
I am trying to draw a least squares plane through a set of points in Three.js. I have a plane defined as follows:
var plane = new THREE.Plane();
plane.setFromNormalAndCoplanarPoint(normal, point).normalize();
My understanding is that I need to take that plane and use it to come up with a Geometry in order to create a mesh to add to the scene for display:
var dispPlane = new THREE.Mesh(planeGeometry, planeMaterial);
scene.add(dispPlane);
I've been trying to apply this answer to get the geometry. This is what I came up with:
plane.setFromNormalAndCoplanarPoint(dir, centroid).normalize();
planeGeometry.vertices.push(plane.normal);
planeGeometry.vertices.push(plane.orthoPoint(plane.normal));
planeGeometry.vertices.push(plane.orthoPoint(planeGeometry.vertices[1]));
planeGeometry.faces.push(new THREE.Face3(0, 1, 2));
planeGeometry.computeFaceNormals();
planeGeometry.computeVertexNormals();
But the plane is not displayed at all, and there are no errors to indicate where I may have gone wrong.
So my question is, how can I take my Math.Plane object and use that as a geometry for a mesh?
This approach should create a mesh visualization of the plane. I'm not sure how applicable this would be towards the least-squares fitting however.
// Create plane
var dir = new THREE.Vector3(0,1,0);
var centroid = new THREE.Vector3(0,200,0);
var plane = new THREE.Plane();
plane.setFromNormalAndCoplanarPoint(dir, centroid).normalize();
// Create a basic rectangle geometry
var planeGeometry = new THREE.PlaneGeometry(100, 100);
// Align the geometry to the plane
var coplanarPoint = plane.coplanarPoint();
var focalPoint = new THREE.Vector3().copy(coplanarPoint).add(plane.normal);
planeGeometry.lookAt(focalPoint);
planeGeometry.translate(coplanarPoint.x, coplanarPoint.y, coplanarPoint.z);
// Create mesh with the geometry
var planeMaterial = new THREE.MeshLambertMaterial({color: 0xffff00, side: THREE.DoubleSide});
var dispPlane = new THREE.Mesh(planeGeometry, planeMaterial);
scene.add(dispPlane);
var material = ...;
var plane = new THREE.Plane(...);
// Align to plane
var geometry = new THREE.PlaneGeometry(100, 100);
var mesh = new THREE.Mesh(geometry, material);
mesh.translate(plane.coplanarPoint());
mesh.quaternion.setFromUnitVectors(new THREE.Vector3(0,0,1), plane.normal);
Note that Plane.coplanarPoint() simply returns -normal*constant, so it might be a better option to use Plane.projectPoint() to determine a center that is "close to" an arbitrary point.
I'm trying to create a three-dimensional compass, that also displays roll and pitch. In order to show the roll (in degrees), I need to apply a texture with numbers to a TorusMaterial. How can I get it on in such a way that the scale is (somewhat) retained?
The black ring in the picture below (around the compass) is the TorusGeometry. The other attached picture is the texture.
Code:
var geometry = new THREE.TorusGeometry(2.41, 0.2, 50, 50);
// var material = new THREE.MeshBasicMaterial({ color: 0x000000, wireframe: false });
var material = new THREE.MeshPhongMaterial();
material.map = THREE.ImageUtils.loadTexture('styles/quarters.png');
var torus = new THREE.Mesh(geometry, material);
scene.add(torus);
Screenshot:
Texture
I have an idea to create, but since my knowledge about Three.js and 3D programming in general is limited, I am stuck...
Idea: User is doing some things. At some point - whole front screen crashes, and reveals something different behind.
At the beginning, my idea was - make screenshot, of what is happening right now, put that image in front of everything (still, having difficulties making that plane to take 100% size - idea - when it shows, user cannot tell the difference, between old 3d renderings, and new 2d picture), and then - shatter it. So - by looking around the Web for different examples, I made some... thing - Created screenshot, made plane and applied screenshot as a texture to it. To create shattering effect, I used TessellateModifier to divide that plane, and ExplodeModifier to create each face as separated face.
Here will be the code I made so far.
function drawSS()
{
var img = new Image;
img.onload = function() { // When screenshot is ready
var canvas = document.createElement('canvas');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var context = canvas.getContext('2d');
// CANVAS DRAWINGS
// Draws screenshot
// END
var texture = new THREE.Texture(canvas);
texture.needsUpdate = true;
var multiMaterial = [
new THREE.MeshBasicMaterial({map: texture, side: THREE.FrontSide}), // canvas drawings
new THREE.MeshBasicMaterial( { color: 0xffffff, wireframe: true, transparent: true}) // for displaying wireframe
];
var geometry = new THREE.PlaneGeometry(canvas.width, canvas.height); // create plane
for (var i = 0, len = geometry.faces.length; i < len; i++) { // Snippet from some stackoverflow post, that works.
var face = geometry.faces[i].clone();
face.materialIndex = 1;
geometry.faces.push(face);
geometry.faceVertexUvs[0].push(geometry.faceVertexUvs[0][i].slice(0));
}
geometry.dynamic = true;
THREE.GeometryUtils.center( geometry ); // ?
var tessellateModifier = new THREE.TessellateModifier( 10 );
for ( var i = 0; i < 5; i ++ )
tessellateModifier.modify( geometry );
new THREE.ExplodeModifier().modify( geometry );
geometry.vertices[0].x -=300;
geometry.vertices[1].x -=300;
geometry.vertices[2].x -=300;
var mesh = new THREE.Mesh( geometry, new THREE.MeshFaceMaterial(multiMaterial) );
scene.add( mesh );
};
// THEN, set the src
img.src = THREEx.Screenshot.toDataURL(renderer);
}
For now - I moved 1 face, by changing coordinates of 3 vertices. I'm asking - if this approach is the way to go? Result looks like this. (white lines - wireframe, black lines - (drawings in canvas) my desired wireframes - problem for later). Note - by moving this way - texture goes along, I don't know, if I make new triangles using these vertices, how would I set texture.