three.js[83] points vertices update not work [duplicate] - javascript

I am using Three.js r83.
I am trying to dynamically add points to a geometry, but the scene never gets updated.
This works :
var tmaterial = new THREE.PointsMaterial({
color: 0xff0000,
size: 5,
opacity: 1
});
var tgeometry = new THREE.Geometry();
var pointCloud = new THREE.Points(tgeometry, tmaterial);
for(var i = 0; i< 1000; i++) {
x = (Math.random() * 200) - 100;
y = (Math.random() * 200) - 100;
z = (Math.random() * 200) - 100;
tgeometry.vertices.push(new THREE.Vector3(x, y, z));
}
tgeometry.verticesNeedUpdate = true;
tgeometry.computeVertexNormals();
scene.add(pointCloud);
This doesn't work:
var tmaterial = new THREE.PointsMaterial({
color: 0xff0000,
size: 5,
opacity: 1
});
var tgeometry = new THREE.Geometry();
var pointCloud = new THREE.Points(tgeometry, tmaterial);
scene.add(pointCloud);
for(var i = 0; i< 1000; i++) {
x = (Math.random() * 200) - 100;
y = (Math.random() * 200) - 100;
z = (Math.random() * 200) - 100;
tgeometry.vertices.push(new THREE.Vector3(x, y, z));
}
tgeometry.verticesNeedUpdate = true;
tgeometry.elementsNeedUpdate = true;
tgeometry.computeVertexNormals();
renderer.render(scene, camera);
As you can see, the only difference is the fact that I add scene.add(pointCloud); before adding vertexes.
What do I miss?
You can find a fiddle Thanks to #hectate
To see what I means, just replace
init();
setPoints();
animate();
by
init();
animate();
setPoints();

I am not sure why the THREE.Geometry object doesn't update Points after initial rendering, but I got it working with a THREE.BufferGeometry instead.
Thanks to #Hectate who got a working fiddle for me and #WestLangley who directed me to the hints, here is the working fiddle
BufferGeometry has a fixed number of Vertices, but you can decide how many of them you want to render. The trick is to make use of geometry.attributes.position.needsUpdate = true; and geometry.setDrawRange( 0, nbPointsYouWantToDisplay );
var MAX_POINTS = 1000000;
var geometry = new THREE.BufferGeometry();
var positions = new Float32Array( MAX_POINTS * 3 );
geometry.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
Then you can create your cloudpoints and add it to the scene:
//material and scene defined in question
pointCloud = new THREE.Points(geometry, material);
scene.add(pointCloud);
Now I want to add and render 500 new points every 10 milliseconds.
var nbPoints = 500;
var INTERVAL_DURATION = 10;
All I have to do is :
var interval = setInterval(function() {
setPoints();
}, INTERVAL_DURATION)
function setPoints() {
var positions = pointCloud.geometry.attributes.position.array;
var x, y, z, index;
var l = currentPoints + nbPoints;
if(l >= MAX_POINTS) {
clearInterval(interval);
}
for ( var i = currentPoints; i < l; i ++ ) {
x = ( Math.random() - 0.5 ) * 300;
y = ( Math.random() - 0.5 ) * 300;
z = ( Math.random() - 0.5 ) * 300;
positions[ currentPointsIndex ++ ] = x;
positions[ currentPointsIndex ++ ] = y;
positions[ currentPointsIndex ++ ] = z;
}
currentPoints = l;
pointCloud.geometry.attributes.position.needsUpdate = true;
pointCloud.geometry.setDrawRange( 0, currentPoints );
controls.update();
renderer.render(scene, camera);
}

Here's a fiddle with your first setup installed: https://jsfiddle.net/87wg5z27/236/
var scene, renderer, camera;
var cube;
var controls;
init();
animate();
function init()
{
renderer = new THREE.WebGLRenderer( {antialias:true} );
var width = window.innerWidth;
var height = window.innerHeight;
renderer.setSize (width, height);
document.body.appendChild (renderer.domElement);
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera (45, width/height, 1, 10000);
camera.position.y = 160;
camera.position.z = 400;
camera.lookAt (new THREE.Vector3(0,0,0));
controls = new THREE.OrbitControls (camera, renderer.domElement);
var tmaterial = new THREE.PointsMaterial({
color: 0xff0000,
size: 5,
opacity: 1
});
var tgeometry = new THREE.Geometry();
var pointCloud = new THREE.Points(tgeometry, tmaterial);
for(var i = 0; i< 1000; i++) {
x = (Math.random() * 200) - 100;
y = (Math.random() * 200) - 100;
z = (Math.random() * 200) - 100;
tgeometry.vertices.push(new THREE.Vector3(x, y, z));
}
tgeometry.verticesNeedUpdate = true;
tgeometry.computeVertexNormals();
scene.add(pointCloud);
window.addEventListener ('resize', onWindowResize, false);
}
function onWindowResize ()
{
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize (window.innerWidth, window.innerHeight);
}
function animate()
{
controls.update();
requestAnimationFrame ( animate );
renderer.render (scene, camera);
}
Here's one with your second: https://jsfiddle.net/87wg5z27/237/
var scene, renderer, camera;
var cube;
var controls;
init();
animate();
function init()
{
renderer = new THREE.WebGLRenderer( {antialias:true} );
var width = window.innerWidth;
var height = window.innerHeight;
renderer.setSize (width, height);
document.body.appendChild (renderer.domElement);
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera (45, width/height, 1, 10000);
camera.position.y = 160;
camera.position.z = 400;
camera.lookAt (new THREE.Vector3(0,0,0));
controls = new THREE.OrbitControls (camera, renderer.domElement);
var tmaterial = new THREE.PointsMaterial({
color: 0xff0000,
size: 5,
opacity: 1
});
var tgeometry = new THREE.Geometry();
var pointCloud = new THREE.Points(tgeometry, tmaterial);
scene.add(pointCloud);
for(var i = 0; i< 1000; i++) {
x = (Math.random() * 200) - 100;
y = (Math.random() * 200) - 100;
z = (Math.random() * 200) - 100;
tgeometry.vertices.push(new THREE.Vector3(x, y, z));
}
tgeometry.verticesNeedUpdate = true;
tgeometry.elementsNeedUpdate = true;
tgeometry.computeVertexNormals();
renderer.render(scene, camera);
window.addEventListener ('resize', onWindowResize, false);
}
function onWindowResize ()
{
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize (window.innerWidth, window.innerHeight);
}
function animate()
{
controls.update();
requestAnimationFrame ( animate );
renderer.render (scene, camera);
}
In both cases the point cloud shows for me perfectly fine (release 82). Perhaps there is something else missing where you're neglecting to render something? I notice that your first example doesn't show at what step you call render(). I hope this helps!

Related

How can I improve the performance of a three.js script?

I have a really nice js animation that i would like to use as a website background. Unfortunately it seems to be very intensive in CPU/GPU usage. The animation itself runs quite smooth, but my GPU is at 100%. other animations on the website don't run smooth at all and seem to lag.
I already looked at other Stackoverflow posts concerning boosting the performance of three.js scripts, but the ideas didn't work for me yet. For example I reduced the calls from 600 down to 200 by reducing the "city" objects in order to improve performance, but GPU is still at 100%.
I updated three.js to the latest version and so on. Nothing worked so far. I am quite new to three.js and JS so please don't be too harsh with me. Also I didn't really know which parts of the code will really boost performance, so I included the whole thing - even though it is very long. I hope the comments help to skip to the right parts.
Thanks in advance for your help!
// Three JS Template
//----------------------------------------------------------------- BASIC parameters
var renderer = new THREE.WebGLRenderer({antialias:true});
renderer.setSize( window.innerWidth, window.innerHeight );
if (window.innerWidth > 800) {
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
renderer.shadowMap.needsUpdate = true;
};
document.getElementById('animated-bg').appendChild(renderer.domElement);
window.addEventListener('resize', onWindowResize, false);
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
};
var camera = new THREE.PerspectiveCamera( 20, window.innerWidth / window.innerHeight, 1, 500 );
camera.position.set(0, 2, 14);
var scene = new THREE.Scene();
var city = new THREE.Object3D();
var smoke = new THREE.Object3D();
var town = new THREE.Object3D();
var createCarPos = true;
var uSpeed = 0.001;
//----------------------------------------------------------------- FOG background
var setcolor = 0x862834;
scene.background = new THREE.Color(setcolor);
scene.fog = new THREE.Fog(setcolor, 10, 16);
//----------------------------------------------------------------- RANDOM Function
function mathRandom(num = 8) {
var numValue = - Math.random() * num + Math.random() * num;
return numValue;
};
//----------------------------------------------------------------- CHANGE bluilding colors
var setTintNum = true;
function setTintColor() {
if (setTintNum) {
setTintNum = false;
var setColor = 0x000000;
} else {
setTintNum = true;
var setColor = 0x000000;
};
//setColor = 0x222222;
return setColor;
};
//----------------------------------------------------------------- CREATE City
function init() {
var segments = 2;
for (var i = 1; i<50; i++) {
var geometry = new THREE.CubeGeometry(1,0,0,segments,segments,segments);
var material = new THREE.MeshStandardMaterial({
color:setTintColor(),
wireframe:false,
shading: THREE.SmoothShading,
side:THREE.DoubleSide});
var wmaterial = new THREE.MeshLambertMaterial({
color:0xFFFFFF,
wireframe:true,
transparent:true,
opacity: 0.03,
side:THREE.DoubleSide});
var cube = new THREE.Mesh(geometry, material);
var wire = new THREE.Mesh(geometry, wmaterial);
var floor = new THREE.Mesh(geometry, material);
var wfloor = new THREE.Mesh(geometry, wmaterial);
cube.add(wfloor);
cube.castShadow = true;
cube.receiveShadow = true;
cube.rotationValue = 0.1+Math.abs(mathRandom(8));
floor.scale.y = 0.05;//+mathRandom(0.5);
cube.scale.y = 0.1+Math.abs(mathRandom(8));
var cubeWidth = 0.9;
cube.scale.x = cube.scale.z = cubeWidth+mathRandom(1-cubeWidth);
cube.position.x = Math.round(mathRandom());
cube.position.z = Math.round(mathRandom());
floor.position.set(cube.position.x, 0/*floor.scale.y / 2*/, cube.position.z)
town.add(floor);
town.add(cube);
};
//----------------------------------------------------------------- Particular
var gmaterial = new THREE.MeshToonMaterial({color:0xFFFF00, side:THREE.DoubleSide});
var gparticular = new THREE.CircleGeometry(0.01, 3);
var aparticular = 5;
for (var h = 1; h<300; h++) {
var particular = new THREE.Mesh(gparticular, gmaterial);
particular.position.set(mathRandom(aparticular), mathRandom(aparticular),mathRandom(aparticular));
particular.rotation.set(mathRandom(),mathRandom(),mathRandom());
smoke.add(particular);
};
var pmaterial = new THREE.MeshPhongMaterial({
color:0x000000,
side:THREE.DoubleSide,
roughness: 10,
metalness: 0.6,
opacity:0.9,
transparent:true});
var pgeometry = new THREE.PlaneGeometry(60,60);
var pelement = new THREE.Mesh(pgeometry, pmaterial);
pelement.rotation.x = -90 * Math.PI / 180;
pelement.position.y = -0.001;
pelement.receiveShadow = true;
city.add(pelement);
};
//----------------------------------------------------------------- MOUSE function
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2(), INTERSECTED;
var intersected;
function onMouseMove(event) {
event.preventDefault();
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
};
function onDocumentTouchStart( event ) {
if ( event.touches.length == 1 ) {
event.preventDefault();
mouse.x = event.touches[ 0 ].pageX - window.innerWidth / 2;
mouse.y = event.touches[ 0 ].pageY - window.innerHeight / 2;
};
};
function onDocumentTouchMove( event ) {
if ( event.touches.length == 1 ) {
event.preventDefault();
mouse.x = event.touches[ 0 ].pageX - window.innerWidth / 2;
mouse.y = event.touches[ 0 ].pageY - window.innerHeight / 2;
}
}
window.addEventListener('mousemove', onMouseMove, false);
window.addEventListener('touchstart', onDocumentTouchStart, false );
window.addEventListener('touchmove', onDocumentTouchMove, false );
//----------------------------------------------------------------- Lights
var ambientLight = new THREE.AmbientLight(0xFFFFFF, 4);
var lightFront = new THREE.SpotLight(0xFFFFFF, 20, 10);
var lightBack = new THREE.PointLight(0xFFFFFF, 0.5);
var spotLightHelper = new THREE.SpotLightHelper( lightFront );
lightFront.rotation.x = 45 * Math.PI / 180;
lightFront.rotation.z = -45 * Math.PI / 180;
lightFront.position.set(5, 5, 5);
lightFront.castShadow = true;
lightFront.shadow.mapSize.width = 6000;
lightFront.shadow.mapSize.height = lightFront.shadow.mapSize.width;
lightFront.penumbra = 0.1;
lightBack.position.set(0,6,0);
smoke.position.y = 2;
scene.add(ambientLight);
city.add(lightFront);
scene.add(lightBack);
scene.add(city);
city.add(smoke);
city.add(town);
//----------------------------------------------------------------- GRID Helper
var gridHelper = new THREE.GridHelper( 60, 120, 0xFF0000, 0x000000);
city.add( gridHelper );
//----------------------------------------------------------------- CAR world
var generateCar = function() {
}
//----------------------------------------------------------------- LINES world
var createCars = function(cScale = 2, cPos = 20, cColor = 0xFFFF00) {
var cMat = new THREE.MeshToonMaterial({color:cColor, side:THREE.DoubleSide});
var cGeo = new THREE.CubeGeometry(1, cScale/40, cScale/40);
var cElem = new THREE.Mesh(cGeo, cMat);
var cAmp = 3;
if (createCarPos) {
createCarPos = false;
cElem.position.x = -cPos;
cElem.position.z = (mathRandom(cAmp));
TweenMax.to(cElem.position, 3, {x:cPos, repeat:-1, yoyo:true, delay:mathRandom(3)});
} else {
createCarPos = true;
cElem.position.x = (mathRandom(cAmp));
cElem.position.z = -cPos;
cElem.rotation.y = 90 * Math.PI / 180;
TweenMax.to(cElem.position, 5, {z:cPos, repeat:-1, yoyo:true, delay:mathRandom(3), ease:Power1.easeInOut});
};
cElem.receiveShadow = true;
cElem.castShadow = true;
cElem.position.y = Math.abs(mathRandom(5));
city.add(cElem);
};
var generateLines = function() {
for (var i = 0; i<60; i++) {
createCars(0.1, 20);
};
};
//----------------------------------------------------------------- CAMERA position
var cameraSet = function() {
createCars(0.1, 20, 0xFFFFFF);
};
//----------------------------------------------------------------- ANIMATE
var animate = function() {
var time = Date.now() * 0.00005;
requestAnimationFrame(animate);
city.rotation.y -= ((mouse.x * 8) - camera.rotation.y) * uSpeed;
city.rotation.x -= (-(mouse.y * 2) - camera.rotation.x) * uSpeed;
if (city.rotation.x < -0.05) city.rotation.x = -0.05;
else if (city.rotation.x>1) city.rotation.x = 1;
var cityRotation = Math.sin(Date.now() / 5000) * 13;
for ( let i = 0, l = town.children.length; i < l; i ++ ) {
var object = town.children[ i ];
}
smoke.rotation.y += 0.01;
smoke.rotation.x += 0.01;
camera.lookAt(city.position);
renderer.render( scene, camera );
}
//----------------------------------------------------------------- START functions
generateLines();
init();
animate();
There are many things you could do.
For starters, you want to keep your Mesh number low to reduce drawcalls. This means that you shouldn't create one mesh for cube and one for floor. If they share the same material, just create 2 separate geometries, then merge them with BufferGeometryUtils.mergeBufferGeometries.
If you have 50 buildings with the same material, you should also merge them so they all draw at once.
MeshStandardMaterial is pretty expensive to render, so since you're not using environment reflections, you should consider Phong or Lambert materials instead, which are much less resource-intensive.
Shadows basically double your drawcalls per frame because it has to first calculate all shadow-casting geometries. If your buildings aren't going to move, set lightFront.shadow.autoUpdate = false after the first frame.
Don't create a new circular Mesh for each particle. That's 300 meshes! Instead, use THREE.Points, which has the capacity of drawing thousands of particles on a single drawcall, saving you tons of render time, as in this example.
Don't set your renderer's pixelRatio to anything above 1, if you do. That'd just kill your performance.
I don't have time to get into the car creation, but the same principle applies: try to reduce your drawcalls!

How to remove transparency here

How to i remove the clipped objects that have become transparent or prevent the object below it from being shown.
It would be better if it looks like a real world solid cubes.
This is written in javascript with three.js. HTML and CSS have no faults. Only the rendering shows issue here.
var scene, camera, renderer, cube;
var WIDTH = window.innerWidth;
var HEIGHT = window.innerHeight;
var SPEED = 0.001;
function init() {
scene = new THREE.Scene();
initLight();
drawScene();
initCamera();
initRenderer();
document.body.appendChild(renderer.domElement);
}
function initLight() {
const light = new THREE.PointLight(0xFFFFFF);
light.position.x = 50;
light.position.y = 50;
light.position.z = 130;
scene.add(light);
}
function initCamera() {
camera = new THREE.PerspectiveCamera(70, WIDTH / HEIGHT, 1, 10);
camera.position.set(1, 3, 5);
camera.lookAt(scene.position);
}
function initRenderer() {
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(WIDTH, HEIGHT);
renderer.sortObjects = false;
}
function drawScene() {
var material = new THREE.MeshLambertMaterial({ color: 0xFF6600 });
var shape = new THREE.CubeGeometry(1, 1, 1);
cube = new THREE.Group();
for (var a = -10; a <= 10; a = a + 2) {
for (var b = -10; b <= 10; b = b + 2) {
for (var c = -10; c <= 10; c = c + 2) {
var part = new THREE.Mesh(shape, material);
part.position.set(a, b, c);
cube.add(part);
}
}
}
scene.add(cube);
}
function rotateCube() {
cube.rotation.x -= SPEED;
cube.rotation.y -= SPEED;
cube.rotation.z -= SPEED;
}
function render() {
requestAnimationFrame(render);
rotateCube();
renderer.render(scene, camera);
}
init();
render();
<script src="https://threejs.org/build/three.js"></script>
I changed the PerspectiveCamera near plane closer, to 0.01 instead of 1, and added the includes to make your snippet run.
The "transparency" you're seeing are the cubes clipping against the camera near plane. By pulling the plane closer to the camera, you're making the viewport smaller in the world, so it more easily fits in between the cubes.
Another thing is backface culling.. that makes cubes invisible if they are viewed from inside. You can disable backface culling via material.side = THREE.DoubleSide, at the cost of potentially rendering twice as much geometry.
var scene, camera, renderer, cube;
var WIDTH = window.innerWidth;
var HEIGHT = window.innerHeight;
var SPEED = 0.001;
function init() {
scene = new THREE.Scene();
initLight();
drawScene();
initCamera();
initRenderer();
document.body.appendChild(renderer.domElement);
}
function initLight() {
const light = new THREE.PointLight(0xFFFFFF);
light.position.x = 50;
light.position.y = 50;
light.position.z = 130;
scene.add(light);
}
function initCamera() {
camera = new THREE.PerspectiveCamera(70, WIDTH / HEIGHT, 0.01, 10);
camera.position.set(1, 3, 5);
camera.lookAt(scene.position);
}
function initRenderer() {
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(WIDTH, HEIGHT);
renderer.sortObjects = false;
}
function drawScene() {
var material = new THREE.MeshLambertMaterial({ color: 0xFF6600, side: THREE.DoubleSide});
var shape = new THREE.CubeGeometry(1, 1, 1);
cube = new THREE.Group();
for (var a = -10; a <= 10; a = a + 2) {
for (var b = -10; b <= 10; b = b + 2) {
for (var c = -10; c <= 10; c = c + 2) {
var part = new THREE.Mesh(shape, material);
part.position.set(a, b, c);
cube.add(part);
}
}
}
scene.add(cube);
}
function rotateCube() {
cube.rotation.x -= SPEED;
cube.rotation.y -= SPEED;
cube.rotation.z -= SPEED;
}
function render() {
requestAnimationFrame(render);
rotateCube();
renderer.render(scene, camera);
}
init();
render();
<script src="https://threejs.org/build/three.js"></script>
<script src="https://cdn.rawgit.com/mrdoob/three.js/master/examples/js/controls/OrbitControls.js"></script>

three.js - object look at mouse

Ok I understand it seems I did not try hard enough but I am really new to this
and I get no errors what so ever in Dreamweaver.
I deleted my old example and this is what I have now, trying to integrate
the look at function with the OBJ loader, camera and lights.
I think I understand what is happening more or less in the code,
but it's still not working, I assume it's because there is a code for
window resize but the look at function dose not take that into account,
thus it's not working since the function assume a fixed window size,
Am I right here?
Also I am not sure I need the two commented lines in the obj loader
object.rotateX(Math.PI / 2); and object.lookAt(new THREE.Vector3(0, 0, 0));
since this is just to get the starting position?
if I put these tow lines back, it will just rotate the object into an initial pose but the object will not turn relative to mouse position.
I am really not sure what is conflicting here
I changed the code now to this:
<script>
var SCREEN_WIDTH = window.innerWidth;
var SCREEN_HEIGHT = window.innerHeight;
var camera, scene;
var canvasRenderer, webglRenderer;
var container, mesh, geometry, plane;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
init();
animate();
function init() {
container = document.createElement('div');
document.body.appendChild(container);
camera = new THREE.PerspectiveCamera(40, window.innerWidth / window.innerHeight, 1, 1500);
camera.position.x = 0;
camera.position.z = 100;
camera.position.y = 0;
camera.lookAt({
x: 0,
y: 0,
z: 0,
});
scene = new THREE.Scene();
// LIGHTS
scene.add(new THREE.AmbientLight(0x666666, 0.23));
var light;
light = new THREE.DirectionalLight(0xffc1c1, 2.20);
light.position.set(0, 100, 0);
light.position.multiplyScalar(1.2);
light.castShadow = true;
light.shadowCameraVisible = true;
light.shadowMapWidth = 512;
light.shadowMapHeight = 512;
var d = 50000;
light.shadowCameraLeft = -d;
light.shadowCameraRight = d;
light.shadowCameraTop = d;
light.shadowCameraBottom = -d;
light.shadowcameranear = 0.5;
light.shadowCameraFar = 1000;
//light.shadowcamerafov = 30;
light.shadowDarkness = 0.1;
scene.add(light);
var mtlLoader = new THREE.MTLLoader();
mtlLoader.setPath( 'model/' );
mtlLoader.load( 'rope.mtl', function( materials ) {
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials( materials );
objLoader.setPath( 'model/' );
objLoader.load( 'rope.obj', function ( object ) {
var positionX = 0;
var positionY = 0;
var positionZ = 0;
object.position.x = positionX;
object.position.y = positionY;
object.position.z = positionZ;
object.scale.x = 1;
object.scale.y = 1;
object.scale.z = 1;
//object.rotateX(Math.PI / 2);
//object.lookAt(new THREE.Vector3(0, 0, 0));
// castshow setting for object loaded by THREE.OBJLoader()
object.traverse( function ( child ) {
if ( child instanceof THREE.Mesh ) {
child.castShadow = true;
child.receiveShadow = true;
}
});
scene.add(object);
});
});
// RENDERER
//webglRenderer = new THREE.WebGLRenderer();
webglRenderer = new THREE.WebGLRenderer({
antialias: true
});
webglRenderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
webglRenderer.domElement.style.position = "relative";
webglRenderer.shadowMapEnabled = true;
webglRenderer.shadowMapSoft = true;
//webglRenderer.antialias: true;
container.appendChild(webglRenderer.domElement);
window.addEventListener('resize', onWindowResize, false);
}
window.addEventListener("mousemove", onmousemove, false);
var plane = new THREE.Plane(new THREE.Vector3(0, 0, 0), 0);
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
var intersectPoint = new THREE.Vector3();
function onmousemove(event) {
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(mouse, camera);
raycaster.ray.intersectPlane(plane, intersectPoint);
object.lookAt(intersectPoint);
}
function onWindowResize() {
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
webglRenderer.setSize(window.innerWidth, window.innerHeight);
}
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
camera.lookAt(scene.position);
webglRenderer.render(scene, camera);
}
</script>
I took your code and adapted so it doesn't require a obj and put it into this codepen. The main problem seems to be that your intersection plane was defined incorrectly. The first argument is the normal vector which needs to be of length 1. Yours is 0. Therefore there are no meaningful intersections.
var plane = new THREE.Plane(new THREE.Vector3(0, 0, 0), 0);
If you change it to
var plane = new THREE.Plane(new THREE.Vector3(0, 0, 1), 10);
the intersections are more meaningful and the object actually rotates.

three.js adding object to scene but not rendering object

I'm creating a function createCylinder(n, len, rad) that is called from function createScene(). I have checked that the vertices and faces are added and I get no errors. However, the geometry is not rendered. I suppose this has to do with the timing of returning the geometry or returning the mesh and adding it to the scene. That being said, I have tried everything I could think of and found no solution. Can someone please help me figure this out? Thanks in advance!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Cylinder</title>
</head>
<script type="text/javascript" src="three.js"></script>
<script type="text/javascript" src="OrbitControls.js"></script>
<style>
body {
/* set margin to 0 and overflow to hidden, to go fullscreen */
margin: 0;
overflow: hidden;
}
</style>
<body>
<div id="container">
</div>
<div id="msg">
</div>
<script type="text/javascript">
var camera, scene, renderer;
var cameraControls;
var clock = new THREE.Clock();
var isCappedBottom = false;
var isCappedTop = false;
function createCylinder(n, len, rad) {
var geometry = new THREE.Geometry();
var radius = rad;
var length = len;
var yUp = length / 2;
var yDown = -length / 2;
var theta = (2.0 * Math.PI) / n;
for (var i = 0; i < n ; i++) { //runs n + 2 times if we allow redundant vertices
var x = radius * Math.cos(i * theta);
var z = radius * Math.sin(i * theta);
//Top to bottom
var originUp = new THREE.Vector3(x, yUp, z);
var originDown = new THREE.Vector3(x, yDown, z);
geometry.vertices.push(originUp); //0
geometry.vertices.push(originDown); //1
console.log("Vertices " + geometry.vertices.length);
}//end of first for loop
// Draw faces
for (var j = 0; j < 2*n; j+= 2) {
var face1 = new THREE.Face3(j, j + 1, j + 2);
var face2 = new THREE.Face3(j + 1, j + 3, j + 2);
geometry.faces.push(face1);
geometry.faces.push(face2);
console.log("faces " + geometry.faces.length);
}
// return geometry;
//scene.add(geometry);
var material = new THREE.MeshLambertMaterial({color: 0xFF0000, side: THREE.DoubleSide});
var mesh = new THREE.Mesh(geometry, material);
return mesh;
scene.add(mesh);
// add subtle ambient lighting
var ambientLight = new THREE.AmbientLight(0x222222);
scene.add(ambientLight);
var light = new THREE.PointLight(0xFFFFFF, 1, 1000);
light.position.set(0, 10, 20);
scene.add(light);
var light2 = new THREE.PointLight(0xFFFFFF, 1, 1000);
light2.position.set(0, -10, -10);
scene.add(light2);
} //End of function
function createScene() {
var cyl = createCylinder(10, 10, 2);
return cyl;
scene.add(cyl);
}
function animate() {
window.requestAnimationFrame(animate);
render();
}
function render() {
var delta = clock.getDelta();
cameraControls.update(delta);
renderer.render(scene, camera);
}
function init() {
var canvasWidth = window.innerWidth;
var canvasHeight = window.innerHeight;
var canvasRatio = canvasWidth / canvasHeight;
scene = new THREE.Scene();
renderer = new THREE.WebGLRenderer({antialias: true, preserveDrawingBuffer: true});
renderer.gammaInput = true;
renderer.gammaOutput = true;
renderer.setSize(canvasWidth, canvasHeight);
renderer.setClearColor(0x000000, 1.0);
renderer.shadowMapEnabled = true;
camera = new THREE.PerspectiveCamera( 40, canvasRatio, 1, 1000);
/* camera.position.z = 5;
camera.lookAt(scene.position); */
camera.position.set(0, 0, 12);
camera.lookAt(new THREE.Vector3(0, 0, 0));
cameraControls = new THREE.OrbitControls(camera, renderer.domElement);
}
function addToDOM() {
var container = document.getElementById('container');
var canvas = container.getElementsByTagName('canvas');
if (canvas.length>0) {
container.removeChild(canvas[0]);
}
container.appendChild( renderer.domElement );
}
init();
createScene();
addToDOM();
render();
animate();
</script>
</body>
</html>
In the createCylinder function:
var mesh = new THREE.Mesh(geometry, material);
return mesh; // this line must be the last line in the function
// after return(), the rest of the code is unreacheable
//scene.add(mesh); // this line should be deleted as you add the mesh in the createScene() function
and then the createScene function should be like this:
function createScene() {
var cyl = createCylinder(10, 10, 2);
//return cyl;
scene.add(cyl);
}
jsfiddle example

THREE.js dynamically add points to a Points geometry does not render

I am using Three.js r83.
I am trying to dynamically add points to a geometry, but the scene never gets updated.
This works :
var tmaterial = new THREE.PointsMaterial({
color: 0xff0000,
size: 5,
opacity: 1
});
var tgeometry = new THREE.Geometry();
var pointCloud = new THREE.Points(tgeometry, tmaterial);
for(var i = 0; i< 1000; i++) {
x = (Math.random() * 200) - 100;
y = (Math.random() * 200) - 100;
z = (Math.random() * 200) - 100;
tgeometry.vertices.push(new THREE.Vector3(x, y, z));
}
tgeometry.verticesNeedUpdate = true;
tgeometry.computeVertexNormals();
scene.add(pointCloud);
This doesn't work:
var tmaterial = new THREE.PointsMaterial({
color: 0xff0000,
size: 5,
opacity: 1
});
var tgeometry = new THREE.Geometry();
var pointCloud = new THREE.Points(tgeometry, tmaterial);
scene.add(pointCloud);
for(var i = 0; i< 1000; i++) {
x = (Math.random() * 200) - 100;
y = (Math.random() * 200) - 100;
z = (Math.random() * 200) - 100;
tgeometry.vertices.push(new THREE.Vector3(x, y, z));
}
tgeometry.verticesNeedUpdate = true;
tgeometry.elementsNeedUpdate = true;
tgeometry.computeVertexNormals();
renderer.render(scene, camera);
As you can see, the only difference is the fact that I add scene.add(pointCloud); before adding vertexes.
What do I miss?
You can find a fiddle Thanks to #hectate
To see what I means, just replace
init();
setPoints();
animate();
by
init();
animate();
setPoints();
I am not sure why the THREE.Geometry object doesn't update Points after initial rendering, but I got it working with a THREE.BufferGeometry instead.
Thanks to #Hectate who got a working fiddle for me and #WestLangley who directed me to the hints, here is the working fiddle
BufferGeometry has a fixed number of Vertices, but you can decide how many of them you want to render. The trick is to make use of geometry.attributes.position.needsUpdate = true; and geometry.setDrawRange( 0, nbPointsYouWantToDisplay );
var MAX_POINTS = 1000000;
var geometry = new THREE.BufferGeometry();
var positions = new Float32Array( MAX_POINTS * 3 );
geometry.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
Then you can create your cloudpoints and add it to the scene:
//material and scene defined in question
pointCloud = new THREE.Points(geometry, material);
scene.add(pointCloud);
Now I want to add and render 500 new points every 10 milliseconds.
var nbPoints = 500;
var INTERVAL_DURATION = 10;
All I have to do is :
var interval = setInterval(function() {
setPoints();
}, INTERVAL_DURATION)
function setPoints() {
var positions = pointCloud.geometry.attributes.position.array;
var x, y, z, index;
var l = currentPoints + nbPoints;
if(l >= MAX_POINTS) {
clearInterval(interval);
}
for ( var i = currentPoints; i < l; i ++ ) {
x = ( Math.random() - 0.5 ) * 300;
y = ( Math.random() - 0.5 ) * 300;
z = ( Math.random() - 0.5 ) * 300;
positions[ currentPointsIndex ++ ] = x;
positions[ currentPointsIndex ++ ] = y;
positions[ currentPointsIndex ++ ] = z;
}
currentPoints = l;
pointCloud.geometry.attributes.position.needsUpdate = true;
pointCloud.geometry.setDrawRange( 0, currentPoints );
controls.update();
renderer.render(scene, camera);
}
Here's a fiddle with your first setup installed: https://jsfiddle.net/87wg5z27/236/
var scene, renderer, camera;
var cube;
var controls;
init();
animate();
function init()
{
renderer = new THREE.WebGLRenderer( {antialias:true} );
var width = window.innerWidth;
var height = window.innerHeight;
renderer.setSize (width, height);
document.body.appendChild (renderer.domElement);
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera (45, width/height, 1, 10000);
camera.position.y = 160;
camera.position.z = 400;
camera.lookAt (new THREE.Vector3(0,0,0));
controls = new THREE.OrbitControls (camera, renderer.domElement);
var tmaterial = new THREE.PointsMaterial({
color: 0xff0000,
size: 5,
opacity: 1
});
var tgeometry = new THREE.Geometry();
var pointCloud = new THREE.Points(tgeometry, tmaterial);
for(var i = 0; i< 1000; i++) {
x = (Math.random() * 200) - 100;
y = (Math.random() * 200) - 100;
z = (Math.random() * 200) - 100;
tgeometry.vertices.push(new THREE.Vector3(x, y, z));
}
tgeometry.verticesNeedUpdate = true;
tgeometry.computeVertexNormals();
scene.add(pointCloud);
window.addEventListener ('resize', onWindowResize, false);
}
function onWindowResize ()
{
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize (window.innerWidth, window.innerHeight);
}
function animate()
{
controls.update();
requestAnimationFrame ( animate );
renderer.render (scene, camera);
}
Here's one with your second: https://jsfiddle.net/87wg5z27/237/
var scene, renderer, camera;
var cube;
var controls;
init();
animate();
function init()
{
renderer = new THREE.WebGLRenderer( {antialias:true} );
var width = window.innerWidth;
var height = window.innerHeight;
renderer.setSize (width, height);
document.body.appendChild (renderer.domElement);
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera (45, width/height, 1, 10000);
camera.position.y = 160;
camera.position.z = 400;
camera.lookAt (new THREE.Vector3(0,0,0));
controls = new THREE.OrbitControls (camera, renderer.domElement);
var tmaterial = new THREE.PointsMaterial({
color: 0xff0000,
size: 5,
opacity: 1
});
var tgeometry = new THREE.Geometry();
var pointCloud = new THREE.Points(tgeometry, tmaterial);
scene.add(pointCloud);
for(var i = 0; i< 1000; i++) {
x = (Math.random() * 200) - 100;
y = (Math.random() * 200) - 100;
z = (Math.random() * 200) - 100;
tgeometry.vertices.push(new THREE.Vector3(x, y, z));
}
tgeometry.verticesNeedUpdate = true;
tgeometry.elementsNeedUpdate = true;
tgeometry.computeVertexNormals();
renderer.render(scene, camera);
window.addEventListener ('resize', onWindowResize, false);
}
function onWindowResize ()
{
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize (window.innerWidth, window.innerHeight);
}
function animate()
{
controls.update();
requestAnimationFrame ( animate );
renderer.render (scene, camera);
}
In both cases the point cloud shows for me perfectly fine (release 82). Perhaps there is something else missing where you're neglecting to render something? I notice that your first example doesn't show at what step you call render(). I hope this helps!

Categories

Resources