Three.js 3D Scene, Uncaught Type Error: "Cannot read property 'x' of undefined" Vertex/Particle Position - three.js

I'm attempting to create a randomly distributed particle field that exhibits Brownian (random) motion.
Scroll to the bottom of the code to see where the error happens. I'm trying to set the position of a single vertex with position.x.
I'll omit the rest of the code not directly related to rendering the particles in effort to save your time.
//Using WebGL renderer...
var particle, particles = [], particle_system, material, p_x, p_y, p_z;
particles = new THREE.Geometry();
material = new THREE.ParticleBasicMaterial({color: 0xffffff, size: 1});
for(var count = 0; count < 1000; count++){
p_x = Math.random() * 1000 - 500;
p_y = Math.random() * 1000 - 500;
p_z = Math.random() * 1000 - 500;
particle = new THREE.Vector3(p_x, p_y, p_z);
particles.vertices.push(particle);
}
particle_system = new THREE.ParticleSystem(particles, material);
scene.add(particle_system);
particle_system.geometry.dynamic = true;
//All of the code bellow will go into the render loop.
var index = 0;
while(index < 1000){
index++;
particle_system.geometry.verticiesNeedUpdate = true;
//THESE 3 LINES BELLOW CAUSE THE ERROR
particles.vertices[index].position.x += Math.random() * 1000 - 500;
particles.vertices[index].position.y += Math.random() * 1000 - 500;
particles.vertices[index].position.z += Math.random() * 1000 - 500;
}

verticiesNeedUpdate should be spelled verticesNeedUpdate
your while loop is wrongly incrementing the index variable before it is used. So in the last iteration (when index == 999) you try to access particles.vertices[1000] which is not defined

Related

Three.js: PointLight change distance

I have made a scene with three.js in which I make use of a PointLight.
var distance = 10000;
var intensity = 10;
var decay = 0;
var hex = 0xFFFFFF;
var light1 = new THREE.PointLight(hex, intensity, distance, decay);
I want to use shadows, so I added
light1.shadow.camera.near = 200;
light1.shadow.camera.far = 10000;
light1.shadow.camera.fov = 90;
light1.shadow.bias = -0.00022;
light1.shadow.mapSize.width = 1024;
light1.shadow.mapSize.height = 1024;
Until here everything worked perfect. However, as soon as I include in the next line:
light1.castShadow = true;
Then the distance visibly changes from 10000 to 1000.
If I call the distance from light1 to the console, it is still 10000. Even though it is not like that in the canvas.
(I have changed it to a ~50-digit number with no change in distance)
Any suggestions on how to solve this?
You can try to create a shadow via THREE.Texture(), in this way the shadow will be an independent element and shouldn't influence the position of the PointLight.
var shadowTexture = new THREE.Texture(canvas);
shadowTexture.needsUpdate = true;
var shadowMaterial = new THREE.MeshBasicMaterial({map: shadowTexture, opacity: 0.5});
var shadowGeo = new THREE.PlaneBufferGeometry(100, 100, 100, 1);
// Locate the position of the shadows
mesh = new THREE.Mesh(shadowGeo, shadowMaterial);
mesh.position.y = 0;
mesh.rotation.x = - Math.PI / 2;
scene.add( mesh );
I am applying the shadow to a PlaneGeometry since I assume that the shadow is casted on the scene. In any case, give also a look at this example concerning shadows in a scene.

How fill a sphere with random particles in three.js

I read the excelent question about random populate the surface of a sphere with particles: How to make a sphere made out of random particles in three.js. How can I populate the total volume of an sphere with random generated particles? I try it:
var particleCount = 1800,
particles = new THREE.Geometry(),
pMaterial = new THREE.PointCloudMaterial({
color: 0xFFFFFF,
size: 20,
map: THREE.ImageUtils.loadTexture(
"images/particle.png"
),
blending: THREE.AdditiveBlending,
transparent: true
});
for (var t = 0; t < particleCount; t++) {
var angle3 = Math.random() * Math.PI * 2;
var radius3 = Math.random() * 350 + 1;
var pX1 = Math.cos(angle3) * radius3,
pY1 = Math.random() * 70 - 35,
pZ1 = Math.sin(angle3) * radius3,
skparticle11 = new THREE.Vector3(pX1, pY1, pZ1);
particles.vertices.push(skparticle11);
}
var particleSystem = new THREE.PointCloud(
particles,
pMaterial);
// add it to the scene
scene.add(particleSystem);
But I'm only get an disk. How to make an sphere filled with particles?
one angle is not enough, that is why you get a disk
create a random normal vector
var randomDirection = new THREE.Vector3(Math.random()-0.5,Math.random()-0.5,Math.random()-0.5).normalize();
create random distance as you did before
var radius3 = Math.random() * 350 + 1;
a random point in a sphere around origin will be
var randomParticle = randomDirection.multiplyScalar(radius3);
for a better distribution use some better generator than Math.random

Three.js issue at edges of tiled texture using MeshFaceMaterial

I am trying to tile the texture from multiple images onto a plane geometry using MeshFaceMaterial. Every thing works fine, except for a blurry edge forming in between tiles.
.
var textureArray = [];
var tileColumns = 2;
var tileRows = 1;
textureArray[0] = THREE.ImageUtils.loadTexture('./test3.jpg');
textureArray[1] = THREE.ImageUtils.loadTexture('./test4.jpg');
var faceCountPerTileX = 2 * widthSegments/tileColumns;
var faceCountPerTileY = heightSegments/tileRows;
var faceCountX = 2 * widthSegments;
var faceCountY = heightSegments;
for(var tileIndexY = 0; tileIndexY < tileRows; tileIndexY++){
for(var tileIndexX = 0; tileIndexX < tileColumns; tileIndexX++){
var index = tileIndexY * tileColumns + tileIndexX;
textureArray[index].wrapS = THREE.RepeatWrapping;
textureArray[index].wrapT = THREE.RepeatWrapping;
textureArray[index].repeat.set(tileColumns,tileRows);
materialContainer[tileIndexY * tileColumns + tileIndexX] = new THREE.MeshBasicMaterial({
map: textureArray[tileIndexY * tileColumns + tileIndexX],
overdraw: true,
ambient: 0xffffff
});
for(var faceIndexY = tileIndexY * faceCountPerTileY; faceIndexY < (tileIndexY+1) * faceCountPerTileY; faceIndexY++){
for(var faceIndexX = tileIndexX * faceCountPerTileX; faceIndexX < (tileIndexX+1) * faceCountPerTileX; faceIndexX++){
g.faces[faceIndexY * faceCountX + faceIndexX].materialIndex = tileIndexY * tileColumns + tileIndexX;
}
}
}
}
var mat = new THREE.MeshFaceMaterial(materialContainer);
var obj = new THREE.Mesh(g, mat);
I have tried all known solutions, i have even tried writing a custom shader and using ShaderMaterial. But no luck, can some help me out to fix the issue?
By the looks of it, you set the texture mode of the invidual textures in your set to repeat.
This seems wrong, the individual textures do not repeat, they are displayed only once. Setting a texture to repeat causes the right side of the texture to "blend through" on the left (and vice versa), causing visible seams like the one on your screenshot.

Change the opacity of a Particle object in Three.js (NOT ParticleSystem)?

I am using the CanvasRendererand Particlein Three.JS. I am generating some random particles using this approach:
texture = THREE.ImageUtils.loadTexture("img.png");
material = new THREE.ParticleBasicMaterial({
map : texture,
transparent : true,
});
for (var i = 0; i < pointCount; i++) {
var particle = new THREE.Particle(material);
particle.position.x = Math.random() * (max - min) + min;
particle.position.y = Math.random() * (max - min) + min;
particle.position.z = Math.random() * (max - min) + min;
// Set the size of the particle
particle.scale.x = particle.scale.y = particle.scale.z = Math.floor(Math.random() * 6) + 2;
particles.push(particle);
scatterPlot.add(particle);
}
I would like to (if possible) be able to change the opacity of individual Particles, as I am using transparency as a dimension in my plot (i.e., transparency of a particle reflects the magnitude of a variable). I know I can use particle.material.opacity, but that changes the opacity for all particles. I tried particles[i].material.opacitybut got the same result.
One possibility of course would be to have an array of materials with different opacities. But I'm not sure if there's perhaps a simpler way to do this?
Many thanks!
I think I might have figured this out -- and was simpler than I was thinking. It at least seems to be working for me. I moved the material declaration into the for loop. I think this generates a different ParticleBasicMaterial for each Particle, but I suppose that is okay.
I am then able to access the individual Particle'smaterial by using particles[i].material, which allows me to change the opacity of specific particles.
Here is my updated code:
texture = THREE.ImageUtils.loadTexture("img.png");
for (var i = 0; i < pointCount; i++) {
material = new THREE.ParticleBasicMaterial({
map : texture,
transparent : true,
});
var particle = new THREE.Particle(material);
particle.position.x = Math.random() * (max - min) + min;
particle.position.y = Math.random() * (max - min) + min;
particle.position.z = Math.random() * (max - min) + min;
// Set the size of the particle
particle.scale.x = particle.scale.y = particle.scale.z = Math.floor(Math.random() * 6) + 2;
particles.push(particle);
scatterPlot.add(particle);
}
// Example opacity change
particles[0].material.opacity = 0.5;
If anyone has any other suggestions, I'd greatly appreciate them. But at least this seems to be giving me the desired behavior for now.

Setting color of mapped image for ThreeJS particles

Originally I was using ParticleSystem, but I discovered that Raycaster does not work with it. So I'm now modifying my code to simply use individual Particle objects.
The problem is, I can't seem to set the color of the image I'm mapping to the particles like I was able to with ParticleSystem.
I tried the following:
texture = THREE.ImageUtils.loadTexture("ball.png");
material = new THREE.ParticleBasicMaterial({
size : 10,
color: 0x00C1BF,
map : texture,
transparent : true,
});
// Generate some random points...
for (var i = 0; i < pointCount; i++) {
var particle = new THREE.Particle(material);
particle.position.x = Math.random() * (max - min) + min;
particle.position.y = Math.random() * (max - min) + min;
particle.position.z = Math.random() * (max - min) + min;
particle.scale.x = particle.scale.y = particle.scale.z = 3;
plot.add(particle);
}
But the color of ball.png remains the same. If I comment out the image I'm mapping to the points, the colors are changing. But it's not working with the mapped image. When I was using ParticleSystem, inside the for loop where I generate the points, I was adding this:
colors[i] = new THREE.Color(0xffffff);
colors[i].setHSL((x + 1000 ) / 2000, 1, 0.5);
And then set particleSys.colors = colors; outside the loop. That changed the color of the points, but this doesn't seem to work with Particle.
I hate to keep bugging the community with questions like this, but I really would appreciate any guidance on this. Many thanks, as always! :)
Also, here's a link to ball.png that I'm using: http://threejsdoc.appspot.com/doc/three.js/examples/textures/sprites/ball.png

Resources