Sphere texture does not cover the whole sphere - javascript

When the texture is applied on the sphere, ugly folds appear at poles and part of the texture is missing.
var geometry = new THREE.SphereGeometry(50, 50, 50, 0, Math.PI * 2, 0, Math.PI * 2);
var load = new THREE.TextureLoader().load("e.jpg");
load.anisotropy = 8;
var material = new THREE.MeshBasicMaterial({
map: load,
overdraw: true
});
sphere = new THREE.Mesh(geometry, material);
scene.add(sphere);
How to do it correctly?

You created a sphere with twice the number of circles of latitude.
Try this :
var geometry = new THREE.SphereGeometry(50, 50, 50, 0, Math.PI * 2, 0, Math.PI);
var load = new THREE.TextureLoader().load("e.jpg");
load.anisotropy = 8;
var material = new THREE.MeshBasicMaterial({
map: load,
overdraw: true
});
sphere = new THREE.Mesh(geometry, material);
scene.add(sphere);
By the way, you can leave extra parameters to default by not passing those to the constructor :
var geometry = new THREE.SphereGeometry(50, 50, 50);

hi try to first load required image and on load use following code.
var earthTexture = new THREE.TextureLoader().load("e.jpg");
var earthGeometery = new THREE.SphereGeometry(50, 50, 50);
var earthMaterial = new THREE.MeshLambertMaterial({
map: earthTexture,
transparent: false
});
imgObj : is image object

Related

How does three.js render video according to spherical UV?

I have a dash streaming video. According to its title, it is a 3*3. Now I can splice the complete video through the THREE,
// 3*3 PlaneGeometry
var geometry = new THREE.PlaneGeometry(400, 200, 3, 3);
const video1 = document.getElementById("videos1");
...................
...................
const texture1 = new THREE.VideoTexture(video3);
texture1.maxFilter = THREE.NearestFilter;
texture1.minFilter = THREE.NearestFilter;
...................
...................
var geometryfaces = geometry.faces;
for (let i = 0; i < geometryfaces.length; i++) {
const faces = geometryfaces[i];
materials[i] = new THREE.MeshBasicMaterial({
map: textures[i],
});
}
var uv = [
new THREE.Vector2(0, 0),
new THREE.Vector2(0, 1),
new THREE.Vector2(1, 1),
new THREE.Vector2(1, 0),
];
// Set the texture coordinates
for (var m = 0; m < geometryfaces.length; m += 2) {
geometry.faces[m].materialIndex = faceId;
console.log(geometry.faces);
geometry.faces[m + 1].materialIndex = faceId;
geometry.faceVertexUvs[0][m] = [uv[2], uv[3], uv[1]];
geometry.faceVertexUvs[0][m + 1] = [uv[3], uv[0], uv[1]];
faceId++;
}
var bufferGeometry = new THREE.BufferGeometry().fromGeometry(geometry);
var material = new THREE.MeshFaceMaterial(materials);
var mesh = new THREE.Mesh(bufferGeometry, material); //网格模型对象Mesh
This way I can get a full flat video, but this video is panoramic and I need to render it on the ball, and I don't know much about the UV of the ball。
I need help. Thank you
picture:enter image description here
picture2:enter image description here
Three.js SphereGeometry automatically creates the UV mapping for you. Since the image you're using is equirectangular, you can just map the image onto the inside of the sphere for the effect you want:
var camera, scene, renderer, vp, sphere;
vp = new THREE.Vector2(window.innerWidth, window.innerHeight);
// Init WebGL stuff
function init() {
// WebGL Renderer
renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(vp.x, vp.y);
renderer.domElement.classList.add("canvasWebGL");
// append to DOM
document.body.appendChild(renderer.domElement);
// scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0xe1e1e1);
// camera
camera = new THREE.PerspectiveCamera(55, vp.x / vp.y, 0.05, 100);
// Sphere radius is large enough to surround the camera
let sphereGeom = new THREE.SphereGeometry( 20, 128, 128 );
// Just use your equirect image as the texture
// And render the INSIDE of the sphere, not the outside
const tex = new THREE.TextureLoader().load("https://i.imgur.com/1VECsLy.jpg");
let sphereMat = new THREE.MeshBasicMaterial({
map: tex,
side: THREE.BackSide
});
sphere = new THREE.Mesh(sphereGeom, sphereMat);
scene.add(sphere);
}
function animate(s) {
sphere.rotation.set(
Math.cos(s / 3000), s / 3000, 0
);
renderer.render(scene, camera);
requestAnimationFrame(animate);
}
init();
animate(0);
<script src="https://cdn.jsdelivr.net/npm/three#0.123/build/three.js"></script>
Read more about sphere geometry here: https://threejs.org/docs/?q=material#api/en/geometries/SphereGeometry

Draw a basic triangle with Three.js

I am triyng to learn three.js I want to dra a basic triangle however my codes do not work.
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 70, window.innerWidth/window.innerHeight, 0.1, 1000 );
camera.position.z = 10;
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
var geometry = new THREE.Geometry();
geometry.vertices= [new THREE.Vector3(2,1,0), new THREE.Vector3(1,3,0), new THREE.Vector3(3,4,0)];
geometry.faces = [new THREE.Face3(0,1,2)];
var mesh= new THREE.Mesh( geometry, new THREE.MeshBasicMaterial({ color: 0xffff00 }) );
scene.add(mesh);
renderer.render(scene, camera);
Where i am doing it wrong?
With Faces
var geom = new THREE.Geometry();
var v1 = new THREE.Vector3(0, 0, 0);
var v2 = new THREE.Vector3(30, 0, 0);
var v3 = new THREE.Vector3(30, 30, 0);
var triangle = new THREE.Triangle(v1, v2, v3);
var normal = triangle.normal();
geom.vertices.push(triangle.a);
geom.vertices.push(triangle.b);
geom.vertices.push(triangle.c);
geom.faces.push(new THREE.Face3(0, 1, 2, normal));
var mesh = new THREE.Mesh(geom, new THREE.MeshNormalMaterial());
scene.add(mesh);
Just Outline
var geometry = new THREE.Geometry();
geometry.vertices.push(new THREE.Vector3(-30, 2, 2));
geometry.vertices.push(new THREE.Vector3(2, 30, 2));
geometry.vertices.push(new THREE.Vector3(30, 2, 2));
geometry.vertices.push(new THREE.Vector3(-30, 2, 2));
var line = new THREE.Line(
geometry,
new THREE.LineBasicMaterial({ color: 0x00ff00 })
);
scene.add(line);
It's funny how hard was to find an updated answer, since Geometry was deprecated in recent versions of Three.js the way I found to draw a plane triangle is with Shape primitive.
const shape = new THREE.Shape();
const x = 0;
const y = 0;
shape.moveTo(x - 2, y - 2);
shape.lineTo(x + 2, y - 2);
shape.lineTo(x, y + 2);
const TriangleGeometry = new THREE.ShapeGeometry(shape);
based on https://threejs.org/docs/index.html?q=ShapeGeometry#api/en/geometries/ShapeGeometry
You have to be careful with the order in which you add the vertices to the face. If the order follows a clockwise order, the normal vector of the surface will point down. And since your camera looks from above, you won't see the triangle. If the order is counterclockwise, the normal will point towards your camera.
It will work if you change:
geometry.faces = [new THREE.Face3(0,1,2)];
To:
geometry.faces = [new THREE.Face3(1,0,2)];
You can also use the argument side, which applies it to both sides of the face.new THREE.MeshBasicMaterial({ color: 0xffff00, side: THREE.DoubleSide };

Why some STL models turn to pure black in three.js scene?

Screenshot 1
Screenshot 2
I have some models(STL) turn to pure black while other models get color(from lights) correctly.
As you can see in Screenshot 1 and 2,the fighter got a nice color but the miku is totally black. It seems no light illuminates her or she behaves like being applied with black BasicMaterial.
The 2 models are applied with PhongMaterial. And I tried several combnations of lights with different position/type/parameter but it didn't work.
I'm sure about that the model of miku is normal. I just downloaded the fighter and miku from the same website,where they both displays with color. I also have some models which turn to pure black in my scene ,though they're normal STL model.
There must be some mistakes in my scene.
Here is my code:
<script>
var renderer;
function initThree() {
width = document.getElementById('canvas-frame').clientWidth;
height = document.getElementById('canvas-frame').clientHeight;
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(width, height);
document.getElementById('canvas-frame').appendChild(renderer.domElement);
}
var camera;
function initCamera() {
camera = new THREE.PerspectiveCamera(45, width / height, 1, 10000);
camera.position.x = 50;
camera.position.y = 0;
camera.position.z = 0;
camera.lookAt({
x: 0,
y: 0,
z: 0
});
}
var scene;
function initScene() {
scene = new THREE.Scene();
}
//光源1
var light;
function initLight() {
light = new THREE.DirectionalLight(0xfefff7, 2.0, 0);
light.position.set(0, 500, 0);
scene.add(light);
}
//光源2
var light2;
function initLight2() {
light2 = new THREE.DirectionalLight(0x414141, 1.0, 0);
light2.position.set(0, -500, 0);
scene.add(light2);
}
//此光源暂时无用
var light3;
function initLight3() {
light3 = new THREE.SpotLight(0xffffff, .7, 0);
light3.spotLight = new THREE.SpotLight(0xffffff, .7, 0);
light3.position.set(-700, 1000, 1000);
light3.castShadow = true;
scene.add(light3);
}
//此光源暂时无用
var light4;
function initLight4() {
light4 = new THREE.PointLight(0xffffff, 0.7, 0);
light4.position.set(3200, -3900, 3500);
light4.castShadow = true;
scene.add(light4);
}
//
//创造木星
var sphere;
function initSphere() {
var bitmap = new Image();
bitmap.src = 'img/jupiter.jpg';
var texture = THREE.ImageUtils.loadTexture(bitmap.src);
var material = new THREE.MeshPhongMaterial({
map: texture
});
var geometry = new THREE.SphereGeometry(50, 64, 64);
sphere = new THREE.Mesh(geometry, material);
sphere.position.set(0, 17, -120);
scene.add(sphere);
}
//加载模型文件
var loader = new THREE.STLLoader();
function initLoad() {
loader.addEventListener('load', function (event) {
var geometryOfFiles = event.content;
var materialOfFiles = new THREE.MeshPhongMaterial({
wrapAround: true,
wrapRGB: new THREE.Vector3(0, 1, 1),
color: 0xFFFFFF,
specular: 0xFFFFFF,
shading: THREE.SmoothShading,
shininess: 630,
fog: false,
side: THREE.DoubleSide
});
var object = new THREE.Mesh(geometryOfFiles, materialOfFiles);
object.position.set(0, 0, 0);
object.rotation.set(-Math.PI / 2, 0, Math.PI / 111);
object.scale.set(2, 2, 2);
scene.add(object);
});
loader.load('miku.stl');
}
var loader1 = new THREE.STLLoader();
function initLoad1() {
loader1.addEventListener('load', function (event) {
var geometryOfFiles = event.content;
var materialOfFiles = new THREE.MeshPhongMaterial({
wrapAround: true,
wrapRGB: new THREE.Vector3(0, 1, 1),
color: 0xFFFFFF,
specular: 0xFFFFFF,
shading: THREE.SmoothShading,
shininess: 230,
fog: false,
side: THREE.DoubleSide
});
var object = new THREE.Mesh(geometryOfFiles, materialOfFiles);
object.position.set(0, 20, 50);
object.rotation.set(-Math.PI / 2, 0, Math.PI / 111);
object.scale.set(0.5, 0.5, 0.5);
scene.add(object);
});
loader1.load('f35.stl');
}
var controls;
function setControl() {
controls = new THREE.TrackballControls(camera);
/*
controls.rotateSpeed = 5.0;
controls.zoomSpeed = 5;
controls.panSpeed = 2;
controls.noZoom = false;
controls.noPan = false;
controls.staticMoving = false;
controls.dynamicDampingFactor = 0.3;*/
}
function animate() {
controls.update();
renderer.clear();
renderer.render(scene, camera);
requestAnimationFrame(animate);
sphere.position.x -= 0.1;
sphere.rotation.y += -0.005;
}
function threeStart() {
initThree();
initCamera();
initScene();
initLight3();
initLight4();
initSphere();
setControl();
animate();
initLoad();
initLoad1();
}
</script>
seeing that adding an AmbientLight helped it will probably be normals calculated incorrectly or missing altogether check them here
geometry.faces[0].normal;
and to calculate the correct values call
geometry.computeFaceNormals()
To answer your question about how thingiverse shows them correct: after looking at their code I noticed they dont actually use those STL files they provide, but have a JSON file to load from (using THREE.JSONLoader)
these files have normals correct(they might have done some precalculations on files uploaded by users) but you would have to check the STL yourself
the miku JSON file can be found at http://thingiverse-production-new.s3.amazonaws.com/threejs_json/51/67/c8/34/6d/293cd764miku.js
don't know if computeFaceNormals() is outdated, but in my case i had to do:
const caseGeometry = useLoader(STLLoader, CaseObject)
caseGeometry.computeVertexNormals()
works like a charm, though 👍

Three.js: extruding a triangle mesh from a flat 3d plane triangle shape

Trying to extrude a triangle mesh from a Vector3 triangle.
I'm calling extrudeSettings in:
var triangleGeometry = new THREE.Geometry(extrudeSettings);
But it's not extruding. What am I doing wrong here?
Here's a plunker
Here's the relevant JS:
drawTriangle(
new THREE.Vector3(0, 0, 0),
new THREE.Vector3(4, 0, 0),
new THREE.Vector3(2, 3.4641, 0)
);
var extrudeSettings = {
steps : 100,
bevelEnabled : false,
extrudePath : closedSpline
};
function drawTriangle (vertex1, vertex2, vertex3) {
var triangleGeometry = new THREE.Geometry(extrudeSettings);
var triangleMaterial = new THREE.MeshBasicMaterial({
color: 0x000000,
wireframe: true,
wireframeLinewidth: 1
});
var triangle = new THREE.Mesh(triangleGeometry, triangleMaterial);
triangleGeometry.vertices = [vertex1, vertex2, vertex3];
triangleGeometry.faces.push(new THREE.Face3(0, 1, 2));
THREE.GeometryUtils.center(triangleGeometry);
scene.add(triangle);

Three js Add plane to the scene

I am trying to add a plane to the scene but if I check children's scene nothing is added.
var plane = new THREE.Mesh( new THREE.PlaneGeometry( 2000, 2000, 8, 8 ), new THREE.MeshBasicMaterial( { color: 0xffff00, opacity: 0.25 } ) );
plane.visible = true;
this.scene.add( plane );
try this:
var geo = new THREE.PlaneBufferGeometry(2000, 2000, 8, 8);
var mat = new THREE.MeshBasicMaterial({ color: 0x000000, side: THREE.DoubleSide });
var plane = new THREE.Mesh(geo, mat);
scene.add(plane);
if you want to use the plane as a floor, you have to rotate it.
plane.rotateX( - Math.PI / 2);

Categories