I need to hide the edges that are displayed in a box primitive using ThreeJS. These only are drawn when I put a texture on the faces.
I've tried with many options like wireframe=false, but the edges are still drawn.
This is the code:
var container, stats;
var camera, scene, renderer;
var canvasWidth = 500;
var canvasHeight = 500;
var windowHalfX = 100;
var windowHalfY = 100;
container = document.createElement( 'div' );
document.body.appendChild( container );
// Camera
camera = new THREE.OrthographicCamera( canvasWidth / - 2, canvasWidth / 2, canvasHeight / 2, canvasHeight / - 2, - 500, 5000 );
// Scene
scene = new THREE.Scene();
camera.position.x = 200;
camera.position.y = 200;
camera.position.z = 200;
camera.lookAt( scene.position );
// Renderer
renderer = new THREE.CanvasRenderer();
renderer.setClearColor( "#fff" );
renderer.setSize( canvasWidth, canvasHeight );
container.appendChild( renderer.domElement );
var size = 100;
geometry = new THREE.BoxGeometry( size, size, size );
material = new THREE.MeshBasicMaterial({
color: "#0000ff",
side: THREE.DoubleSide,
wireframe: false
});
// Comment this line to paint a single color cube
material = new THREE.MeshLambertMaterial({ map: THREE.ImageUtils.loadTexture("http://upload.wikimedia.org/wikipedia/commons/8/81/Color_icon_black.png") });
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
var draw = function() {
requestAnimationFrame( draw );
renderer.render( scene, camera );
}
draw();
And a link to the example:
http://jsfiddle.net/gyss/qg4x9/
Cheers!
I've solved my problem changing this line
renderer = new THREE.CanvasRenderer();
for this other
renderer = new THREE.WebGLRenderer();
Other possible solution, as WestLangley commented above is to use this line with CanvasRenderer
material.overdraw = 0.5; // or some number between 0 and 1
When using renderer = new THREE.CanvasRenderer();
to remove the edges, a parameter (overdraw:true) needs to be added to the material definition like this:
var material = new THREE.MeshBasicMaterial( { map: texture, overdraw: true } );
Then you can use add the material to the 3D object:
mesh = new THREE.MeshBasicMaterial( geometry, material );
Related
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>
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
If I have a basic hollow cyclinder made using three.js like in the JSFiddle how can I change the thickness of the walls?
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 95, window.innerWidth / window.innerHeight, 0.1, 1000 );
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
var geometry = new THREE.CylinderGeometry( 2, 2, 5, 360, 1, true );
var material = new THREE.MeshNormalMaterial( { color: 0x00ff00, side: THREE.DoubleSide } );
var cube = new THREE.Mesh( geometry, material );
scene.add( cube );
camera.position.y = 5;
camera.position.z = 5;
camera.lookAt(0,0,0);
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
animate();
JSFiddle example
No, you have to subtract another cylinder from a cylinder. The one you subtract from it is the inner diameter of the cylinder.
So I changed your code to this:
var outerGeometry = new THREE.CylinderGeometry(2, 2, 5, 360, 1);
var innerGeometry = new THREE.CylinderGeometry(1.5, 1.5, 5, 360, 1);
var material = new THREE.MeshNormalMaterial({
color: 0x00ff00,
side: THREE.DoubleSide
});
var outerCylinder = new ThreeBSP(outerGeometry);
var innerCylinder = new ThreeBSP(innerGeometry);
var hollowedCylinder = innerCylinder.union(outerCylinder);
scene.add(hollowedCylinder.toMesh(material));
Here is the fiddle:
http://jsfiddle.net/gerdonabbink/tephoLr1/133/
As you can see the inner cylinder is 1.5, change this to 1 for example to make the thickness 1.
Below is my snippet, For now i want to position a single particle on the sphere. How can i combine partical and sphere geometries together ? Once this is achieved i want to render particles on top of the sphere dynamically
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 2000 );
camera.position.z = 500;
renderer = new THREE.WebGLRenderer();
renderer.setClearColor( 0x000000 );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
scene = new THREE.Scene();
loader = new THREE.TextureLoader();
loader.load( '<%= image_path('earthmap1k.jpg') %>', function ( texture ) {
geometry = new THREE.SphereGeometry( 200, 20, 20 );
material = new THREE.MeshBasicMaterial( { map: texture, overdraw: 0.5, wireframe: true } );
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
} );
function addPartical() {
var distance = 200;
ggeometry = new THREE.Geometry();
vertex = new THREE.Vector3();
theta = THREE.Math.randFloatSpread(360);
phi = THREE.Math.randFloatSpread(360);
vertex.x = distance * Math.sin(theta) * Math.cos(phi);
vertex.y = distance * Math.sin(theta) * Math.sin(phi);
vertex.z = distance * Math.cos(theta);
ggeometry.vertices.push(vertex);
particles = new THREE.Points(ggeometry, new THREE.PointsMaterial({color: 0xffffff}));
particles.boundingSphere = 50;
scene.add(particles);
};
}
function animate() {
requestAnimationFrame( animate );
addParticle();
render();
}
function render() {
renderer.render( scene, camera );
}
If you want to treat the two objects as one use a THREE.Object3D() and manipulate that.
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);