Why do I have to normalize coordinates? - three.js

I see that everybody normalizes his coordinates to be in range of [-1;1]. Why is this done? Is this required? Is this only for ThreeJS , or is it a common thing for every 3D framework?

Three.js is based on WebGL and WebGL is based on OpenGL ES (Embedded System)
In WebGL / OpenGL ES there is a viewport:
2.3 The WebGL Viewport
OpenGL manages a rectangular viewport as part of its state which defines the placement of the rendering results in the drawing buffer. Upon creation of the WebGL context, the viewport is initialized to a rectangle with origin at (0, 0) and width and height equal to (canvas.width, canvas.height).
5.13.4 Viewing and clipping
The viewport specifies the affine transformation of x and y from normalized device coordinates to window coordinates. The size of the drawing buffer is determined by the HTMLCanvasElement. The scissor box defines a rectangle which constrains drawing. When the scissor test is enabled only pixels that lie within the scissor box can be modified by drawing commands. When enabled drawing can only occur inside the intersection of the viewport, canvas area and the scissor box. When the scissor test is not enabled drawing can only occur inside the intersection of the viewport and canvas area.
This means gl.viewport defines the transformation from normalized device coordinates to the viewport rectangle.
Because of that everything which is drawn and should be shown on the viewport, has to be in the normalized device space, which is in the range from (-1,-1,-1) to (1, 1, 1).
Transformation of the geometry to normalized device coordinates:
The geometry is transformed by its model matrix, to world coordinates.
To transform from wolrd coordinates to normaliced device coordinates, Three.js provides the THREE.OrthographicCamera or the THREE.PerspectiveCamera. The camera defines a view matrix and a projection matrix.
The view matrix describes the direction and position from which the scene is looked at. The view matrix transforms from the wolrd space to the view (eye) space. In general world coordinates and view coordinates are Cartesian coordinates.
The projection matrix describes the mapping from 3D points of a scene, to 2D points of the viewport. The projection matrix transforms from view space to the clip space. Clip space coordinates are Homogeneous coordinates. The coordinates in the clip space are transformed to the normalized device coordinates (NDC) in the range (-1, -1, -1) to (1, 1, 1) by dividing with the w component of the clip coordinates.

Related

How to "focus zoom" on a spherical camera?

So, for anyone familiar with Google Maps, when you zoom, it does it around the cursor.
That is to say, the matrix transformation for such a zoom is as simple as:
TST^{-1}*x
Where T is the translation matrix representing the point of focus, S the scale matrix and x is any arbitrary point on the plane.
Now, I want to produce a similar effect with a spherical camera, think sketchfab.
When you zoom in and out, the camera needs to be translated so as to give a similar effect as the 2D zooming in Maps. To be more precise, given a fully composed MVP matrix, there exists a set of parallel planes that are parallel to the camera plane. Among those there exists a unique plane P that also contains the center of the current spherical camera.
Given that plane, there exists a point x, that is the unprojection of the current cursor position onto the camera plane.
If the center of the spherical camera is c then the direction from c to x is d = x - c.
And here's where my challenge comes. Zooming is implemented as just offsetting the camera radially from the center, given a change in zoom Delta, I need to find the translation vector u, colinear with d, that moves the center of the camera towards x, such that I get a similar visual effect as zooming in google maps.
Since I know this is a bit hard to parse I tried to make a diagram:
TL;DR
I want to offset a spherical camera towards the cursor when I zoom, how do i pick my translation vector?

How to you draw a line segment from 3D to 2D in THREE.js?

I am trying to draw a line segment from a point a 3D scene to point on a HUD UI. One end of the line segment is specified in 3D e.g. (1.232, -34.12, 4.21) but the other I want to specify in 2D pixel coordinates e.g. (320, 200).
How can I convert the 2D coordinate to a 3D point and have it remain at those pixel coordinates as the camera (Perspective) moves? Initially I thought of taking the 2D position and projecting it onto the near view frustum maybe that would work, but wasn't sure how to do it or if there was a better way?
var vector = new THREE.Vector3(320, 200, 0.5);
vector.unproject(camera);
will return in vector a 3D point which you can use to draw.
If you keep unprojecting as the perspective camera moves you are guaranteed that the 2D point will seem not to move in your HUD.

How does OpenGL map an image to a quadrilateral?

Image files are rectangular, yet in a 3D environment, a rectangle will appear as an irregular quadrilateral most of the time. Consider the following image (credit to this blog):
Given that:
you already know the four vertices of the green face
you have access to the image file as a 2D array of color values
you are drawing to a screen that is a 2D array of pixels
What is the algorithm that OpenGL uses for drawing the image onto the green face?
The algorithm is basically (if we ignore stuff like shaders for now):
break down the quadrilateral into two triangles
for each triangle, compute the projection onto the image plane
for each screen pixel covered by the projection of the triangle:
compute the texture coordinates by interpolation from the vertices for the position to which the pixel location corresponds on the triangle.
look up the texture image at the location that corresponds to the texture coordinates. Typically, some form of filtering is applied here.
you have found the color for your pixel

Algorithm to create Image Texture from Vertex colors

I know i can go from 3d space to 2d space of the Mesh by getting the corresponding uv coordinates of the vertex.
When i transform to uv space, each vertex will have its color and i can put the color in the pixel position what the uv co-ordinate returns for a particular vertex, but the issue is how do i derive the pixels that lie inbetween them, i want a smooth gradient.
For example, the color value at uv co-ordinate (0.5,0.5)->(u,v) is [30,40,50]->(RGB) and at [0.75,0.75] its [70,80,90] and lets say there are three vertices and theres one more at [0.25.0.6] as [10,20,30], how do i derive the colors that goes on the area these three uv/vertex coordinates fill, i mean the inbetween values for the pixels?
Just draw this mesh on a GPU. You know already that you can replace vertex positions with UVs so you have it represented on the texture space.
Keep your vertex colors unchanged and draw this mesh on your target texture, GPU will do color interpolation for every triangle you draw.
And keep in mind that if two or more triangles share the same texture space then the result will depend on triangle order.

Computing depthmap from 3D reconstruction model

I'm using VisualSfM to build the 3D reconstruction of a scene. Now I want to estimate the depthmap and reproject the image. Any idea on how to do it?
If you have the camera intrinsic matrix K, its position vector in the world C and an orientation matrix R that rotates from world space to camera space, you can iterate over all pixels x,y in your image and perform:
Then, find using ray tracing, the minimal t that causes the ray to intersect with your 3D model (assuming it's dense, otherwise interpolate it), so that P lies on your model. The t value you found is then the pixel value of the depth map (perhaps normalized to some range).

Resources