threejs - raycasting reports wrong faceIndex when picking a face - three.js

threejs - raycasting reports wrong faceIndex when picking a face
I want to pick a face in a mesh when clicking on it with the mouse.
The mesh is loaded using ObjLoader and MtlLoader (attached)
When hovering on the mesh, the intersection is detected correctly, but the reported faceIndex does not match the face index in the .obj file
(as well as the vertices of the reported face)
For example,
face 0 (f 3/1 1/1 10/1) - has vertices 3,1,10
when hovering on it in the object file, console.log(intersects[0]); reports: "faceIndex: 0" and "face: Ya {a: 0, b: 1, c: 2, ...}"
face 1 (f 3/1 10/1 7/1) - has vertices 3,10,7
when hovering on it in the object file, console.log(intersects[0]); reports: "faceIndex: 3" and "face: Ya {a: 3, b: 4, c: 5, ...}"
face 3 (f 2/2 4/3 8/4) - has vertices 2,4,8
when hovering on it in the object file, console.log(intersects[0]); reports: "faceIndex: 9" and "face: Ya {a: 9, b: 10, c: 11, ...}"
Attached here is a small self-contained example that is based on webgl_interactive_cubes.html and the .obj file.
It looks like the faceIndex is the face index (location) in the .obj file multiplied by 3.
Can anyone tell what is the rational for this, and is this the correct way to map the reported faceIndex to a face in the .obj file?
Thanks,
Avner

Related

Transform matrix, convert one triangle to another: missing last step

I am trying to get the transform matrix from one triangle to another. I am principally concerned about 2D. We will see for 3D later (but open to solutions).
I was reading this answer.
Now please correct me: if my first equilateral triangle, with sides of length 1, has its leftmost point located at the origin, its transform should be the identity matrix.
So, reading the solution above, the transform matrix I am looking for, should be triangle B matrix * inv(Identity) == B matrix.
I cannot wrap my head around that, because it seems wrong. In the given image, I want to transform blue to red, with blue having one point at the origin. The selected point of transform for the red triangle is always the closest to the origin.
The last missing image is the last transform merging Blue as Red (same triangle).
I am using Eigen (c++) for my transforms and calculation already.
Questions:
What info did I miss in the process?
What is the real transform matrix given those constraints?
Thanks
The inverted matrix is generated from the triangle you are translating from, not the destination. I've made a fiddle that demonstrates this here: https://jsfiddle.net/dwch1tju/
Let's say your first triangle has points at [0,0] [0.5,sin(60)] and [1,0] and the second triangle has points at [1.1,0.7] [0.9,1.9] and [1,0]. Then the triangle matrices are:
[[0, 0.5, 1],[0, 0.866, 0], [1, 1, 1]]
[[1.1, 0.9, 2.3], [0.7, 1.9, 0.6], [1, 1, 1]]
Demonstrated by:
const triangleMatrixA = createTriangleMatrix(triangleA);
const triangleMatrixB = createTriangleMatrix(triangleB);
Which creates a transform of
[[0.88, 0.56, -1.36], [0.07, 0.85, -0.67], [0, 0, 1]]
Demonstrated by:
const invertedMatrixB = invertMatrix(triangleMatrixB);
const multiplied = multiplyMatricies(triangleMatrixA, invertedMatrixB)
The fiddle then uses the transform on the three points in the second triangle, to show that they become the points of the first tringle in these lines:
const translatedA = multiplyPointByMatrix(multiplied, triangleB.a);
const translatedB = multiplyPointByMatrix(multiplied, triangleB.b);
const translatedC = multiplyPointByMatrix(multiplied, triangleB.c);
The first generated image in the fiddle shows the original location of the triangles and the second image shows that the translated points place the triangles in the same location.
The answer you link is not inverting a transform. It is inverting a triangle matrix that contains the coordinates of the triangle, then multiplying it by the other triangle matrix to create a transform.

ThreeJS: PlaneBufferGeometry, raycasting and faces

Made a buffered plane, set its vertices with:
var vertices = tg.attributes.position.array;
geometry.addAttribute('position', new THREE.BufferAttribute(vertices, 3));
Now i want to raycast to a face to get it's Z value:
var z = intersects[i].object.geometry.vertices[intersects[i].face.a].z;
This worked on a standard geometry as it had faces and lot of other things i'm trying to save from memory.
My question comes from the index: intersects[i].face.a. What do i have to add? There seem not to be a method to add "faces" to the buffered geometry. Right now there is just one face for the whole geometry at:
object.face.(a,b,c)
Perhaps there is another way of clicking on a face and getting it's vertex value when using buffered geoms.
Tips? Thanks!
Buffer geometries contain attributes of positions in an array.
If you want to obtain information about z-value of a specific vertex from a buffer geometry's vertices then you can do it like this:
intersects[i].object.geometry.attributes.position.array[intersects[i].face.a * 3 + 2]
also you can use the z-coordinate of the point of intersection (which is in world's coordinates):
intersects[i].point.z;
jsfiddle example (see function showDetails(intersect), the green plane is THREE.PlaneGeometry, the blue plane is THREE.PlaneBufferGeometry)

How to draw a line with changing intensity/grayscale

If I have matrix/data with line intensity values:
e.g.
0, 1, 2, 3, 4, 5, ..... M (where intensity value is gradually changing)
or
any random order of values
So if I use the first intensity set of data, (0, 1, 2, 3, 4, 5, ..... M), my line color should be gradually turning black to white. If I remember correctly, 0 is used to represent black and 255 is used to represent white? I would like to use a data of intensity values to draw 3D line with changing color/intensity.
How can I draw a 3D line with changing intensity/grayscale? I would appreciate any advice or recommendation.
You can use the 3D colored line plot tool from the file exchange and change the colormap to whatever you need.

Viewing a city's coordinates from above

As a little project I've been thinking to create a little Google Earth-like animation. I want to play back a timeline while rotating the globe to center over various cities. At present I can use the default view settings to render a globe with the cities indicated by points.
When I try to orient the camera with a view vector looking down on a city (for example Denver), I end up with the following:
The ViewVector needs to be computed for some point out in space above the globe. However my trial and error has not arrived on any sort of coherent viewpoint with most looking like they're "inside" the globe.
What I need help with is a function which given the latitude and longitude of a city choses a ViewVector placing the city at the "center" of the camera view. The code which produced the "inside the globe" view follows:
SC[{lat_, lon_}] := {Cos[lon \[Degree]] Cos[lat \[Degree]],
Sin[lon \[Degree]] Cos[lat \[Degree]], Sin[lat \[Degree]]};
Graphics3D[{
Opacity[0.75],
Sphere[{0, 0, 0}, 0.99 ],
Map[Line[
Map[SC,
CountryData[#, "SchematicCoordinates"], {-2}]] &,
CountryData["Countries"]], {Yellow, PointSize[Medium],
Point[SC[CityData["Denver", "Coordinates"]]]
}
},
Boxed -> False,
SphericalRegion -> True,
ViewVector -> {{0, 0, 0}, SC[CityData["Denver", "Coordinates"]]}
]
When using ViewVector in the form ViewVector->{v1, v2}, the camera is sitting in point v1 and is pointed in the direction of v2. So in your example, the camera would be sitting in the origin and is pointed in the direction of Denver, which produces the "inside globe" view. To have the camera looking down at Denver the camera should be sitting in a point directly above the city, e.g. in 2 SC[CityData["Denver", "Coordinates"] and be pointed at the origin, so ViewVector would be something like
ViewVector -> {2 SC[CityData["Denver", "Coordinates"]], {0, 0, 0}}
With this setting for ViewVector the view becomes something like

Mathematica: Help me understand Mathematica 3D coordinates system

I gave up trying to understand Mathematica 3D axes configuration.
When I make 3D plot, and label the 3 axes to identify which axes is which, and then make points on these axes, the points appear on different axes than what I expect them to show at using the Point command, which takes {x,y,z} coordinates.
Here is an example
g=Graphics3D[
{
{PointSize[0],Point[{0,0,0}]}
},
AxesOrigin->{0,0,0}, PlotRange->{{-3,3},{-3,3},{-3,3}},
Axes->True, AxesLabel->{"X","Y","Z"},
LabelStyle->Directive[Bold,Red,16],
PreserveImageOptions->False, Ticks->None,Boxed->False]
The above results in
So, now I added a point at at end of the x-axis, and at the end of the y-axis, and at the end of the z-axis. I make each point different color to help identify them on the plot.
g=Graphics3D[
{
{Red,PointSize[.03],Point[{3,0,0}]},
{Black,PointSize[.03],Point[{0,3,0}]},
{Blue,PointSize[.03],Point[{0,0,3}]}
},
AxesOrigin->{0,0,0},PlotRange->{{-3,3},{-3,3},{-3,3}},
Axes->True,AxesLabel->{"X","Y","Z"},
LabelStyle->Directive[Bold,Red,16],PreserveImageOptions->False,
Ticks->None,Boxed->False]
The result is this:
You can see, the RED point, which I expected it to go to end of the x-axis, shows up at the end of the Z axis. And the Black point, instead of showing up at the end of the Y-axis, shows up at X-axis, and the blue point, instead of showing at the end of the Z axis, shows up at the end of the Y-axis.
May be the labels are wrong? May be I am looking at the image in wrong way?
I am really confused, as I am clearly not understanding something. I looked at documentation, and I could not find something to help me see what I am doing wrong. I am just starting to learn Mathematica 3D graphics.
EDIT:
add image with Ticks on it, reply to Simon, I did not know how to do it the comment box:
g=Graphics3D[
{
Cuboid[{-.1,-.1,-.1},{.1,.1,.1}],
{Red,PointSize[.03],Point[{2,0,0}]},
{Black,PointSize[.03],Point[{0,2,0}]},
{Blue,PointSize[.03],Point[{0,0,2}]}
},
AxesOrigin->{0,0,0},
PlotRange->{{-2,2},{-2,2},{-2,2}},
Axes->True,
AxesLabel->{"X","Y","Z"},
LabelStyle->Directive[Bold,Red,16],
PreserveImageOptions->False,
Ticks->True, TicksStyle->Directive[Black,8],
Boxed->False
]
here is the result:
EDIT: OK, I decided to forget about using AxesLabels, and I put them myself . Much more clear now
m=3;
labels={Text[Style["X",16],{1.2 m,0,0}],Text[Style["Y",16],{0,1.2 m,0}],
Text[Style["Z",16],{0,0,1.2 m}]};
g=Graphics3D[
{
{Red,PointSize[.03],Point[{m,0,0}]},
{Black,PointSize[.03],Point[{0,m,0}]},
{Blue,PointSize[.03],Point[{0,0,m}]},
labels
},
AxesOrigin->{0,0,0},
PlotRange->{{-m,m},{-m,m},{-m,m}},
Axes->True,
AxesLabel->None,
LabelStyle->Directive[Bold,Red,16],
PreserveImageOptions->False,
Ticks->True, TicksStyle->Directive[Black,8],
Boxed->False
]
I agree with you that AxesLabel for 3D graphics is next to worthless. Look at the effects of a small interactive viewpoint change on your figure:
IMHO WRI should really improve the operation of this option, and preferably provide some more placement control too (end/mid of axes etc.).
I believe the labels are being placed in unintuitive spots. Replacing your dots with colored lines of different length is clearer to me. I've also removed the explicit plot range which helps Mathematica put the labels in much clearer places.
g=Graphics3D[
{
{Red,Thick, Line[{{0, 0, 0}, {1, 0, 0}}]},
{Black,Thick, Line[{{0, 0, 0}, {0, 2, 0}}]},
{Blue,Thick, Line[{{0, 0, 0}, {0, 0, 3}}]}
},
AxesOrigin->{0,0,0},
Axes->True,AxesLabel->{"X","Y","Z"},
LabelStyle->Directive[Bold,Red,16],PreserveImageOptions->False,
Ticks->None,Boxed->False]

Resources