10
$\begingroup$

There are a few posts on this theme:

How to make a 3D globe?

How to render a 3D tubular graphics from a 2D image path

How to extrude a 3D image from a binary 2D image

However I can't quite piece them together. I am looking to take a 2D image wrapped on a 3D surface and protrude the markings.

For example: Given an image such as

enter image description here

and wrap around an ellipsoid protrude the lines and circles such that half a sphere is present enter image description here

It would be ideal for the text to be clearly visible as well. EDIT If the text could be engraved that would be amazing!

Thanks if anyone fancies having a go! :)

$\endgroup$
3
  • $\begingroup$ Can you show an example of something similar for clarity? I'm not sure how to interprete "half a sphere is present". $\endgroup$
    – Kuba
    Commented Jun 17, 2018 at 8:49
  • $\begingroup$ @Kuba I interpret it as the outer surface of a half-sphere: Plot3D[Sqrt[1 - x^2 - y^2], {x, -1, 1}, {y, -1, 1}, Mesh -> None, BoxRatios -> {1, 1, 1/2}], i.e. one hemisphere is mapped onto the circular plot from the OP. $\endgroup$
    – corey979
    Commented Jun 17, 2018 at 10:11
  • $\begingroup$ Apologies for the confusion @Kuba I would like to wrap the first image around a 3D shape and protrude each dot/pixel/star - ideally with the shapes still overlapping. As in i.sstatic.net/XfQi6.png $\endgroup$
    – Teabelly
    Commented Jun 17, 2018 at 18:55

1 Answer 1

8
+150
$\begingroup$

I'm absolutely unsure if I got right what you want, but I'll give it a try.

enter image description here

The general steps are the fowllowing:

  1. Take your image (which is of too low quality for a good texture) and create from it a gray-image that you can use as bump-map. Bright spots are higher and black is flat. Additionally, we use the original image as texture
  2. Create an interpolation function from the pixel-data of the bump-map where you take care that it does the transformation from image coordinates to ellipsoid parameters
  3. Create a custom parametric function for the ellipsoid that includes the bump-map that can be scaled with a factor. When the factor is zero, it would give a normal ellipsoid and the higher the factor, the more visible the bumps get.
  4. Use ParametricPlot3D to plot your custom ellipsoid and use your image as a texture.

Most of the fiddling is to get the coordinate-system of interpolating function and the texture right and I didn't try hard to clean this up. First, I import your image and I use a combination of the brightness and the saturation channel as bump-map. Additionally, I smooth the bump-map a bit to prevent pixel artifacts.

img = Import["https://i.sstatic.net/m7YSX.png"];
{h, s, b} = ColorSeparate[img, "HSB"];
height = GaussianFilter[
   ImageData[ImageAdjust[ImageAdd[s, ColorNegate[b]]], "Real"], 2];
Image[height]

Mathematica graphics

Now we turn the height data into a function that can be used with the parametric form of an ellipsoid. The transformations are necessary because you probably want the center of the image at one end of the ellipse.

With[{ip = 
   ListInterpolation[height, {{-Pi/2, Pi/2}, {-Pi/2, Pi/2}}]},
 bumpMap[theta_?NumericQ, phi_?NumericQ] := 
  ip @@ ((Pi/2 - theta)*{Cos[phi], Sin[phi]}) /; 0 <= theta <= Pi/2 && 0 <= phi <= 2 Pi;
 bumpMap[___] := 0.0
 ]

The parametric function of the ellipsoid takes the two angles and the ratios a, b, and c as defined on the wiki page. In addition, we make the bump-map stick out normal to the surface of the ellipsoid.

ellipsiod[theta_, phi_, a_, b_, c_, factor_] := 
 With[{pt = {a Cos[theta]*Cos[phi], b Cos[theta] Sin[phi], 
     c Sin[theta]}},
  pt + bumpMap[theta, phi]*factor*pt/Norm[pt]
]

Finally, you can make a parametric plot and grab a tea in the meantime because this takes long if you want a bit of quality

ParametricPlot3D[
  ellipsiod[theta, phi, 1, 1, 2, 0.07],  {theta, 0, Pi/2}, {phi, 0, 2 Pi}, 
  PlotPoints -> 100,
  MaxRecursion -> 5, 
  PlotStyle -> Texture[img], 
  TextureCoordinateFunction -> 
    Function[{x, y, z, u, v}, ((Pi/2 - u)/(Pi))*{Cos[v - Pi/2], Sin[v - Pi/2]} + 1/2],
  TextureCoordinateScaling -> False, Mesh -> None, Ticks -> None, 
  Lighting -> "Neutral"
]
$\endgroup$
2
  • $\begingroup$ Spot on! Thanks a lot for taking the time to explain the steps, niceone. Any estimate on time taken for final step? $\endgroup$
    – Teabelly
    Commented Jun 21, 2018 at 22:06
  • 1
    $\begingroup$ @AwkwardPanda Some minutes on my machine. You can tune down MaxRecursion to 0 and PlotPoints to 50 and you'll note that you need much more resolution to see the small details. $\endgroup$
    – halirutan
    Commented Jun 21, 2018 at 22:20

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.