threeJS .lookAt looking the wrong way, inherited rotations - javascript

I am just trying to get this._mesh.skeleton.bones[ 5 ](location: the bend in the green thing coming from the hand) to point the same way as the helper yellow line
_FindBubble() {
const handPosition2world = new THREE.Vector3();
this._anchor['LeftHandIndex1'].getWorldPosition(handPosition2world);
const dir = handPosition2world;
// helper yellow line
const material = new THREE.LineBasicMaterial({ color: 0xffff00 });
const points = [];
points.push( new THREE.Vector3( handPosition2world.x, handPosition2world.y, handPosition2world.z ) );
points.push( new THREE.Vector3( this._bubble._components.BubbleModelController.averageOfVertices.x, this._bubble._components.BubbleModelController.averageOfVertices.y, this._bubble._components.BubbleModelController.averageOfVertices.z ) );
const geometry = new THREE.BufferGeometry().setFromPoints( points );
const line = new THREE.Line( geometry, material );
this._scene.add( line );
dir.sub(this._bubble._components.BubbleModelController.averageOfVertices);
dir.normalize();
return dir.negate();
}
_Updateanimation(timeInSeconds) {
const dirToBubble = this._FindBubble();
var dirToBubbleObj = new THREE.Object3D();
dirToBubbleObj.lookAt(dirToBubble);
this._mesh.skeleton.bones[ 5 ].quaternion.set(dirToBubbleObj.quaternion);
}
photo with this._mesh.skeleton.bones[ 5 ].quaternion.slerp(dirToBubbleObj.quaternion, 1) instead of set, .set(dirToBubbleObj.quaternion) does not render any of the green tube from the hand after bone 5
changing _Updatedateanimation to
_Updateanimation(timeInSeconds) {
const dirToBubble = this._FindBubble();
this._mesh.skeleton.bones[ 5 ].lookAt(dirToBubble);
}
has given me this, which sort of feels like progress, i dont know why its different i thought i would do the same as the code above but it was just written cleaner

add a bone of minimal length in place of 0 between the hand and the tube in the code below and make 1 -> 0 so there is not a funky bend at the start, i will update later when i get around to it but below gives the effect i was going for
_Updateanimation(timeInSeconds) {
this._mesh.skeleton.bones[ 0 ].lookAt(this._bubble._components.BubbleModelController.averageOfVertices);
this._mesh.skeleton.bones[ 1 ].rotation.x = Math.PI/2;
}

Related

Create a curved grid for threejs

I want to create a grid of, let's say 500x500, and I want it to be able to be curved in certain places (think of it as space-time plane that's curved due to gravity). I'm stuck at the start.
This is what I found on the documentation:
// Create a sine-like wave
const curve = new THREE.SplineCurve( [
new THREE.Vector2( -10, 0 ),
new THREE.Vector2( -5, 5 ),
new THREE.Vector2( 0, 0 ),
new THREE.Vector2( 5, -5 ),
new THREE.Vector2( 10, 0 )
] );
const points = curve.getPoints( 50 );
const geometry = new THREE.BufferGeometry().setFromPoints( points );
const material = new THREE.LineBasicMaterial( { color : 0xff0000 } );
// Create the final object to add to the scene
const splineObject = new THREE.Line( geometry, material );
I think this should be working but it doesn't. I don't know how to create a multiple lines from here. I tried to handle some array but I didn't know where or how. I have done my research but I can't make any headway.
I have another question: Is that this is a Vector2 I need to make it 3d for that work? There a lot of other classes like CatmullRomCurve3, CubicBezierCurve3, etc, but the problem still is that i need to make an array to create all the vectors and lines.
--
EDIT i created a code for the grid lines but the curve probleme still the same
let size = 12, step = 1;
const geometry = new THREE.BufferGeometry();
// create a simple square shape. We duplicate the top left and bottom right
// vertices because each vertex needs to appear once per triangle.
const vertices = [];
for(var i = - size; i <= size; i += step) {
vertices.push( - size, - 0.4, i);
vertices.push( size, - 0.4, i);
vertices.push( i, - 0.4, - size);
vertices.push( i, - 0.4, size);
}
let positionAttribute = new THREE.Float32BufferAttribute(vertices, 3);
geometry.setAttribute("position", positionAttribute);
let lines = new THREE.LineSegments(geometry, new THREE.LineBasicMaterial());

Align BoxGeometry between two 3D Points

I make a game where you can add objects to a world without using a grid. Now I want to make a footpath. When you click on "Create footpath", then you can add a point to on the world at the raycaster position. After you add a first point you can add a second point to the world. When these 2 objects where placed. A line/footpath is visible from the first point to the second one.
I can do this really simple with THREE.Line. See the code:
var lineGeometry = new THREE.Geometry();
lineGeometry.vertices.push( new THREE.Vector3(x1,0,z1), new THREE.Vector3(x2,0,z2) );
lineGeometry.computeLineDistances();
var lineMaterial = new THREE.LineBasicMaterial( { color: 0xFF0000 } );
var line = new THREE.Line( lineGeometry, lineMaterial );
scene.add(line);
But I can't add a texture on a simple line. Now I want to do something the same with a Mesh. I have the position of the first point and the raycaster position of the second point. I also have the lenght between the two objects for the lenght of the footpath. But I don't know how I can get the rotation what is needed.
Note. I saw something about LookAt, is this maybe a good idea, how can I use this with a mesh?
Can anyone help me to get the correct rotation for the footpath object?
I use this code for the foodpath mesh:
var loader = new THREE.TextureLoader();
loader.load('images/floor.jpg', function ( texture ) {
var geometry = new THREE.BoxGeometry(10, 0, 2);
var material = new THREE.MeshBasicMaterial({ map: texture, overdraw: 0.5 });
var footpath = new THREE.Mesh(geometry, material);
footpath.position.copy(point2);
var direction = // What can I do here?
footpath.rotation.y = direction;
scene.add(footpath);
});
I want to get the correct rotation for direction.
[UPDATE]
The code of WestLangley helps a lot. But it works not in all directions. I used this code for the lenght:
var lenght = footpaths[i].position.z - point2.position.z;
What can I do that the lenght works in all directions?
You want to align a box between two 3D points. You can do that like so:
var geometry = new THREE.BoxGeometry( width, height, length ); // align length with z-axis
geometry.translate( 0, 0, length / 2 ); // so one end is at the origin
...
var footpath = new THREE.Mesh( geometry, material );
footpath.position.copy( point1 );
footpath.lookAt( point2 );
three.js r.84

Merging meshes that have different colors

Using Three.js r75
I am trying to display cubes that change color depending on an integer value from green to red. I have tried multiple ways as I am stuck on this. I was unable to make cubeMat.material.color.setRGB work and creating a new Three.Color doesn't seem to work either. Please note I merge all the geometries at the end for one draw call. I am hoping this isn't the issue.
[UPDATE]
I am confirming the rgb values are set correctly with getStyle however they do not render correctly. All cube stacks should be different colors.
function colorData(percentage){
var rgbString = "",
r = parseInt(percentage * 25.5),
g = parseInt(((percentage * 25.5) - 255) * -1),
b = 0;
rgbString = "rgb("+r+","+g+",0)";
return rgbString;
}
...
var position = latLongToSphere(objectCoord[1], objectCoord[0], 300),
rgb = colorData(objectMag),
cubeColor = new THREE.Color(rgb),
cubeMat = new THREE.MeshBasicMaterial({color: cubeColor}),
cubeHeight = objectMag * 175,
cubeGeom = new THREE.BoxGeometry(3,3,cubeHeight,1,1,1),
cube = new THREE.Mesh(cubeGeom, cubeMat);
// set position of cube on globe, point to center, merge together for one draw call
cube.geometry.colorsNeedUpdate = true;
cube.position.set(position.x, position.y, position.z);
cube.lookAt(lookCenter);
cube.updateMatrix();
console.log(cube.material.color.getStyle());
geom.merge(cube.geometry, cube.matrix);
You are merging geometries so you can render with a single draw call and a single material, but you want each of the merged geometries to have a different color.
You can achieve that by defining vertexColors (or faceColor) in your geometry. Here is a pattern to follow:
// geometry
var geometry = new THREE.Geometry();
for ( var count = 0; count < 10; count ++ ) {
var geo = new THREE.BoxGeometry( 5, 5, 5 );
geo.translate( THREE.Math.randFloat( - 5, 5 ), THREE.Math.randFloat( - 5, 5 ), THREE.Math.randFloat( - 5, 5 ) );
var color = new THREE.Color().setHSL( Math.random(), 0.5, 0.5 );
for ( var i = 0; i < geo.faces.length; i ++ ) {
var face = geo.faces[ i ];
face.vertexColors.push( color, color, color ); // all the same in this case
//face.color.set( color ); // this works, too; use one or the other
}
geometry.merge( geo );
}
Then, when you specify the material for the merged geometry, set vertexColors like so:
// material
var material = new THREE.MeshPhongMaterial( {
color: 0xffffff,
vertexColors: THREE.VertexColors // or THREE.FaceColors, if defined
} );
Your geometry will be rendered with a single draw call. You can verify that by typing renderer.info into the console. renderer.info.render.calls should be 1.
three.js r.75
cubeMat.material.color.setRGB won't work because it's like you're calling the material twice (cubeMat and material), try this instead:
cube.material.color.setRGB( value, value, value );
Turns out if you merge the geometry the materials cant have different colors.
I had to set the face color of each cube before merging.
See
Changing material color on a merged mesh with three js
Three js materials of different colors are showing up as one color

Calculating individual spheres position to create a sphere made of spheres

I'm trying to re-create an atom with THREE.js, and I'm running into my first issue - since every type of atom has a different amount of Protons/Neutrons, I'm trying to find a way to position them automatically so that there is no collisions, and so the final result of them all together will make something as close to a sphere as possible - see this image for an example
(source: alternativephysics.org)
.
Is there a way to calculate this and assign each Neutron/Protons position easily with a formula? Or will I have to get a physics engine involved to just squeeze the spheres together and hope for the best result with each run?
I don't have any code on this yet, since I'm just trying to figure out where to start with this part.
EDIT
I should also note, that I want the spheres to be squished together within the space of the larger sphere. I am NOT trying to just make all the spheres go on the radius of the larger sphere.
EDIT 2
I looked into using a physics engine to squish them all into a small area, but I can't find an engine that will allow me to move all of the objects in my scene to position (0,0,0) with a gravitational force. All of the engines just make gravity push down on an object. I'd still rather use a formula for positioning the spheres, rather than include an entire physics engine into my project.
EDIT 3, 04/06/06
I've done a bit of experimenting, but I still can't get it right. Here's what it looks like now:
But as you can see, looks really off. This is what happens when I make a Uranium atom instead of a Carbon one (more protons/neutrons/electrons)
It might just be me, but that's looking more like some fancy ratatouille than a Uranium atom.
How I got here:
I was attempting to make what I was looking for up above, and here's the premise:
(particleObject is the parent of particle, the particle will move relative to this object)
I added all protons and neutrons lengths together, so that I could
loop through them all.
If the added number % 2 == 0, (which it is for my testing) I would set the rotate to (pi * 2) / 2 <- last two being there to represent the two above.
Every iteration I would increment l variable. (hopefully) whenever i would equal the loopcount variable, it would mean that I've placed sphere's around in a sphere shape. I'd then multiply loopcount by 3 to find out how many sphere's would be needed for the next run. I'd set l to 0 so that the sphere's positioning would be reset, and the loop would be incremented, causing the next row of sphere's to be placed 1 unit out on the x axis.
(Sorry for the terminology here, it's very hard to explain. See code.)
var PNamount = atomTypes[type].protons + atomTypes[type].neutrons;
var loopcount = 1;
if(PNamount % 2 == 0) {
var rotate = (PI * 2) / 2;
loopcount = 2;
}
var neutrons = 0,
protons = 0,
loop = 1,
l = 0;
for(var i = 0; i < PNamount; i++) {
if(i == loopcount){
loopcount = loopcount * 3;
loop++;
rotate = (PI * 2) / loopcount;
l = 0;
} else {
l++;
}
particleObject.rotation.x = rotate * l;
particleObject.rotation.y = rotate * l;
particleObject.rotation.z = rotate * l;
particle.position.x = loop;
}
Honestly, I'm not that great at all with 3D math. So any help would be really helpful. Plus, it's very possible that my method of positioning them is absolutely wrong in every way. Thanks!
You can see the code live here.
I would definitely say that this is a perfect use case of a physics engine. Making this simulation without a physics engine sounds like a real hassle, so "including an entire physics engine" doesn't seam like such a big cost to me. Most of the JavaScript physics engines that i've found are leight weight anyway. It will however demand some extra CPU power for the physics calculations!
I sat down and tried to create something similar to what you describe with the physics engine CANNON.js. It was quite easy to get a basic simulation working, but to get the parameters just right took is what seems a bit tricky, and will need more adjusting.
You mentioned that you tried this already but couldn't get the particles to gravitate towards a point, with CANNON.js (and probably most other physic engines) this can be achieved be applying a force to the object in the negative position direction:
function pullOrigin(body){
body.force.set(
-body.position.x,
-body.position.y,
-body.position.z
);
}
It is also easy to achieve behaviours where bodies are pulled towards a certain parent object, which in its turn is pull towards the average position of all other parent objects. This way you can create whole molecules.
One tricky thing was to let the electrons circulate the protons and neutrons at a distance. To achieve this I give them a slight force towards the origin, and then a slight force away from all the protons and neutrons at the same time. On top of that I also give them a small push sideways in the beginning of the simulation so that they start circulating the center.
Please let me know if you want me to clarify any particular part.
let scene = new THREE.Scene();
let world = new CANNON.World();
world.broadphase = new CANNON.NaiveBroadphase();
world.solver.iterations = 5;
let camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
let renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
function Proton(){
let radius = 1;
return {
// Cannon
body: new CANNON.Body({
mass: 1, // kg
position: randomPosition(6),
shape: new CANNON.Sphere(radius)
}),
// THREE
mesh: new THREE.Mesh(
new THREE.SphereGeometry( radius, 32, 32 ),
new THREE.MeshPhongMaterial( { color: 0xdd5555, specular: 0x999999, shininess: 13} )
)
}
}
function Neutron(){
let radius = 1;
return {
// Cannon
body: new CANNON.Body({
mass: 1, // kg
position: randomPosition(6),
shape: new CANNON.Sphere(radius)
}),
// THREE
mesh: new THREE.Mesh(
new THREE.SphereGeometry( radius, 32, 32 ),
new THREE.MeshPhongMaterial( { color: 0x55dddd, specular: 0x999999, shininess: 13} )
)
}
}
function Electron(){
let radius = 0.2;
return {
// Cannon
body: new CANNON.Body({
mass: 0.5, // kg
position: randomPosition(10),
shape: new CANNON.Sphere(radius)
}),
// THREE
mesh: new THREE.Mesh(
new THREE.SphereGeometry( radius, 32, 32 ),
new THREE.MeshPhongMaterial( { color: 0xdddd55, specular: 0x999999, shininess: 13} )
)
}
}
function randomPosition(outerRadius){
let x = (2 * Math.random() - 1 ) * outerRadius,
y = (2 * Math.random() - 1 ) * outerRadius,
z = (2 * Math.random() - 1 ) * outerRadius
return new CANNON.Vec3(x, y, z);
}
function addToWorld(object){
world.add(object.body);
scene.add(object.mesh);
}
// create our Atom
let protons = Array(5).fill(0).map( () => Proton() );
let neutrons = Array(5).fill(0).map( () => Neutron() );
let electrons = Array(15).fill(0).map( () => Electron() );
protons.forEach(addToWorld);
neutrons.forEach(addToWorld);
electrons.forEach(addToWorld);
let light = new THREE.AmbientLight( 0x202020 ); // soft white light
scene.add( light );
let directionalLight = new THREE.DirectionalLight( 0xffffff, 0.5 );
directionalLight.position.set( -1, 1, 1 );
scene.add( directionalLight );
camera.position.z = 18;
const timeStep = 1/60;
//Small impulse on the electrons to get them moving in the start
electrons.forEach((electron) => {
let centerDir = electron.body.position.vsub(new CANNON.Vec3(0, 0, 0));
centerDir.normalize();
let impulse = centerDir.cross(new CANNON.Vec3(0, 0, 1));
impulse.scale(2, impulse);
electron.body.applyLocalImpulse(impulse, new CANNON.Vec3(0, 0, 0));
});
function render () {
requestAnimationFrame( render );
// all particles pull towards the center
protons.forEach(pullOrigin);
neutrons.forEach(pullOrigin);
electrons.forEach(pullOrigin);
// electrons should also be pushed by protons and neutrons
electrons.forEach( (electron) => {
let pushForce = new CANNON.Vec3(0, 0, 0 );
protons.forEach((proton) => {
let f = electron.body.position.vsub(proton.body.position);
pushForce.vadd(f, pushForce);
});
neutrons.forEach((neutron) => {
let f = electron.body.position.vsub(neutron.body.position);
pushForce.vadd(f, pushForce);
});
pushForce.scale(0.07, pushForce);
electron.body.force.vadd(pushForce, electron.body.force);
})
// protons and neutrons slows down (like wind resistance)
neutrons.forEach((neutron) => resistance(neutron, 0.95));
protons.forEach((proton) => resistance(proton, 0.95));
// Electrons have a max velocity
electrons.forEach((electron) => {maxVelocity(electron, 5)});
// Step the physics world
world.step(timeStep);
// Copy coordinates from Cannon.js to Three.js
protons.forEach(updateMeshState);
neutrons.forEach(updateMeshState);
electrons.forEach(updateMeshState);
renderer.render(scene, camera);
};
function updateMeshState(object){
object.mesh.position.copy(object.body.position);
object.mesh.quaternion.copy(object.body.quaternion);
}
function pullOrigin(object){
object.body.force.set(
-object.body.position.x,
-object.body.position.y,
-object.body.position.z
);
}
function maxVelocity(object, vel){
if(object.body.velocity.length() > vel)
object.body.force.set(0, 0, 0);
}
function resistance(object, val) {
if(object.body.velocity.length() > 0)
object.body.velocity.scale(val, object.body.velocity);
}
render();
<script src="https://cdnjs.cloudflare.com/ajax/libs/cannon.js/0.6.2/cannon.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r75/three.min.js"></script>
EDIT
I have modularized the particles into a Atom object that can be retrieved from the Atom function. Also added some more comments in the code if your unsure about anything. I would advise you to really study the code, and check the CANNON.js documentation (it is really thourogh). The force related stuff is in the Body class of Cannon.js. All i've done is to combine a THREE.Mesh and a CANNON.Body into a single object (for each particle). Then I simulate all movements on the CANNON.Body, and right before I render the THREE.Mesh, I copy the positions and rotations from CANNON.Body to THREE.Mesh.
This is the Atom function (changed some of the electron physics aswell):
function Atom(nProtons, nNeutrons, nElectrons, pos = new CANNON.Vec3(0, 0, 0)){
//variable to move the atom, which att the particles will pull towards
let position = pos;
// create our Atom
let protons = Array(nProtons).fill(0).map( () => Proton() );
let neutrons = Array(nNeutrons).fill(0).map( () => Neutron() );
let electrons = Array(nElectrons).fill(0).map( () => Electron() );
// Public Functions
//=================
// add to a three.js and CANNON scene/world
function addToWorld(world, scene) {
protons.forEach((proton) => {
world.add(proton.body);
scene.add(proton.mesh);
});
neutrons.forEach((neutron) => {
world.add(neutron.body);
scene.add(neutron.mesh);
});
electrons.forEach((electron) => {
world.add(electron.body);
scene.add(electron.mesh);
});
}
function simulate() {
protons.forEach(pullParticle);
neutrons.forEach(pullParticle);
//pull electrons if they are further than 5 away
electrons.forEach((electron) => { pullParticle(electron, 5) });
//push electrons if they are closer than 6 away
electrons.forEach((electron) => { pushParticle(electron, 6) });
// give the particles some friction/wind resistance
//electrons.forEach((electron) => resistance(electron, 0.95));
neutrons.forEach((neutron) => resistance(neutron, 0.95));
protons.forEach((proton) => resistance(proton, 0.95));
}
function electronStartingVelocity(vel) {
electrons.forEach((electron) => {
let centerDir = electron.body.position.vsub(position);
centerDir.normalize();
let impulse = centerDir.cross(new CANNON.Vec3(0, 0, 1));
impulse.scale(vel, impulse);
electron.body.applyLocalImpulse(impulse, new CANNON.Vec3(0, 0, 0));
});
}
// Should be called after CANNON has simulated a frame and before THREE renders.
function updateAtomMeshState(){
protons.forEach(updateMeshState);
neutrons.forEach(updateMeshState);
electrons.forEach(updateMeshState);
}
// Private Functions
// =================
// pull a particale towards the atom position (if it is more than distance away)
function pullParticle(particle, distance = 0){
// if particle is close enough, dont pull more
if(particle.body.position.distanceTo(position) < distance)
return false;
//create vector pointing from particle to atom position
let pullForce = position.vsub(particle.body.position);
// same as: particle.body.force = particle.body.force.vadd(pullForce)
particle.body.force.vadd( // add particle force
pullForce, // to pullForce
particle.body.force); // and put it in particle force
}
// Push a particle from the atom position (if it is less than distance away)
function pushParticle(particle, distance = 0){
// if particle is far enough, dont push more
if(particle.body.position.distanceTo(position) > distance)
return false;
//create vector pointing from particle to atom position
let pushForce = particle.body.position.vsub(position);
particle.body.force.vadd( // add particle force
pushForce, // to pushForce
particle.body.force); // and put it in particle force
}
// give a partile some friction
function resistance(particle, val) {
if(particle.body.velocity.length() > 0)
particle.body.velocity.scale(val, particle.body.velocity);
}
// Call this on a particle if you want to limit its velocity
function limitVelocity(particle, vel){
if(particle.body.velocity.length() > vel)
particle.body.force.set(0, 0, 0);
}
// copy ratation and position from CANNON to THREE
function updateMeshState(particle){
particle.mesh.position.copy(particle.body.position);
particle.mesh.quaternion.copy(particle.body.quaternion);
}
// public API
return {
"simulate": simulate,
"electrons": electrons,
"neutrons": neutrons,
"protons": protons,
"position": position,
"updateAtomMeshState": updateAtomMeshState,
"electronStartingVelocity": electronStartingVelocity,
"addToWorld": addToWorld
}
}
function Proton(){
let radius = 1;
return {
// Cannon
body: new CANNON.Body({
mass: 1, // kg
position: randomPosition(0, 6), // random pos from radius 0-6
shape: new CANNON.Sphere(radius)
}),
// THREE
mesh: new THREE.Mesh(
new THREE.SphereGeometry( radius, 32, 32 ),
new THREE.MeshPhongMaterial( { color: 0xdd5555, specular: 0x999999, shininess: 13} )
)
}
}
function Neutron(){
let radius = 1;
return {
// Cannon
body: new CANNON.Body({
mass: 1, // kg
position: randomPosition(0, 6), // random pos from radius 0-6
shape: new CANNON.Sphere(radius)
}),
// THREE
mesh: new THREE.Mesh(
new THREE.SphereGeometry( radius, 32, 32 ),
new THREE.MeshPhongMaterial( { color: 0x55dddd, specular: 0x999999, shininess: 13} )
)
}
}
function Electron(){
let radius = 0.2;
return {
// Cannon
body: new CANNON.Body({
mass: 0.5, // kg
position: randomPosition(3, 7), // random pos from radius 3-8
shape: new CANNON.Sphere(radius)
}),
// THREE
mesh: new THREE.Mesh(
new THREE.SphereGeometry( radius, 32, 32 ),
new THREE.MeshPhongMaterial( { color: 0xdddd55, specular: 0x999999, shininess: 13} )
)
}
}
function randomPosition(innerRadius, outerRadius){
// get random direction
let x = (2 * Math.random() - 1 ),
y = (2 * Math.random() - 1 ),
z = (2 * Math.random() - 1 )
// create vector
let randVec = new CANNON.Vec3(x, y, z);
// normalize
randVec.normalize();
// scale it to the right radius
randVec = randVec.scale( Math.random() * (outerRadius - innerRadius) + innerRadius); //from inner to outer
return randVec;
}
And to use it:
let scene = new THREE.Scene();
let world = new CANNON.World();
world.broadphase = new CANNON.NaiveBroadphase();
world.solver.iterations = 5;
let camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
let renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
// create a Atom with 3 protons and neutrons, and 5 electrons
// all circulating position (-4, 0, 0)
let atom = Atom(3, 3, 5, new CANNON.Vec3(-4, 0, 0));
// move atom (will not be instant)
//atom.position.x = -2;
// add to THREE scene and CANNON world
atom.addToWorld(world, scene);
let light = new THREE.AmbientLight( 0x202020 ); // soft white light
scene.add( light );
let directionalLight = new THREE.DirectionalLight( 0xffffff, 0.5 );
directionalLight.position.set( -1, 1, 1 );
scene.add( directionalLight );
camera.position.z = 18;
const timeStep = 1/60;
// give the atoms electrons some starting velocity
atom.electronStartingVelocity(2);
function render () {
requestAnimationFrame( render );
// calculate all the particles positions
atom.simulate();
// Step the physics world
world.step(timeStep);
//update the THREE mesh
atom.updateAtomMeshState();
renderer.render(scene, camera);
};
render();
I have been facing the same problem, and also made a solution using Cannon.js. However, when rendering heavier elements this might cause a considerable load, especially on mobile.
I came up with an idea to capture the final position of the nucleons after they have settled and save that in a json file for all the elements.
Then the nucleons can be made to orbit the nucleus linearly without physics.
one solution would be to use the icosphere algorithm to calculate the position of a Neutrons/Protons using the vertex point of generated sphere.
You can find ad usefoul algorithm here
the distance between the points remains equal over the entire surface

Three.js add dynamic line(s) between animated sprites

I'm trying to add a line(s) between animated sprites, like in this example. I tryed different solutions. But I couldn't make a dynamic line and not even a static line between sprites that are animated. Is it possible to create a dymanic line between those sprites from that example. If yes, how can I do it?
This is the code I used:
for ( var i = 0; i < objects.length; i ++ ) {
var geometry = new THREE.Geometry();
geometry.vertices.push(objects.position);
var material = new THREE.LineBasicMaterial( {
color: 0x0000FF,
transparent: true,
opacity: 1
} );
var line = new THREE.Line( geometry, material, THREE.LinePieces );
scene.add( line );
}
On ...jsfiddle.net/LxpmN/40/ u can see what I'm try to achieve, but he used two meshes instead of sprites. I understand that I need to put line.geometry.verticesNeedUpdate = true;, but I can't even make a static line from objects, like in that previous example.
If you want to add a collection of line segments to your scene, create one THREE.Line instead of many. Use a pattern like this one:
var geometry = new THREE.Geometry();
for ( var i = 0; i < objects.length - 1; i ++ ) { // stop one short of end
geometry.vertices.push( objects[ i ].position );
geometry.vertices.push( objects[ i + 1 ].position );
}
var material = new THREE.LineBasicMaterial( { color: 0x0000FF } );
var line = new THREE.Line( geometry, material, THREE.LinePieces );
scene.add( line );
If you modify any of the object's positions, you will have to add the following line in the render loop:
line.geometry.verticesNeedUpdate = true;
three.js r.71

Categories