3
$\begingroup$

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

Graphics3D[{
  Opacity@0.5, 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[{
   Opacity@0.5, 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
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[{Opacity@0.5, 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$ Apr 10 '20 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
    Apr 10 '20 at 8:37
  • $\begingroup$ Well, fiddlesticks. $\endgroup$ Apr 10 '20 at 10:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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