I have a construction that starts with a point and a segment. Later I have an intersection. The correct output of the intersection depend if the 3.rd parameter i is 0 or 1. The point and the line are not part of create('intersection'....
If 0 or 1 depends where the point is relative to the line. Is it above or left the line it is 1 otherwise 0.
So I thougt I create an angle between the the point and the segment and decide if the angle is less pi. Statically this works, but how do I update the intersection, if I move the point or the segment?
Best regards basil
At the moment (i.e. v1.5.0) dynamic values for the intersection number are not supported.
But this is a very good suggestion. We included it into the source, it will be available in 1.5.1. Here is an example how to use it:
var ci = board.create('circle', [[0, 0], 3]);
var li = board.create('line', [[-3, -3], [4, 1]]);
var sl = board.create('slider', [[1,4], [2,4], [0, 0, 1]],
{snapWidth: 1, name:'i', digits:0});
var is = board.create('intersection', [ci, li, () => sl.Value()]);
Related
After using CSG my mesh gets messed up with lots of more vertices and faces than needed. The data provides all vertices in a single array without differentiating wether they are real corners or somewhere in the middle of the surface / plane. I made a simple fiddle to show an example.
https://jsfiddle.net/apbln/k5ze30hr/82/
geometry.vertices.push(
new THREE.Vector3(-1, -1, 0), // 0
new THREE.Vector3( 1, -1, 0), // 1
new THREE.Vector3(-1, 1, 0), // 2
new THREE.Vector3( 1, 1, 0), // 3
new THREE.Vector3(-0.5, -0.5, 0), // 4
new THREE.Vector3( 0, 1, 0), // 5
new THREE.Vector3( 1, -1, 0), // 6
);
geometry.faces.push(
new THREE.Face3(0, 5, 2),
new THREE.Face3(0, 1, 5),
new THREE.Face3(3, 5, 1),
);
This is a simplified version of how my surfaces look like after using csg. How could I possibly know which vertices are real corners, so that I could repair the surface with 2 faces only?
You could try detecting adjacent faces. If two faces share an edge and they are coplanar then they can be merged. This would be a slightly more general algorithm.
Skecth of algorithm would be to first build adjacency graph where each edge is linked to the faces adjacent to it. Then loop through the list of edges and detect those where the two adjacent faces are coplaner, if so merge the faces and adjust adajacency lists.
Its a bit more complex if you require a triangular mesh. Best aproach might be to first construct the mesh with non triangular faces and then split them into triangles.
Its a pretty common problem and there are no doubt libraries which can do it for you. This answer may help: ThreeJS: is it possible to simplify an object / reduce the number of vertexes?
Let's say I have this triangle (dark blue) and I know it's vertices (red):
(1,3,0)
(0,4,0)
(-1,3,0)
Now I want to create new points (yellow) above their vertices but parallel to the triangle. In this case it is easy: just add to the y value and you got it.
But what if the triangle is not straight up? for example:
(1,3,0)
(0,4,1)
(-1,3,0)
I got its n-Vector (green line) and I think I have to use it to create these parallel points, but I don't know how...I am looking for a way to do this to multiple triangles programmatically that are positioned in all kind of ways. Any idea?
#Ben Whitmore
var v1 = new THREE.Vector3(0,4,1);
var v2 = new THREE.Vector3(1,3,0);
var v3 = new THREE.Vector3(-1,3,0);
var c = new THREE.Vector3( );
c.crossVectors( v2, v3 ) // { x: 0, y: -0, z: 6 }
c.normalize() // { x: 0, y: -0, z: 1 }
sphere.position.set( ??? );`
To achieve this you need to find a direction vector that is perpendicular to the plane of the triangle. This can be easily derived from the cross product of two of the edges of the triangle, the result then normalised to a unit vector.
There are of course two directions that vector can take, to be perpendicular to the plane: it can be pointing "above" the plane or "below" the plane. Which direction you get will depend on the clockwise/anticlockwise directions of the triangle's edge vectors. If it's not the direction you want, simply invert it.
I have exported some hair particules from Blender (a hairstyle). These are composed of several lines (GL_LINES). My openGL program displays these particules without any problem. Now I just want to apply light properties on these particules. Blender does not export the normals vectors so I need to compute them by myself. I know the following rule :
If we define a line segment as [AB] in two dimensions,
we have dx = xB - xA and dy = yB - yA, then the normals are N1(-dy, dx) and N2(dy, -dx).
I hope I did not make any mistake.
But I don't know the rule for a 3D space line segment definition if I add the z dimention in my line segment coordinates (for instance A(5, 2, 3) and B(0, 0, -5)).
Does anyone can help me?
Since Aki forgot that comments aren't answers:
Lines in 3D space don't have a normal. Technically, lines in 2D space don't have a normal either; they have two normals.
There are an infinite number of directions that are perpendicular to a line in 3D space. All of these normals are in the same plane, but with different directions. Without some more advanced algorithm (likely based on adjacent lines), there is no way to pick one of these normals over another.
If you assume that you can get two vectors to begin with, and it looks like that's what you are saying, call them v, w, to get a normal vector take the cross product. It's not a bad idea to normalize v, w to begin with, depending on the situation. The cross product can be given by:
v x w =(v_2w_3 - v_3w_2, v_3x_1 - v_1w_3, v_1w_2 - v_3w_1),
Here v_i is the ith component of v and so on. The numbers next to each other represent multiplication. You, of course, have plus or minus this vector giving two possibilities.
I had a similar question, and even used the indefinite article "a". Some have suggested there is no norm to a 3D line segment by saying there is an infinite number of them. Yet, miss the indefinite article "a" --- which I assume could mean any 1 of infinite.
What happens when someone does not have two vectors to start with?
vector is the unit vector of the line segment or vector.
create a rotation matrix around vector to obtain 1 of infinite norms
It took some time, but using Eigen template library and 10000 random test samples. Here is the code:
#include <Eigen/Core>
#include <Eigen/Geometry>
Eigen::MatrixXd samples = Eigen::MatrixXd::Random(10000, 3); // 3x3 Matrix filled with random numbers between (-1,1)
for (int i = 0; i < 10000; ++i)
{
Eigen::Vector3d vector(samples(i, 0), samples(i, 1), samples(i, 2));
vector.normalize();
Eigen::Vector3d zaxis(0, 0, 1);
Eigen::Vector3d xaxis = zaxis.cross(vector);
xaxis.normalize();
Eigen::Vector3d yaxis = vector.cross(xaxis);
yaxis.normalize();
Eigen::Matrix3d m;
m(0, 0) = xaxis(0);
m(0, 1) = yaxis(0);
m(0, 2) = vector(0);
m(1, 0) = xaxis(1);
m(1, 1) = yaxis(1);
m(1, 2) = vector(1);
m(2, 0) = xaxis(2);
m(2, 1) = yaxis(2);
m(2, 2) = vector(2);
// one of two easy points to use to get 1 of infinite norms --- the other being (1, 0, 0)
Eigen::Vector3d point(0, 1, 0);
point = m * point;
point.normalize();
auto norm = point.cross(vector);
norm.normalize(); // 1 of an infinite number of norms
auto check = norm.dot(vector); // verify with dot product
if (std::abs(check) >= 1e-12)
{
//complain
}
}
I'm rusty a bit here.
I have a vector (camDirectionX, camDirectionY, camDirectionZ) that represents my camera direction of view.
I have a (camX, camY, camZ) that is my camera position.
Then, I have an object placed at (objectX, objectY, objectZ)
How can I calculate, from the camera point of view, the azimut & elevation of my object ??
The first thing I would do, to simplify the problem, is transform the coordinate space so the camera is at (0, 0, 0) and pointing straight down one of the axes (so the direction is say (0, 0, 1)). Translating so the camera is at (0, 0, 0) is pretty trivial, so I won't go into that. Rotating so that the camera direction is (0, 0, 1) is a little trickier...
One way of doing it is to construct the full orthonormal basis of the camera, then stick that in a rotation matrix and apply it. The "orthonormal basis" of the camera is a fancy way of saying the three vectors that point forward, up, and right from the camera. They should all be at 90 degrees to each other (which is what the ortho bit means), and they should all be of length 1 (which is what the normal bit means).
You can get these vectors with a bit of cross-product trickery: the cross product of two vectors is perpendicular (at 90 degrees) to both.
To get the right-facing vector, we can just cross-product the camera direction vector with (0, 1, 0) (a vector pointing straight up). You'll need to normalise the vector you get out of the cross-product.
To get the up vector of the camera, we can cross product the camera direction vector with the right-facing vector we just calculated. Assuming both input vectors are normalised, this shouldn't need normalising.
We now have the orthonormal basis of the camera. If we stick these vectors into the rows of a 3x3 matrix, we get a rotation matrix that will transform our coordinate space so the camera is pointing straight down one of the axes (which one depends on the order you stick the vectors in).
It's now fairly easy to calculate the azimuth and elevation of the object.
To get the azimuth, just do an atan2 on the x/z coordinates of the object.
To get the elevation, project the object coordinates onto the x/z plane (just set the y coordinate to 0), then do:
acos(dot(normalise(object coordinates), normalise(projected coordinates)))
This will always give a positive angle -- you probably want to negate it if the object's y coordinate is less than 0.
The code for all of this will look something like:
fwd = vec3(camDirectionX, camDirectionY, camDirectionZ)
cam = vec3(camX, camY, camZ)
obj = vec3(objectX, objectY, objectZ)
# if fwd is already normalised you can skip this
fwd = normalise(fwd)
# translate so the camera is at (0, 0, 0)
obj -= cam
# calculate the orthonormal basis of the camera
right = normalise(cross(fwd, (0, 1, 0)))
up = cross(right, fwd)
# rotate so the camera is pointing straight down the z axis
# (this is essentially a matrix multiplication)
obj = vec3(dot(obj, right), dot(obj, up), dot(obj, fwd))
azimuth = atan2(obj.x, obj.z)
proj = vec3(obj.x, 0, obj.z)
elevation = acos(dot(normalise(obj), normalise(proj)))
if obj.y < 0:
elevation = -elevation
One thing to watch out for is that the cross-product of your original camera vector with (0, 1, 0) will return a zero-length vector when your camera is facing straight up or straight down. To fully define the orientation of the camera, I've assumed that it's always "straight", but that doesn't mean anything when it's facing straight up or down -- you need another rule.
Hello all math masters, I got a problem for you:
I have a 2D game (top down), and I would like to make the character escape from a shot, but not just walk away from the shot (I mean, don't be pushed by the shot), I want it to have a good dodging skills.
The variables are:
shotX - shot x position
shotY - shot y position
shotSpeedX - shot x speed
shotSpeedY - shot x speed
charX - character x position
charY - character y position
keyLeft - Set to true to make the character press the to left key
keyRight - Set to true to make the character press the to right key
keyUp - Set to true to make the character press the to up key
keyDown - Set to true to make the character press the down key
I can understand the following languages:
C/C++
Java
Actionscript 2/3
Javascript
I got this code (Actionscript 3), but sometimes it doesn't work:
var escapeToLeft:Boolean = false;
var r:Number = Math.atan2(0 - shotSpeedY, 0 - shotSpeedX)
var angle:Number = Math.atan2(charY - (shotY + shotSpeedY), charX - (shotX + shotSpeedX));
var b:Number = diepix.fixRotation(r-angle); // This function make the number between -180 and 180
if(b<0) {
escapeToLeft = true;
}
r += (escapeToLeft?1:0 - 1) * Math.PI / 2;
var cx:Number = Math.cos(r);
var cy:Number = Math.sin(r);
if(cx < 0.0) {
keyLeft = true;
}else {
keyRight = true;
}
if(cy < 0.0) {
keyUp = true;
}else {
keyDown = true;
}
Some observations:
Optimal dodging probably involves moving at a 90 degree angle from the bullets direction. That way, you get out of harms way the quickest.
If you do err, you want to err in the direction of the bullet, as that buys you time.
you can calculate 90 degrees to bullet direction with the scalar product
find the closest compass direction to the calculated optimal angle (4 possible answers)
are you allowed to go up and left at the same time? Now you have 8 possible answers to a bullet
bonus points for dodging in optimal direction according to second point
The scalar product of two vectors (ax, ay) and (bx, by) is ax * bx + ay * by. This is 0 if they are orthogonal (90 degrees). So, given the bullet (ax, ay), find a direction (bx, by) to run that has a scalar product of 0:
ax * bx must equal ay * by, so (bx, by) = (-ax, -ay)
Now to find the closest point on the compass for (bx, by), the direction you would like to run to. You can probably figure out the technique from the answer to a question of mine here on SO: How to "snap" a directional (2D) vector to a compass (N, NE, E, SE, S, SW, W, NW)? (note, thow, that I was using a wonky coordinate system there...)
If you have only 4 compass directions, your easiest path is to take:
max(abs(bx), abs(by))
The bigger vector component will show you the general direction to go - for
bx positive: right
bx negative: left
by positive: up (unless (0, 0) is top left with y positive in bottom left...)
by negative: down
I guess you should be able to come up with the rest on your own - otherwise, good luck on writing your own game!
I am not following what the line
var angle:Number = Math.atan2(charY - (shotY + shotSpeedY), charX - (shotX + shotSpeedX));
is supposed to be doing. The vector ( charY - shotY, charX - shotX ) would be the radius vector pointing from the location of the shot to the location of the character. But what do you have when you subtract a speed vector from that, as you are doing in this line?
It seems to me that what you need to do is:
Calculate the radius vector (rY, rX) where rY = shotY - charY; rX = xhotX - charX
Calculate the optimal direction of jump, if the character weren't constrained to a compass point.
Start with a vector rotated 90 degrees from the shot-character radius vector. Say vJump = ( rX, -rY ). (I think Daren has this calculation slightly wrong--you are transposing the two coordinates, and reversing one of their signs.)
The character should either wants to jump in the direction of vJump or the direction of -vJump. To know which, take the scalar product of vJump with (shotSpeedY, shotSpeedX). If this is positive, then the character is jumping towards the bullet, which you don't want, obviously, so reverse the sign of both components of vJump in this case.
Jump in the permissible direction that is closest to vJump. In the code you listed, you are constrained to jump in one of the diagonal directions--you will never jump in one of the cardinal directions. This may in fact be the mathematically optimal solution, since the diagonal jumps are probably longer than the cardinal jumps by a factor of 1.414.
If your jumps are actually equal distance, however, or if you just don't like how it looks if the character always jumps diagonally, you can test each of the eight cardinal and intermediate directions by calculating the scalar product between vJump and each of the eight direction vectors (0,1), (0.7071,0.7071), (1,0), (0.7071,-0.7071), etc. Take the direction that gives you the biggest positive scalar product. Given the patterns present, with some clever programming you can do this in fewer than eight tests.
Note that this algorithm avoids any math more complicated than addition and multiplication, so will likely have much better performance than something that requires trig functions.