Three.JS - Remove yellow box when using EdgesGeometry, LineSegments, and BoxHelper - javascript

Three.js Version: 82
I'm looking at this example here: https://threejs.org/examples/#webgl_helpers
Notice that there are yellow boxes around the models. I was using version 79 and was using THREE.EdgesHelper to outline my 3D objects I made in Blender, but THREE.EdgesHelper was replaced by THREE.EdgesGeometry. I wanted to see an example of this, and the only one I could find is linked above.
I dove into the line and BoxHelper objects, but I didn't notice anything that would allow me to get rid of those yellow boxes.
JSFiddle: https://jsfiddle.net/4nbjvmpe/
Here is the code from the JSFiddle:
HTML
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
CSS
body {
background-color: #000;
margin: 0px;
overflow: hidden;
}
JavaScript
var mesh, renderer, scene, camera, controls;
init();
animate();
function init() {
// renderer
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
// scene
scene = new THREE.Scene();
// camera
camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.set( 20, 20, 20 );
// controls
controls = new THREE.OrbitControls( camera );
// ambient
scene.add( new THREE.AmbientLight( 0x222222 ) );
// light
var light = new THREE.DirectionalLight( 0xffffff, 1 );
light.position.set( 20, 20, 0 );
scene.add( light );
// geometry
var geometry = new THREE.SphereGeometry( 5, 12, 8 );
// material
var material = new THREE.MeshPhongMaterial( {
color: 0x00ffff,
shading: THREE.FlatShading,
transparent: true,
opacity: 0.7,
} );
// mesh
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
// CUSTOM
// This is where I create the outline mesh.
var group = new THREE.Group();
scene.add( group );
group.updateMatrixWorld(true);
var edges = new THREE.EdgesGeometry(geometry);
var line = new THREE.LineSegments(edges);
group.add(line);
line.material.depthTest = true;
line.material.opacity = 0.25;
line.material.transparent = false;
this.outlineMesh = new THREE.BoxHelper(line);
scene.add(this.outlineMesh);
}
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
}

Simply comment this.outlineMesh = new THREE.BoxHelper(line); and scene.add(this.outlineMesh);. you will get want you want.

Related

Two material in the same place in three.js

I'm trying to put two materials in a plane, one over the other. I mean, I have a bricks background and over it I need to put another material whit other texture.
Use the following approach to apply more than a single material to a mesh. The idea is to define BufferGeometry.groups in a way such that the entire geometry (not just parts of it) is rendered with different materials.
var renderer, scene, camera;
init();
render();
function init() {
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setClearColor( 0x000000, 0.0 );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.set( 15, 20, 30 );
scene.add( camera );
var controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.addEventListener( 'change', render );
controls.minDistance = 10;
controls.maxDistance = 50;
scene.add( new THREE.AmbientLight( 0xffffff, 0.1 ) );
var light = new THREE.PointLight( 0xffffff, 1 );
camera.add( light );
var geometry = new THREE.BoxBufferGeometry( 10, 10, 10 );
geometry.clearGroups();
geometry.addGroup( 0, Infinity, 0 );
geometry.addGroup( 0, Infinity, 1 );
// textures
var loader = new THREE.TextureLoader();
var map = loader.load( 'https://threejs.org/examples/textures/decal/decal-diffuse.png', render );
var normalMap = loader.load( 'https://threejs.org/examples/textures/decal/decal-normal.jpg', render );
var material1 = new THREE.MeshPhongMaterial( {
color: 0xffffff,
specular: 0x222222,
shininess: 100,
map: map,
normalMap: normalMap,
alphaTest: 0.5,
visible: true
} );
var material2 = new THREE.MeshNormalMaterial( {
opacity: 0.5,
transparent: true,
visible: true
} );
mesh = new THREE.Mesh( geometry, [ material1, material2 ] );
scene.add( mesh );
}
function render() {
renderer.render( scene, camera );
}
body {
margin: 0px;
}
canvs {
display: block;
}
<script src="https://cdn.jsdelivr.net/npm/three#0.116.1/build/three.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three#0.116.1/examples/js/controls/OrbitControls.js"></script>

Grainy textures in a simple cube scene

I'm just starting to learn three.js and have been trying to set up a simple textured cube box in an isometric view. When I add edge lines to my cube it turns out to be quite grainy on a few of the edges.
I've tried moving the camera and aspect ratio a bit but to no avail.
var aspect = 100/100
var scene = new THREE.Scene();
var d = 100;
camera = new THREE.OrthographicCamera( - d * aspect, d * aspect, d, - d, 1, 500 );
camera.position.set( 80, 80, 80 ); // all components equal
camera.lookAt( scene.position ); // or the origin
var renderer = new THREE.WebGLRenderer( {alpha: true });
renderer.setSize( 100, 80 );
document.body.appendChild( renderer.domElement );
var geometry = new THREE.BoxGeometry( 65, 65, 65 );
var edges = new THREE.EdgesGeometry( geometry )
var line = new THREE.LineSegments( edges, new THREE.LineBasicMaterial( {color: 0x000000} ) );
var material = new THREE.MeshBasicMaterial( { color: 0xf0f0f5 } );
var cube = new THREE.Mesh( geometry, material );
scene.add( cube );
scene.add( line );
var animate = function () {
requestAnimationFrame( animate );
renderer.render( scene, camera );
};
animate();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/102/three.min.js"></script>
The above gives me a nice grey cube with black edges but the edges appear grainy in my browser.
Picture below:
This is a Z-fighting issue, which can be solved by a polgon offset .polygonOffset.
The issue is caused because the lines and the surface have to same coordinates and depth.
Set the .polygonOffset, .polygonOffsetFactor and .polygonOffsetUnits property of that THREE.Material, which is set to the solid geometry.
This causes that the surfaces are slightly pushed to the back and the lines cover the surfaces:
e.g.
var material = new THREE.MeshBasicMaterial({
color: 0xf0f0f5,
polygonOffset: true,
polygonOffsetFactor: 1.0,
polygonOffsetUnits: -4.0
} );
var aspect = 100/100
var scene = new THREE.Scene();
var d = 100;
camera = new THREE.OrthographicCamera( - d * aspect, d * aspect, d, - d, 1, 500 );
camera.position.set( 80, 80, 80 ); // all components equal
camera.lookAt( scene.position ); // or the origin
var renderer = new THREE.WebGLRenderer( {alpha: true });
renderer.setSize( 100, 80 );
document.body.appendChild( renderer.domElement );
var geometry = new THREE.BoxGeometry( 65, 65, 65 );
var edges = new THREE.EdgesGeometry( geometry )
var line = new THREE.LineSegments( edges, new THREE.LineBasicMaterial( {color: 0x000000} ) );
var material = new THREE.MeshBasicMaterial({
color: 0xf0f0f5,
polygonOffset: true,
polygonOffsetFactor: 1.0,
polygonOffsetUnits: -4.0
} );
var cube = new THREE.Mesh( geometry, material );
scene.add( line );
scene.add( cube );
var animate = function () {
requestAnimationFrame( animate );
renderer.render( scene, camera );
};
animate();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/102/three.min.js"></script>

SVGRenderer with OrbitControls shows two SVG elements on opposite sides

I create two scenes and two renderers, one is for simple 3D mesh sphere and another is for svg circle. SVG scene sits on top of Mesh scene, like an overlay. Sphere and circle are placed on the same position in 3D space. I use OrbitControls to look around. When program loads I see sphere and the circle in the same place, but when I look around I see another svg sphere on the opposite side. Why do I see two svg icons in 3D space and how to get rid of the second one? I know for sure it is one svg node, not two, but somehow orbit controls see it behind like in the mirror.
Here is demo link: http://mystic-peanut.com/mystic_sites/svgdouble/svg_sandbox.html
Here is code snippet:
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.z = -50;
scene = new THREE.Scene();
scene.background = new THREE.Color( 0xff0000 );
meshScene = new THREE.Scene();
meshScene.background = new THREE.Color( 0x000000 );
// 3d sphere mesh added to mesh scene
var sphereGeometry = new THREE.SphereGeometry( 51, 60, 40 )
var mesh = new THREE.Mesh( sphereGeometry, new THREE.MeshLambertMaterial( { color: Math.random() * 0xffffff } ) );
mesh.name = 'pointer sphere';
mesh.position.set( 0, 0, 1500 );
meshScene.add( mesh );
// svg circle added to svg scene
node = document.createElementNS( 'http://www.w3.org/2000/svg', 'circle' );
node.setAttribute( 'stroke', 'black' );
node.setAttribute( 'fill', 'blue' );
node.setAttribute( 'r', '10' );
node.style.cursor = 'pointer';
var object = new THREE.SVGObject( node );
object.position.x = 0;
object.position.y = 0;
object.position.z = 1500;
scene.add( object );
meshRenderer = new THREE.WebGLRenderer( { antialias: true } );
meshRenderer.setPixelRatio( window.devicePixelRatio );
meshRenderer.setSize(window.innerWidth, window.innerHeight);
meshRenderer.domElement.style.position = 'absolute';
meshRenderer.domElement.style.top = '0px';
threeJSCanvas.appendChild( meshRenderer.domElement );
renderer = new THREE.SVGRenderer( {alpha: true } );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setQuality( 'low' );
renderer.domElement.style.position = 'absolute';
renderer.domElement.style.top = '0px';
renderer.domElement.style.zIndex = 2;
renderer.setClearColor( 0x000000, 0);
threeJSCanvas.appendChild( renderer.domElement );
// controls
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.addEventListener( 'change', render ); // call this only in static scenes (i.e., if there is no animation loop)
controls.minDistance = 10;
controls.maxDistance = 100;
controls.maxPolarAngle = 2*Math.PI / 3;
controls.minPolarAngle = Math.PI / 3;
This issue was fixed within this ticket:
github.com/mrdoob/three.js/issues/15476

Three.js - CanvasRenderer not rendering Mesh with multiple materials

I have a problem with CanvasRenderer rendering a Mesh that has multiple materials applied to a BoxBufferGeometry. It renders a Mesh with no materials applied. This is only problem with CanvasRenderer, when I use the same Mesh with WebGLRenderer all works as expected.
Here's an example code:
// three.js: multiple materials on a single mesh
var renderer, scene, camera, mesh;
init();
render();
function init() {
// renderer
renderer = new THREE.CanvasRenderer( { alpha: true } );
renderer.setSize( window.innerWidth / 2, window.innerHeight );
document.body.appendChild( renderer.domElement );
// scene
scene = new THREE.Scene();
// camera
camera = new THREE.PerspectiveCamera( 40, (window.innerWidth / 2) / window.innerHeight, 1, 1000 );
camera.position.set( 15, 20, 30 );
camera.lookAt(scene.position);
scene.add( camera );
// ambient
scene.add( new THREE.AmbientLight( 0xffffff, 0.1 ) );
// light
camera.add( new THREE.PointLight( 0xffffff, 1 ) );
// geometry
var geometry = new THREE.BoxBufferGeometry( 10, 10, 10 );
// materials
var material0 = new THREE.MeshBasicMaterial({ color: 0xff0000 });
var material1 = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
var material2 = new THREE.MeshBasicMaterial({ color: 0x0000ff });
var material3 = new THREE.MeshBasicMaterial({ color: 0xffff00 });
var material4 = new THREE.MeshBasicMaterial({ color: 0x00ffff });
var material5 = new THREE.MeshBasicMaterial({ color: 0xff00ff });
var materials = [ material0, material1, material2, material3, material4, material5 ];
// mesh
mesh = new THREE.Mesh( geometry, materials );
scene.add( mesh );
}
function render() {
requestAnimationFrame(render);
mesh.rotation.x += 0.005;
mesh.rotation.y += 0.01;
renderer.render( scene, camera );
}
I've also made this fiddle
Where you can see exactly what I'm talking about. In the fiddle there's a Mesh(cube) that has all 6 groups(sides) in different material(color), and that same Mesh is rendered with WebGLRenderer(left) and CanvasRenderer(right).
Can someone with more experience help me understand this.
Am I doing something wrong?
Is there some limitation with CanvasRenderer that disables it to render such a Mesh, and if so, how would I achieve this effect in some other way?
Is this a bug, and should I report it as an issue on three.js repository?
Thanks for your help!
Note:
I'm new to Three.js, so I apologize if I made some obvious mistake.
CanvasRenderer is crucial for me as I use phantom.js to capture some screenshots.
Three.js r93
CanvasRenderer does not appear to support BufferGeometry and multi-materials.
A work-around is to use Geometry, instead.
var geometry = new THREE.BoxGeometry( 10, 10, 10 );
three.js r.93

Issue with custom geometry and face normal

I'm quite new to ThreeJS and I have a small issue (probably wrong usage). I'm trying to create a custom geometry and define the faces normals by myself.
I create one normal in one direction and the other one in the opposite direction, as my Mesh is not 2 sided I expect to see only one of the face, however I can see both of them... Any Idea of what I'm doing wrong ?
Thanks!
<body>
<script src="../build/Three.js"></script>
<script src="js/Stats.js"></script>
<script>
var container, stats;
var camera, scene, renderer;
container = document.createElement( 'div' );
document.body.appendChild( container );
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 );
camera.up.x = 0;
camera.up.y = 0;
camera.up.z = 1;
camera.position.x = 300;
camera.position.y = -1000;
camera.position.z = 1000;
camera.lookAt(new THREE.Vector3(300, 250, 0));
scene.add( camera );
var light, geometry, material;
scene.add( new THREE.AmbientLight( 0x404040 ) );
light = new THREE.DirectionalLight( 0xffffff );
light.position.set( 0, 1, 0 );
scene.add( light );
material = new THREE.MeshBasicMaterial( { color: 0xFFFF00, wireframe: false, transparent: false, opacity: 1 } );
geometry = new THREE.Geometry();
geometry.vertices.push(new THREE.Vector3(0,0,0));
geometry.vertices.push(new THREE.Vector3(600,0,0));
geometry.vertices.push(new THREE.Vector3(0,-500,0));
geometry.vertices.push(new THREE.Vector3(600,-500,0));
var face;
face = new THREE.Face3(0,2,1);
face.normal.set(0,0,-1);
geometry.faces.push(face);
face = new THREE.Face3(2,3,1);
face.normal.set(0,0,1);
geometry.faces.push(face);
geometry.computeCentroids();
//geometry.computeFaceNormals();
//geometry.computeTangents();
var mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
renderer.render( scene, camera );
</script>
</body>
WebGLRenderer uses the vertex order in which you created the face for defining the orientation instead of the normal. Try doing this:
face = new THREE.Face3(2,1,3);

Categories