SVGRenderer with OrbitControls shows two SVG elements on opposite sides - javascript

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

Related

Orbit controls; Angle clamping

I've been working on a mini project recently for a visuals I want to develop and I'm having issues being able to limit the camera rotation based on the Y axis rotation, and I don't quite know why or how I'm having this issue.
I've looked around and all I can find is people wanting to remove the angle clamp, and they always seem to refer to minAzimuthAngle or maxAzimuthAngle, but I can't seem to get it to do anything.
// controls.minAzimuthAngle = -Math.PI, controls.maxAzimuthAngle = Math.PI
I'm just asking here as I can't find much elsewhere to explain my problem. I'm thinking it's just the specifically the way I'm using or rendering the camera but it's hard to find any reference to clamping the angles other than unclamping them.
var renderer, scene, camera; // scene render var creation
var orbitalControl = new THREE.OrbitControls(camera, renderer); //orbitcontrol setup
var controls = new THREE.OrbitControls( camera, renderer); // camera to renderer
controls.addEventListener( 'change', render ); //control listening
scene = new THREE.Scene(), camera; // scene creation
var W = window.innerWidth, H = window.innerHeight; // scene size
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.set(0, 0, 400); // camera assignment
camera.up = new THREE.Vector3(0,500,0);
controls = new THREE.OrbitControls(camera); // centeralising the camera
controls.target = new THREE.Vector3(500, 200, 500); // controls
controls.addEventListener('change', render); // renderer based on controls
scene.add(camera); // camera to scene
controls.addEventListener( 'change', render ); // control adjustments
controls.screenSpacePanning = false;
controls.enableDamping = true, controls.dampingFactor = 0.25;
controls.enableZoom = false, controls.autoRotate = false;
controls.minPolarAngle = Math.PI / 2 ; // radians
controls.maxPolarAngle = Math.PI / 2 // radians
controls.minAzimuthAngle = -Math.PI * 0.5;
controls.maxAzimuthAngle = Math.PI * 0.5;
controls.addEventListener("change", () => {
if (this.renderer) this.renderer.render(this.scene, camera)});
regardless of whatever I change the min or max AzimuthAngle, it doesn't do anything, but it's the only thing I'm referred to from any other posts.
is there something conflicting with the way I'm trying to render this?
I genuinelly have no clue what the issue is.
Thanks in advance for anyone who responds
github link to the entire project; https://github.com/Thealonic/GENESIS
I'm having issues being able to limit the camera rotation based on the Y axis rotation,
In this case, you have to configure minAzimuthAngle and maxAzimuthAngle. Keep in mind that you can only use values in the range [ - Math.PI, Math.PI ]. Check out how the following example restricts how far you can orbit horizontally.
var mesh, renderer, scene, camera, controls;
init();
animate();
function init() {
// renderer
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setPixelRatio( window.devicePixelRatio );
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, renderer.domElement );
controls.minAzimuthAngle = 0;
controls.maxAzimuthAngle = Math.PI * 0.5;
// ambient
scene.add( new THREE.AmbientLight( 0x222222 ) );
// light
var light = new THREE.DirectionalLight( 0xffffff, 1 );
light.position.set( 20,20, 0 );
scene.add( light );
// axes
scene.add( new THREE.AxesHelper( 20 ) );
// geometry
var geometry = new THREE.SphereGeometry( 5, 12, 8 );
// material
var material = new THREE.MeshPhongMaterial( {
color: 0x00ffff,
flatShading: true,
transparent: true,
opacity: 0.7,
} );
// mesh
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
}
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
body {
margin: 0;
}
canvas {
display: block;
}
<script src="https://cdn.jsdelivr.net/npm/three#0.115/build/three.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three#0.115/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>

threejs - morphTargets shrink other meshes in scene

Description of the problem
I have a simple box mesh with a morphTarget and a slider which adjusts the morphTargetInfluence. The morph affects the mesh as it should but it also shrinks any other mesh in the scene.
I've put together a jsfiddle (modified from the threejs morph target) example below to demo the issue. In this demo moving the slider correctly morphs the corner of the red cube but incorrectly shrinks the size of the blue cube. The cube meshes are entirely unrelated so I don't see how the morph could affect the blue cube.
https://jsfiddle.net/djmm7vv2/
// JS code from jsfiddle
var container, stats;
var camera, scene, renderer;
var geometry, objects;
var mesh, mesh2;
init();
animate();
function init() {
// Create cameras, lights, scene, ect.
container = document.getElementById( 'container' );
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 15000 );
camera.position.z = 500;
scene = new THREE.Scene();
scene.background = new THREE.Color( 0x222222 );
scene.fog = new THREE.Fog( 0x000000, 1, 15000 );
var light1 = new THREE.PointLight( 'white', 1);
light1.position.set( 100, 100, 100 );
var light2 = new THREE.PointLight( 'white', 1);
light2.position.set( -100, 100, 100 );
scene.add( light1 );
scene.add( light2 );
// Create first mesh (red cube)
var geometry = new THREE.BoxGeometry( 100, 100, 100 );
var material = new THREE.MeshLambertMaterial( { color: 'red', morphTargets: true } );
// Create 1 blend shape
for ( var i = 0; i < 1; i ++ ) {
var vertices = [];
for ( var v = 0; v < geometry.vertices.length; v ++ ) {
vertices.push( geometry.vertices[ v ].clone() );
if ( v === i ) {
vertices[ vertices.length - 1 ].x *= 2;
vertices[ vertices.length - 1 ].y *= 2;
vertices[ vertices.length - 1 ].z *= 2;
}
}
geometry.morphTargets.push( { name: "target" + i, vertices: vertices } );
}
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
// Add second mesh (blue cube)
var blue = new THREE.MeshLambertMaterial( { color: 'blue', morphTargets: true } );
var box2 = new THREE.BoxGeometry( 100, 100, 100 );
mesh2 = new THREE.Mesh( box2, blue );
scene.add( mesh2 );
mesh2.position.x = 150
// Create simple GUI slider to change morph influence on mesh (red cube)
var params = {
influence1: 0,
};
var gui = new dat.GUI();
var folder = gui.addFolder( 'Morph Targets' );
folder.add( params, 'influence1', 0, 1 ).step( 0.01 ).onChange( function( value ) { mesh.morphTargetInfluences[ 0 ] = value; } );
folder.open();
// Render it all
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
}
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
mesh.rotation.y += 0.01;
renderer.render( scene, camera );
}
...And here's the answer https://github.com/mrdoob/three.js/issues/12691#issuecomment-345416590. My blue mesh material had morphTargets set to true. Changing it to false corrected the issue.
var blue = new THREE.MeshLambertMaterial( { color: 'blue', morphTargets: false } );
If anyone knows why this is the case I would love to know more. The documentation on MeshLambertMaterials is sparse. Maybe this has to do with keeping material textures from freaking out when the morph is applied?

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

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.

I Need to hide edges on ThreeJS box primitive

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 );

Categories