3D coordinates interpolation - opengl

Let's suppose a square (4 points), viewed from top.
Each of the 4 points do not have the same altimetry.
If you look from top (or from bottom), you see a square, but if you look from side, you will see that the 4 points are not at the same level.
So you have a plane which is not horizontal.
Lets imagine a fifth point inside the square. What i want to do is to calculate the altimetry of this fifth point. This altimetry is a function of the position of the point inside the square, and the altimetry of the 4 points of the square.
I think i have to compute an interpolation but i did not managed to do it...
Any idea ?
Thanks

So unless you know for certain that all points lie on a single plane, which would be a simplification of this method, I'll assume you have divided your square into two triangles. Furthermore, I'll assume there are 4 vertices, v_00, v_10, v_01, and v_11 representing each vertex of your square. I will also assume that your triangles are defined as (v_00, v_10, v_11), and (v_00, v_11, v_01).
vec4 v00 = vec4(...);
vec4 v01 = vec4(...);
vec4 v10 = vec4(...);
vec4 v11 = vec4(---);
vec4[2][3] triangles = {{v00, v10, v11}, {v00, v11, v01}};
Finally, I'll assume you know the X and Y coordinates relative to the bottom left vertex (just subtract the x and y coordinate of your fifth point from the x and y coordinates of v_00). I'll call this point P. We'd like to know its z coorinate.
vec4 fifthPoint = vec4(...);
vec4 P = fifthPoint - v00;
This means the "shared border" of both triangles lies along the diagonal going between the bottom left and top right of your square.
Since both triangles can be entirely different, determining the coordinates of your arbitrary fifth point starts with determining which of the two triangles it is on.
Since we know the shape is a square, we can take the coordinates of our point P relative to v_00 (as I assumed previously), and see which is greater than the other. If the x coordinate of P is greater than the y coordinate, we know P is on the bottom right triangle. Otherwise it's on the top left one.
bool whichTriangle = P.x > P.y;
int triangleIndex = whichTriangle ? 0 : 1;
Now that we know which triangle we're on, we can interpolate their coordinates to obtain any point on the surface of the triangle.
For triangle 0:
vec4 vectorX = triangles[0][1] - triangles[0][0];
vec4 vectorY = triangles[0][2] - triangles[0][1];
For triangle 1:
vec4 vectorX = triangles[1][1] - triangles[1][2];
vec4 vectorY = triangles[1][2] - triangles[1][0];
Notice that each vector here goes along the x and y axis. That's important, so that we can directly use the x and y coordinates from P to calculate interpolated values.
Next, we normalise the two vectors we just created.
vectorX = vectorX.normalize();
vectorY = vectorY.normalize();
Now we just need to multiply these two values with the X and Y coordinates of P to get any point on the triangle, and add it to a base point.
For triangle 0:
P = triangles[0][0] + vectorX * P.x + vectorY * P.y;
For triangle 1:
P = triangles[1][1] - vectorX * (1.0 - P.x) - vectorY * (1.0 - P.y);
And there you have it. A far too complicated explanation for something that's actually not all that hard. P.z now contains the Z-coordinate of your arbitrary point.

Being a trapezoid ABCD consider this ruled surface:
Then you can interpolate P1 from A and B, and P2 from C and D. Finally you can interpolate P height from P1 and P2 heights

Related

OpenGl Rotate object on Y axis to look at another object

So like in a topic I got 2 objects one i moving around (on z and x axis) the other one is static but should rotate around y axis to always like a look at the other... and i am fighting with this already a week
what i got now is
vector from 1object to 2object and actual look at(also vector) of the 2object
i'am calculating angel betwean this two vectors and adding this to rotattion.y of the 2 object but its not working properly
any idea how to make it work? btw i'am using eular angel transforms
pseudCode:
vectorFrom1to2 = vector1 - vector2;
lookatVectorof2ndObject;
i normalize both of them and then
float angle = acos(dot(vectorFrom1to2, lookatVectorof2ndObject));
object2.rotateY = angle;
i dont know where i do mistake
As a general rule of thumb, which proved itself true in many situations I observed is: As soon as you find yourself calculating angles from vectors, you are most likely doing something in a more unnecessarily complicated way than necessary.
All you need is a basis transformation which transforms the first object's local coordinate system to make its local Z axis point towards the second object. You can do this with a simple rotation matrix (provided you have a matrix/vector library ready to facilitate this more easily).
So, provided you have object 1 with position p1 and object 2 with position p2 and you want p1 to rotate towards p2, then the rotation matrix can be obtained as follows:
(I am just using GLSL pseudo syntax here)
vec3 p1 = ... // <- position of first object
vec3 p2 = ... // <- position of second object
vec3 d = normalize(p2 - p1)
vec3 r = cross(vec3(0.0, 1.0, 0.0), d)
= vec3(d.z, 0, -d.x)
mat3 m = mat3(d.z, 0, -d.x, // <- first column ('right' vector)
0, 1, 0, // <- second column (keep Y)
d.x, 0, d.z) // <- third column (map Z to point towards p2)
When transforming the vertices v of the first object with m by: v' = m * v you get the Z axis of object p1 to point towards the position of p2, all formulated in the same "world" coordinate system.

Need rotation matrix for opengl 3D transformation

The problem is I have two points in 3D space where y+ is up, x+ is to the right, and z+ is towards you. I want to orientate a cylinder between them that is the length of of the distance between both points, so that both its center ends touch the two points. I got the cylinder to translate to the location at the center of the two points, and I need help coming up with a rotation matrix to apply to the cylinder, so that it is orientated the correct way. My transformation matrix for the entire thing looks like this:
translate(center point) * rotateX(some X degrees) * rotateZ(some Z degrees)
The translation is applied last, that way I can get it to the correct orientation before I translate it.
Here is what I have so far for this:
mat4 getTransformation(vec3 point, vec3 parent)
{
float deltaX = point.x - parent.x;
float deltaY = point.y - parent.y;
float deltaZ = point.z - parent.z;
float yRotation = atan2f(deltaZ, deltaX) * (180.0 / M_PI);
float xRotation = atan2f(deltaZ, deltaY) * (180.0 / M_PI);
float zRotation = atan2f(deltaX, deltaY) * (-180.0 / M_PI);
if(point.y < parent.y)
{
zRotation = atan2f(deltaX, deltaY) * (180.0 / M_PI);
}
vec3 center = vec3((point.x + parent.x)/2.0, (point.y + parent.y)/2.0, (point.z + parent.z)/2.0);
mat4 translation = Translate(center);
return translation * RotateX(xRotation) * RotateZ(zRotation) * Scale(radius, 1, radius) * Scale(0.1, 0.1, 0.1);
}
I tried a solution given down below, but it did not seem to work at all
mat4 getTransformation(vec3 parent, vec3 point)
{
// moves base of cylinder to origin and gives it unit scaling
mat4 scaleFactor = Translate(0, 0.5, 0) * Scale(radius/2.0, 1/2.0, radius/2.0) * cylinderModel;
float length = sqrtf(pow((point.x - parent.x), 2) + pow((point.y - parent.y), 2) + pow((point.z - parent.z), 2));
vec3 direction = normalize(point - parent);
float pitch = acos(direction.y);
float yaw = atan2(direction.z, direction.x);
return Translate(parent) * Scale(length, length, length) * RotateX(pitch) * RotateY(yaw) * scaleFactor;
}
After running the above code I get this:
Every black point is a point with its parent being the point that spawned it (the one before it) I want the branches to fit into the points. Basically I am trying to implement the space colonization algorithm for random tree generation. I got most of it, but I want to map the branches to it so it looks good. I can use GL_LINES just to make a generic connection, but if I get this working it will look so much prettier. The algorithm is explained here.
Here is an image of what I am trying to do (pardon my paint skills)
Well, there's an arbitrary number of rotation matrices satisfying your constraints. But any will do. Instead of trying to figure out a specific rotation, we're just going to write down the matrix directly. Say your cylinder, when no transformation is applied, has its axis along the Z axis. So you have to transform the local space Z axis toward the direction between those two points. I.e. z_t = normalize(p_1 - p_2), where normalize(a) = a / length(a).
Now we just need to make this a full 3 dimensional coordinate base. We start with an arbitrary vector that's not parallel to z_t. Say, one of (1,0,0) or (0,1,0) or (0,0,1); use the scalar product ·(also called inner, or dot product) with z_t and use the vector for which the absolute value is the smallest, let's call this vector u.
In pseudocode:
# Start with (1,0,0)
mindotabs = abs( z_t · (1,0,0) )
minvec = (1,0,0)
for u_ in (0,1,0), (0,0,1):
dotabs = z_t · u_
if dotabs < mindotabs:
mindotabs = dotabs
minvec = u_
u = minvec_
Then you orthogonalize that vector yielding a local y transformation y_t = normalize(u - z_t · u).
Finally create the x transformation by taking the cross product x_t = z_t × y_t
To move the cylinder into place you combine that with a matching translation matrix.
Transformation matrices are effectively just the axes of the space you're "coming from" written down as if seen from the other space. So the resulting matrix, which is the rotation matrix you're looking for is simply the vectors x_t, y_t and z_t side by side as a matrix. OpenGL uses so called homogenuous matrices, so you have to pad it to a 4×4 form using a 0,0,0,1 bottommost row and rightmost column.
That you can load then into OpenGL; if using fixed functio using glMultMatrix to apply the rotation, or if using shader to multiply onto the matrix you're eventually pass to glUniform.
Begin with a unit length cylinder which has one of its ends, which I call C1, at the origin (note that your image indicates that your cylinder has its center at the origin, but you can easily transform that to what I begin with). The other end, which I call C2, is then at (0,1,0).
I'd like to call your two points in world coordinates P1 and P2 and we want to locate C1 on P1 and C2 to P2.
Start with translating the cylinder by P1, which successfully locates C1 to P1.
Then scale the cylinder by distance(P1, P2), since it originally had length 1.
The remaining rotation can be computed using spherical coordinates. If you're not familiar with this type of coordinate system: it's like GPS coordinates: two angles; one around the pole axis (in your case the world's Y-axis) which we typically call yaw, the other one is a pitch angle (in your case the X axis in model space). These two angles can be computed by converting P2-P1 (i.e. the local offset of P2 with respect to P1) into spherical coordinates. First rotate the object with the pitch angle around X, then with yaw around Y.
Something like this will do it (pseudo-code):
Matrix getTransformation(Point P1, Point P2) {
float length = distance(P1, P2);
Point direction = normalize(P2 - P1);
float pitch = acos(direction.y);
float yaw = atan2(direction.z, direction.x);
return translate(P1) * scaleY(length) * rotateX(pitch) * rotateY(yaw);
}
Call the axis of the cylinder A. The second rotation (about X) can't change the angle between A and X, so we have to get that angle right with the first rotation (about Z).
Call the destination vector (the one between the two points) B. Take -acos(BX/BY), and that's the angle of the first rotation.
Take B again, ignore the X component, and look at its projection in the (Y, Z) plane. Take acos(BZ/BY), and that's the angle of the second rotation.

Set the orientation of objects in 3d space

I have program in which I am drawing some shapes such as rectangle/circle/triangle etc. in 3D space, equidistant from the centre.
Example of two points which are equidistant from the centre (0,0,0) are
x1: 93, 313, 123
x2: -263, -135, -186
and there may be more points as well.
At these two points, I am drawing the shapes by something like
glRectangle(x1, width, height);
The shapes (rectangles/triangles etc.) come out very well at the starting vertex (x1 or x2) equi-distant from the centre. However, the shapes have wrong orientation in space as to what I am looking for.
I want centre of the plane of in which the shape lies to to be prependicular to an imaginary line coming from the centre. This probably can be solved by rotation of the plane but I am not sure about the approach to adopt. For the current example, let's say I have the vertex of the shape but how do I figure out the plane in which the the rectangle is and rotate that plane to make it prependicular (to the line coming from the centre of the space (0,0,0))
If the center needs to be perpendicular to the vector C (Line between coord-center and rect-center), it should work like this (pseudo-code):
A = C x UP_VECTOR (CROSS-PRODUCT to calculate helper vector pointing in "sideway" direction of "rectangle")
B = C x A (CROSS-PRODUCT to get the local "up/down" vector of the "rectangle")
A = normalize(A)
B = normalize(B)
P1 = width/2 * A + height/2 * B
P2 = -width/2 * A + height/2 * B
P3 = -width/2 * A + -height/2 * B
P4 = width/2 * A + -height/2 * B
Hopefully this is understandable and right (didn't try it and had some trouble finding the right vocabulary)
Some additional informations:
A and B are helper vectors and are the local up and left directions on the rectangle, after normalizing they can be used to calculate the 4 points of the rectangle accordingly.
Also be careful if no rectangle is displayed it's probably related to the drawing order so just reverse the order then if front and backfaces are wrong...

Generating a normal map from a height map?

I'm working on procedurally generating patches of dirt using randomized fractals for a video game. I've already generated a height map using the midpoint displacement algorithm and saved it to a texture. I have some ideas for how to turn that into a texture of normals, but some feedback would be much appreciated.
My height texture is currently a 257 x 257 gray-scale image (height values are scaled for visibility purposes):
My thinking is that each pixel of the image represents a lattice coordinate in a 256 x 256 grid (hence, why there are 257 x 257 heights). That would mean that the normal at coordinate (i, j) is determined by the heights at (i, j), (i, j + 1), (i + 1, j), and (i + 1, j + 1) (call those A, B, C, and D, respectively).
So given the 3D coordinates of A, B, C, and D, would it make sense to:
split the four into two triangles: ABC and BCD
calculate the normals of those two faces via cross product
split into two triangles: ACD and ABD
calculate the normals of those two faces
average the four normals
...or is there a much easier method that I'm missing?
Example GLSL code from my water surface rendering shader:
#version 130
uniform sampler2D unit_wave
noperspective in vec2 tex_coord;
const vec2 size = vec2(2.0,0.0);
const ivec3 off = ivec3(-1,0,1);
vec4 wave = texture(unit_wave, tex_coord);
float s11 = wave.x;
float s01 = textureOffset(unit_wave, tex_coord, off.xy).x;
float s21 = textureOffset(unit_wave, tex_coord, off.zy).x;
float s10 = textureOffset(unit_wave, tex_coord, off.yx).x;
float s12 = textureOffset(unit_wave, tex_coord, off.yz).x;
vec3 va = normalize(vec3(size.xy,s21-s01));
vec3 vb = normalize(vec3(size.yx,s12-s10));
vec4 bump = vec4( cross(va,vb), s11 );
The result is a bump vector: xyz=normal, a=height
My thinking is that each pixel of the image represents a lattice coordinate in a 256 x 256 grid (hence, why there are 257 x 257 heights). That would mean that the normal at coordinate (i, j) is determined by the heights at (i, j), (i, j + 1), (i + 1, j), and (i + 1, j + 1) (call those A, B, C, and D, respectively).
No. Each pixel of the image represents a vertex of the grid, so intuitively, from symmetry, its normal is determined by heights of neighboring pixels (i-1,j), (i+1,j), (i,j-1), (i,j+1).
Given a function f : ℝ2 → ℝ that describes a surface in ℝ3, a unit normal at (x,y) is given by
v = (−∂f/∂x, −∂f/∂y, 1) and n = v/|v|.
It can be proven that the best approximation to ∂f/∂x by two samples is archived by:
∂f/∂x(x,y) = (f(x+ε,y) − f(x−ε,y))/(2ε)
To get a better approximation you need to use at least four points, thus adding a third point (i.e. (x,y)) doesn't improve the result.
Your hightmap is a sampling of some function f on a regular grid. Taking ε=1 you get:
2v = (f(x−1,y) − f(x+1,y), f(x,y−1) − f(x,y+1), 2)
Putting it into code would look like:
// sample the height map:
float fx0 = f(x-1,y), fx1 = f(x+1,y);
float fy0 = f(x,y-1), fy1 = f(x,y+1);
// the spacing of the grid in same units as the height map
float eps = ... ;
// plug into the formulae above:
vec3 n = normalize(vec3((fx0 - fx1)/(2*eps), (fy0 - fy1)/(2*eps), 1));
A common method is using a Sobel filter for a weighted/smooth derivative in each direction.
Start by sampling a 3x3 area of heights around each texel (here, [4] is the pixel we want the normal for).
[6][7][8]
[3][4][5]
[0][1][2]
Then,
//float s[9] contains above samples
vec3 n;
n.x = scale * -(s[2]-s[0]+2*(s[5]-s[3])+s[8]-s[6]);
n.y = scale * -(s[6]-s[0]+2*(s[7]-s[1])+s[8]-s[2]);
n.z = 1.0;
n = normalize(n);
Where scale can be adjusted to match the heightmap real world depth relative to its size.
If you think of each pixel as a vertex rather than a face, you can generate a simple triangular mesh.
+--+--+
|\ |\ |
| \| \|
+--+--+
|\ |\ |
| \| \|
+--+--+
Each vertex has an x and y coordinate corresponding to the x and y of the pixel in the map. The z coordinate is based on the value in the map at that location. Triangles can be generated explicitly or implicitly by their position in the grid.
What you need is the normal at each vertex.
A vertex normal can be computed by taking an area-weighted average of the surface normals for each of the triangles that meet at that point.
If you have a triangle with vertices v0, v1, v2, then you can use a vector cross product (of two vectors that lie on two of the sides of the triangle) to compute a vector in the direction of the normal and scaled proportionally to the area of the triangle.
Vector3 contribution = Cross(v1 - v0, v2 - v1);
Each of your vertices that aren't on the edge will be shared by six triangles. You can loop through those triangles, summing up the contributions, and then normalize the vector sum.
Note: You have to compute the cross products in a consistent way to make sure the normals are all pointing in the same direction. Always pick two sides in the same order (clockwise or counterclockwise). If you mix some of them up, those contributions will be pointing in the opposite direction.
For vertices on the edge, you end up with a shorter loop and a lot of special cases. It's probably easier to create a border around your grid of fake vertices and then compute the normals for the interior ones and discard the fake borders.
for each interior vertex V {
Vector3 sum(0.0, 0.0, 0.0);
for each of the six triangles T that share V {
const Vector3 side1 = T.v1 - T.v0;
const Vector3 side2 = T.v2 - T.v1;
const Vector3 contribution = Cross(side1, side2);
sum += contribution;
}
sum.Normalize();
V.normal = sum;
}
If you need the normal at a particular point on a triangle (other than one of the vertices), you can interpolate by weighing the normals of the three vertices by the barycentric coordinates of your point. This is how graphics rasterizers treat the normal for shading. It allows a triangle mesh to appear like smooth, curved surface rather than a bunch of adjacent flat triangles.
Tip: For your first test, use a perfectly flat grid and make sure all of the computed normals are pointing straight up.

How to plot two equidistant moving points?

Imagine a surface which has got 2 points which are moving over the surface (resulting into various lines and curves) while adhering to the following conditions.
These two points are always and always at a constant C distance from each other.
Each point has it's own velocity and direction vector. Of course both these parameters will be restricted based on condition 1.
Ex. if point 1 has 0 velocity and point 2 is moving it will result into a circle like shape with point one being it's center.
I am unable to express these conditions in programming constructs. Can someone help me with that?
I am using OpenGL but even a pseudo code will do for me.
vec3 center;
while(1):
vec3 centerDirection = ...
center += centerDirection
float angle = ...
vec3 dir(cos(angle), 0, sin(angle))
vec3 p1 = center + (C/2) * dir
vec3 p2 = center - (C/2) * dir
draw p1
draw p2
This is a solution where you move the center of a circle and make sure p1 and p2 are two diametrically opposed points
Another solution :
while 1:
p1 += random
p2 += random
delta = p1-p2
delta.normalize()
p2 = p1 + C * delta
i.e you restrain p2, not both points.
In openGL I achieved is as below
PlotTwoPoints(-SPAN,0,+SPAN,0); //two points on x axis
Then I rotated the co-ordinate system and kept on drawing two points at above two locations.
Simple!