3
$\begingroup$

By manually adjusting the coefficients inside TextureCoordinateFunction I can get the numbers on each ball to sort of face the camera:

Graphics3D[{
  [email protected], Blue, Cuboid[{-2, -2, -2}, {2, 2, 0}],
  Opacity@1, Sequence @@ MapThread[
    Translate[
      SphericalPlot3D[#3, {theta, 0, Pi}, {phi, 0, 2 Pi}, 
        Mesh -> None, 
        TextureCoordinateFunction -> ({#1, 0.3*#2 + 0.7*#3} &), 
        PlotStyle -> 
         Texture[Show@
           Graphics@Text@Style[ToString@#1, 100]]][[1]], #2] &, {{8, 
      5, 13, 3},
     {{-1, -1, 0}, {-1, 1, 0}, {1, -1, 0}, {1, 1, 0}}, {0.2, 0.4, 0.4,
       0.2}}]
  }, Boxed -> False, ViewPoint -> {-5, -9, 3}, 
 ViewVertical -> {0, 0, 1}, PreserveImageOptions -> False]

enter image description here

How can I script the coordinates inside TextureCoordinateFunction so the numbers are facing the ViewPoint, while preserving the orientation of the cube?

The solution from Viewing a city's coordinates from above doesn't take into account that I also want to see the cube from a particular perspective.

Update: this almost works: (But how to preserve the shape of the letter? I can't get it to work with slots 1-3 of the TextureCoordinateFunction.)

With[{viewpoint = {-5, -9, 3}}, Graphics3D[{
   [email protected], Blue, Cuboid[{-2, -2, -2}, {2, 2, 0}],
   Opacity@1, Sequence @@ MapThread[
     With[{textpos = 
         CoordinateTransform[ "Cartesian" -> "Spherical", 
            Normalize[#2 - viewpoint]][[2 ;; 3]]/\[Pi]},
       Translate[
        SphericalPlot3D[#3, {theta, 0, Pi}, {phi, 0, 2 Pi}, 
          Mesh -> None, 
          TextureCoordinateFunction -> ({(#4 - textpos[[1]] - 
                0.2), (#5 - textpos[[2]] + 0.15)} &), 
          PlotStyle -> 
           Texture[
            Rotate[Show@Graphics@Text@Style[ToString@#1, 100], 
             90 Degree]]][[1]], #2]] &, {
      {8, 5, 13, 3},
      {{-1, -1, 0}, {-1, 1, 0}, {1, -1, 0}, {1, 1, 0}},
      {0.2, 0.4, 0.4, 0.2}
      }]
   }, Boxed -> False, ViewPoint -> viewpoint, 
  ViewVertical -> {0, 0, 1}, PreserveImageOptions -> False]]

enter image description here

$\endgroup$
0

1 Answer 1

3
$\begingroup$

A possible approach is to use Text as Graphics3D primitive (it is automatically re-oriented to face the viewer and it is not blocked by other primitives):

Graphics3D[{[email protected], Blue, Cuboid[{-2, -2, -2}, {2, 2, 0}], 
  Opacity@1, Sequence @@ 
   MapThread[Translate[
    {SphericalPlot3D[#3, {theta, 0, Pi}, {phi, 0, 2 Pi}, Mesh -> None][[1]], 
     Text[Style[ToString@#1, Black, FontSize -> Scaled[#3/8]]]}, #2] &,
   {{8, 5, 13, 3}, {{-1, -1, 0}, {-1, 1, 0}, {1, -1, 0}, {1, 1, 0}}, 
    {0.2, 0.4, 0.4, 0.2}}]}, 
 Boxed -> False, ViewPoint -> {-5, -9, 3}, 
 ViewVertical -> {0, 0, 1}, PreserveImageOptions -> False]

enter image description here

$\endgroup$
3
  • $\begingroup$ This is great, but it doesn't preserve the wrapping of the numbers on each ball. Is Text in Graphics3D just pasting a 2D letter on top, or actually mapping it to the surface? I tried looking at the GraphicsComplex of your output and it's not clear to me what's going on, it does seem to be converting TextureCoordinateFunction into VertexTextureCoordinates which gives me some idea maybe it is actually keeping track of the 3D positions to render each number. If so, I think it should be possible to simply plug that into the TextureCoordinateFunction instead to get the desired result? $\endgroup$ Commented Apr 10, 2020 at 8:27
  • $\begingroup$ @ninemileskid, Re "Is Text in Graphics3D just pasting a 2D letter on top, or actually mapping it to the surface?", it is the former. $\endgroup$
    – kglr
    Commented Apr 10, 2020 at 8:37
  • $\begingroup$ Well, fiddlesticks. $\endgroup$ Commented Apr 10, 2020 at 10:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.