Three JS rotate model towards xyz position - javascript

I'm trying to rotate an object in Three JS towards a fixed xyz location within a space. Currently I'm able to achieve it like this:
var position_x = -0.85;
var position_z = -4.44;
model.lookAt(position_x, 0, position_z);
However the lookAt() function rotates the model instantly and I would like to rotate the model more slowly. Is there a way to accomplish this using built in Three JS functions?
Thanks!

Is there a way to accomplish this using built in Three JS functions?
Yes, you can use Quaternion.rotateTowards() which works similar to Unity's Quaternion.rotateTowards() method.
The idea is to compute a target orientation which is represented by a quaternion. You can do this by using Matrix4.lookAt() and then create a quaternion based on this matrix via Quaternion.setFromRotationMatrix().
Next, you compute an angular step per frame the will define how much your object is turned towards the target. The computation of step looks like so:
const step = speed * delta;
delta is the time delta value in seconds and speed represents the turn rate of our model in radians per second.
A complete code example is available is here:
https://threejs.org/examples/webgl_math_orientation_transform

Related

2D/3D CAD design in JavaScript

I am having 2D design in microstation and I wanted to represent this design in web using any tool(javascript/Unity 3D or any other) where the web tool will not have all the functionality but basic functionality like reshaping or adding a new shape should be available.
As of now, my approach is once I created a design in microstation then I am capturing properties of shapes like the cordinates of a line and now using these coordinates I wanted to represent in the browser since this is a 2D design so it will be plotted in some location (x,y) for example I have created a line in microstation from (2,2) to (10,10) so it will be a straight line and I have all the coordinates I tried redrawing it in Unity which am able to do but I am facing issue to change the length from (2,2) to (20,20) by mouse click. And my goal is to do it in runtime, not in Unity editor tool.
This is an example of a straight line I wanted to do it for all geometric shape,any guidance would be appreciated.
As of now am trying Unity to do so but struggling in the edit part is there a way to achieve this in unity?
I also looked at various javascript libraries like konvaJS, makerJS, ThreeJS, etc. but except konvajs none of the other library provide facilities like reshaping, in Konva also creating shape using a mouse not found any solution for this.
Can we achieve this by any of the two approaches, of course, am not looking for all functionality only a few custom functionality, if yes which approach will be the best, and which tool should I proceed with?
Any guidance will be helpful.
To draw a line-segment, you can use LineRenderer.
//two points of the line-segment are known (or got from the Transform of GameObject)
Vector3 start;
Vector3 end;
GameObject myLine = new GameObject();
myLine.transform.position = start;
myLine.AddComponent<LineRenderer>();
LineRenderer lr = myLine.GetComponent<LineRenderer>();
lr.material = new Material(Shader.Find("Particles/Alpha Blended Premultiply"));
lr.SetColors(color, color);
lr.SetWidth(0.1f, 0.1f);
lr.SetPosition(0, start);
lr.SetPosition(1, end);
//to change the points of this line
myLine.transform.position = another_start;
lr.SetPosition(0, another_start);
lr.SetPosition(1, another_end);
There are also other solutions:
Use scaled cube or capsule primitive.
3rd-party plugins: vectrosity
To get mouse clicked position, use Camera.main.ScreenToWorldPoint(Input.mousePosition).
To determine when your mouse is clicked, use Input.GetMouseButtonUp.

Make two instances of d3.forceCollide() play nice together

I want two instances of d3.forceCollide(). In one, every node is pushed away from one another to prevent overlap. In the second, only a subset of nodes are pushed away from one another, with a much bigger radius.
To accomplish the second force, I tweak the initialize method to filter the incoming nodes, like so:
function selective(force,filter){
var init = force.initialize;
force.initialize = function(_){return init(_.filter(filter));};
return force;
}
var dpi = 90; // approximate pixels per inch in SVG
var size = dpi * (1/4); // quarter-inch unit size
var universally_applied =
d3.forceCollide()
.radius(size)
.strength(1);
var selectively_applied =
selective(
d3.forceCollide(),
function(d){return d.id === color;}
)
.radius(size*5)
.strength(1);
}
Now, this ALMOST works. I created a fiddle to see it in action: https://jsfiddle.net/jarrowwx/0dax43ue/38/ - every colored circle is supposed to repel every other circle of the same color, from a distance. Every other color, it just bumps into and pushes it out of the way.
If I do not change the order in which things are defined, then the selectively applied force is ONLY applied to the first color (red). If I shuffle the data array before applying forces, it is difficult to define exactly what happens, but the force is applied to some circles and not most of the others, even among the same color.
Any ideas what is going on here, or how to fix it?
The D3 team decided that this behavior was a bug (Isolating forces to a subset of nodes? #72), and fixed it. The fix was included in version 1.0.4 of d3-force, which is available as part of the full D3 build as of version 4.4.0.
The problem is resolved using the solution suggested by "Partial forces on nodes in D3.js", and the code works as intended now.

Is object facing another

I'd like to derive a value for how much one object is facing another. For example if it is directly facing the value would be 1 and facing directly away -1.
I have the object's global position and a quaternion for orientation. I'm using three.js
This is what I have so far, but its not giving me numbers I would expect.
Storing the object orientation as 3 part vector:
const lookVector = new THREE.Vector3(0,0,1);
const direction = lookVector.clone().applyMatrix4(torsoMesh.matrix);
this.lookVector = direction.sub(this.worldPosition);
Then using this to derive an angle to another point:
angleTo(pointOfInterest){
const vectorToPOI = pointOfInterest.sub(this.worldPosition);
const angle = this.lookVector.angleTo(vectorToPOI);
return angle;
}
one way to achieve this is using dot product. It is very simple, you just normalize both vectors and multiply each component respectively, then sum them up. I won't go into more detail here, because there is loads of resources explaining this on the internet. But here is an example of how to do it in three.js:
this.lookVector.normalize();
pointOfInterest.normalize();
var angleValue = this.lookVector.dot(pointOfInterest);
this will give exactly what you asked for (just remember that by calling normalize() on a vector, you are modifying it).
angleValue is actually just the cosine of the angle between the two vectors, so another way would just be to do:
.
.
return Math.cos(angle);
hope I understood you question correctly.
I know the mesh objects keep rotation values in radians. Maybe you can have a "parent mesh" so to speak and its its rotation values to determine this.

Javascript spring physics: Apply direction vector to spring

I'm implementing spring physics in Javascript, inspired by this blog post. My system uses Hooke's Law formula to calculate spring forces:
F = -k(|x|-d)(x/|x|) - bv
I made a CodePen that shows the implementation of a spring between two points. The CodePen has two points connected by a spring, and every 2 seconds the point positions are randomized. You can see the points bounce on the spring towards each other.
If you look at the source, you can see I've defined a direction vector for my spring:
var spring = {
length: 100,
direction: {
x: 1, y: 1
}
};
I'm trying to make it so that the spring always "resolves" in this direction. Put another way, I'd like the spring to always be "pointing" up and to the right. If this were implemented in the CodePen, it means the resting orientation of the points would always be the green point on the bottom left, and the blue point on the top right. No matter where the points start, they should end up in the following orientation (which matches the direction vector):
I've tried multiplying the normals by the spring vector:
norm1 = multiplyVectors( normalize( sub1 ), spring.direction ),
However this is a noop because the vector is (1,1). I've been hacking on this system for a few days now and I'm stuck. How can I constrain my 2d spring to a specific direction?
Spring forces are central just like gravity, which means that the total angular momentum of the system is conserved. Since you start with zero initial velocities, the angular momentum of the system is initially zero. The spring interaction keeps it zero, therefore the final orientation of the spring equals its initial orientation - the weights only move along the line connecting them.
To have the system rotate into the desired final position, you should also apply torque. The easiest way is to give the blue weight a positive charge and the green weight a negative one and then apply a constant external field in direction (1,1). That way the two charges will form a dipole and the interaction with the external field will generate the desired torque.
I don't get along with JavaScript, but I tried to write something based on your initial code here. The force that an external field with intensity E exerts on charge q is F = q * E, with both F and E being vectors. By adjusting q and E you can control how quickly the dipole will orient in the direction of the external field.
The force now becomes F = -k(|x|-d)(x/|x|) + qE - bv.
This has the probably undesired side effect that the final length of the spring will be slightly longer by delta, where delta = 2 * |q||E| / k. You can always adjust for that by reducing the length of the spring. Also, there is a little problem with that approach. Namely, there are two equilibrium states: one with the dipole facing the direction of the field (stable equilibrium) and one with the dipole facing the opposite direction (unstable equilibrium). A bit of random noise in the initial steps of the simulation will prevent the dipole from being trapped into the latter state.

The closer the x/y the more x/y velocity

I am writing a fairly simple script in JavaScript using the canvas. It draws a central node which pulls all of the surrounding nodes towards it. This works great, however I need each node to repel each other.
I am going to do this by increasing each nodes velocity away from each other so eventually they should level out and end up looking something like a flower. It needs to be enough force to stop them from hitting each other or sinking into the center node without flying off into the distance.
I just can not work out how I can have a higher number the closer they get.
So if two nodes where 10px away from each other it would add 5 in force to one of their x velocities. But if they where 1000px away from each other then it would add almost nothing to the force of one of the nodes.
Does anyone know of a mathematical equation I can use to work this kind of thing out, or maybe a nudge in the right direction?
TL;DR: Depending on how close two x values are, I need to increment the x velocity of one node so they move apart but eventually level out. It is just the maths I can not crack, I have pretty much all of the JavaScript done, including the implementation of velocity.
Thanks, and sorry it is a bit wordy.
You just need an inverse (or inverse square) relationship:
var increment = k / distance;
or:
var increment = k / (distance * distance);
You can determine k based on the actual values you want, for example, in the first case, if you wanted an increment of 5 for a distance of 10, you would set k = increment * distance = 50.
Look into the equations governing electrical point charges, have the velocity be based on the "force" each "charge" would feel based on its proximity.

Categories