Extrude Buffer Geometry in Three.js? - three.js

I recently went back through a scene, replacing all the creations of
new THREE.SphereGeometry()
with buffer geometries: new THREE.SphereBufferGeometry()
(cylinder, circle, box, etc.) down the line for all my geometries.
Hit a snag creating new THREE.ExtrudeBufferGeometry()
Is there a buffered version of THREE.ExtrudeGeometry? And how do I create it?

I believe I have my answer: You create the extrude geometry first, then create a buffer geometry from it.
This example assumes you have already extruded a geometry called "extrugeom":
var buffgeom = new THREE.BufferGeometry();
buffgeom.fromGeometry(extrugeom);
var mat = new THREE.MeshBasicMaterial({ color: 0x0000ff });
var mes = new THREE.Mesh(buffgeom, mat);

Related

Sphere object deformation after changing position of sphere

I have two sphere objects on the scene. Both of them been made with default position (scene center). There is no problem when objects are in the middle, however when I want to move one to the right and second to the left, strange deformation has a place. When spheres moving away from the center on X axis they seems to be more squeezed on Y axis. It is kind of "FishEye" lens effect. Is it possible that some default cameras value is interfering to make such a result? FOV value does not bring solution for that, and I did not find information about camera lens properties. What is wrong with that?
I have tried to play with Vector3 as a position provider and spheres has the same result.
I have tried object.position.set(vector3) with no result.
Also object.position.copy(vector3) gave the same result.
Trying translate position without animation gave the same result.
Playing with FOV parameter in camera object also did not solve the problem.
// init
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(100, window.innerWidth/window.innerHeight, 0.1,10000);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
//creating sphere
var geometry = new THREE.SphereGeometry(6, 16, 16);
var material = new THREE.MeshBasicMaterial({color: 0xffffff, wireframe: true});
var sphere = new THREE.Mesh(geometry, material);
//earth
var geometry = new THREE.SphereGeometry(3, 16, 16);
var material = new THREE.MeshBasicMaterial({color: 0x0000ff, wireframe: true});
var earth = new THREE.Mesh(geometry, material);
scene.add(sphere, earth);
camera.position.z = 10;
var animation = function(){
requestAnimationFrame(animation);
update();
renderer.render(scene,camera);
}
var update = function(){
earth.rotation.y +=0.001;
sphere.rotation.y -=0.001;
sphere.rotation.x -=0.001;
sphere.position.x +=0.001;
}
I expect to move sphere.postion.x -=1; and earth.position.x+=1; without squeezing and deformation of spheres on Y axis.
Welcome to Stack Overflow. Thank you for taking the time to take the tour, and for including your code.
The fish-eye effect is likely being caused by your camera defintion:
var camera = new THREE.PerspectiveCamera(100, window.innerWidth/window.innerHeight, 0.1,10000);
The 100 is the FOV (Field of View) for your camera, and is quite wide. In a PerspectiveCamera, the wider your FOV, the more distortion you'll see for objects closer to the edges. Try setting it lower to get a more natural effect.
Do some searches for "Perspective Distortion" and you should find a host of articles on why it happens and how to mitigate it. For starters, here's the Wikipedia page: https://en.wikipedia.org/wiki/Perspective_distortion_(photography) which has a nice animation of changing the FOV for an image of a house.

Three.js: How to prevent parts of mesh from shape dissapearing at larger distance

I have a geometry that should be visible from a close and large distance. It is a shape geometry. The material used is the basic mesh material. The code is like this:
var shape = new THREE.Shape(geoPoints);
var geometry = new THREE.ShapeGeometry(shape);
var material = new THREE.MeshBasicMaterial({
color: 0x0000FF,
wireframe: true
});
var mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
When I use the wireframe property of the material, the geometry stays entirely visible. However, when I turn off the wireframe parts of the mesh dissapear from larger distance. This can be seen in the added figures:
Mesh basic material, wireframe off
Mesh basic material, wireframe on
How can this be solved? Many thanks in advance.

How to use rendering result of scene as texture in ThreeJS

I would like to use the rendering result of the scene as a texture in ThreeJS.
Does ThreeJS have such a function?
Do I need to modify ThreeJS?
Thanks.
You can render a scene to a texture by passing a THREE.WebGLRenderTarget to THREE.WebGLRenderer.render().
First, create a render target of the desired size (this is your texture) :
var renderer = new THREE.WebGLRenderer();
var renderTarget = new THREE.WebGLRenderTarget(512, 512);
You can then use THREE.WebGLRenderTarget.texture on a material :
var geometry = new THREE.PlaneGeometry(1.0, 1.0);
var material = new THREE.MeshBasicMaterial({
map: renderTarget.texture
});
var mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
Finally render the scene in 2 passes :
renderer.render(fakeScene, fakeCamera, renderTarget);
renderer.render(scene, camera);
You may want to create a new scene and a new camera to render on the renderTarget. It depends on what you want to do.
Take a look at this fiddle and this example.

Three.js: Add a texture to an object just on the outside

I'm very new with Three.js and I'm trying to make a ring:
http://www.websuvius.it/atma/myring/preview.html
I have a background texture ( the silver one ) and another one with a text.
I want the text only on the ring external face.
This is part of my code:
var loader = new THREE.OBJLoader( manager );
var textureLoader = new THREE.TextureLoader( manager );
loader.load( 'assets/3d/ring.obj', function ( event ) {
var object = event;
var geometry = object.children[ 0 ].geometry;
var materials = [];
var backgroundTexture = textureLoader.load('img/texture/silver.jpg');
backgroundTexture.flipY = false;
var background = new THREE.MeshBasicMaterial({
map: backgroundTexture,
color: 0xffffff
});
materials.push(background);
var customTexture = textureLoader.load('img/text.png');
customTexture.flipY = false;
var custom = new THREE.MeshBasicMaterial({
map: customTexture,
transparent: true,
opacity: 1,
color: 0xffffff
});
materials.push(custom);
mesh = THREE.SceneUtils.createMultiMaterialObject(geometry, materials);
mesh.position.y=-50;
scene.add(mesh);
}, onProgress, onError );
It is possible?
Thanks
The reason behind your issue appears to be in your .obj file. Judging from a quick glance at the texture coordinates stored in the file, the inside of the ring uses the same part of the texture image as the outside of the ring.
Increasing the transparent parts of the image won't help. Neither will the attempts to stop the texture from repeating. Those would help if the texture coordinates were larger than 1 but this is not your case unfortunately.
However, there are several solutions:
Split the object in a 3D modeling software to two objects - outside and inside of the ring - and apply the texture only to the first one.
Adjust the UV coordinates of the object in a 3D modeling software.
Adjust the UV coordinates of the vertices programmatically after loading the object to Three.JS

three.js planegeometry with texture map from jpg image is coming up black

I'm trying to apply a texture to a planeGeometry using the three.js engine.
I should be seeing a football field, I'm actually seeing black.
If I replace the map:texture argument with color:0x80ff80, I get a field of solid green, demonstrating that the geometry is in the correct place.
The page contains an which appears in the files before any scripts. I can display that image, demonstrating that there isn't a problem with the image.
The files are being served locally by an http server.
The code I'm using to build the material and PlaneGeometry is below. Any ideas appreciated. Thank you.
function buildField( fieldLength, fieldWidth, scene) {
var image = document.getElementById("fieldTexture");
var texture = new THREE.Texture(image);
texture.minFilter = THREE.LinearFilter;
var geometry = new THREE.PlaneGeometry(fieldLength, fieldWidth, 5, 5);
var material = new THREE.MeshBasicMaterial( {map:texture, side:THREE.DoubleSide});
var field = new THREE.Mesh(geometry, material);
field.rotation.x = -Math.PI/2;
scene.add(field);
}
THREE.ImageUtils is already deprecated. (source)
Use THREE.TextureLoader().load('field.png') instead
Try this, own THREE.js methods usually work better...:
texture = THREE.ImageUtils.loadTexture('field.png');
material = new THREE.MeshBasicMaterial({map: texture});
var field = new THREE.Mesh(geometry, material);

Resources