Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I'd like to add texture to a Cylinder inside Graphics3D. I can't see how to use FaceForm and tell it to use Texture. The problem is Texture needs TextureCoordinateFunction.

I saw few solutions, but many use ParametricPlot3D, which I could use, but I need a solid Cylinder, so I would have to do the top/bottom faces manually. For example, using the solution in Applying an ArrayPlot as a texture to the surface of a cylinder I could do

mplt = MatrixPlot[Table[Sin[x y/100], {x, -10, 10}, {y, -10, 10}], 
   ColorFunction -> "Rainbow", Frame -> False, ImagePadding -> 0, 
   PlotRangePadding -> 0];
p = ParametricPlot3D[{ Cos[theta], Sin[theta], rho}, {theta, -Pi, Pi}, {rho, 0, 3}, 
   PlotStyle -> Directive[Specularity[White, 30], Texture[mplt]], 
   TextureCoordinateFunction -> ({#1, #3} &), Lighting -> "Neutral", 
   Mesh -> None, PlotRange -> All, TextureCoordinateScaling -> True];

Graphics3D[First@p]

Mathematica graphics

But what I want is to add texture to outside surface of

  Graphics3D[Cylinder[{{0, 0, 0}, {0, 0, 3}}, 1], Axes -> True]

Mathematica graphics

There is solution here for 2D objects How to texturize a Disk/Circle/Rectangle? since one can find the VertexTextureCoordinates are easy to do for these.

I think what is needed here is to tell FaceForm to use Texture? but do not know how to go about this. Version 9.01

share|improve this question
1  
I'd do Graphics3D[{First@p, Cylinder[{{0, 0, 0}, {0, 0, 3}}, .99]}, Axes -> True] –  Kuba Jul 9 at 6:19
    
@Kuba I actually thought about this, but the top/bottom faces will be different, and more important, I am not sure it is efficient, since I am rendering a 3D object (cylinder) in addition to the texture itself. I am trying to see if I can make a circle with same texture and add these to the ParametricPlot3D to build the cylinder manually. If all else fails, will use what you suggested. –  Nasser Jul 9 at 6:28

1 Answer 1

up vote 9 down vote accepted

In general, I don't think it's possible to use Texture directly with the built-in primitives such as Sphere and Cylinder. See also Texture mapping and resizing a sphere primitive in Mathematica.

So you have to write your own replacement for those primitives. Since you specifically mentioned the Cylinder, I added the ability to handle Texture to my answer here. There, I already had added VertexNormals to give the smooth appearance that the Cylinder primitive has. Here, I inserted the VertexTextureCoordinates option into all the polygons making up the sides of my custom cylinder. The result is the following:

ClearAll[prism];
prism[pts_List, h_] := 
 Module[{bottoms, tops, surfacePoints, sidePoints, n}, 
  surfacePoints = 
   Table[Map[PadRight[#, 3, height] &, pts], {height, {0, h}}];
  {bottoms, tops} = {Most[#], Rest[#]} &@surfacePoints;
  sidePoints = 
   Flatten[{bottoms, RotateLeft[bottoms, {0, 1}], 
     RotateLeft[tops, {0, 1}], tops}, {{2, 3}, {1}}];
  n = Length[sidePoints];
  MapThread[
   Polygon[#1, VertexNormals -> (#1 - #2), 
     VertexTextureCoordinates -> #3] &, {
    Join[sidePoints, surfacePoints], 
    Join[Map[{0, 0, 1} # &, sidePoints, {2}], 
     Map[({1, 1, 0} # - {0, 0, h/2}) &, surfacePoints, {2}]
     ],
    Join[
     Table[{{i/n, 0}, {(i + 1)/n, 0}, {(i + 1)/n, 1}, {i/n, 1}}, {i, 
       0, n - 1}],
     Table[None, {Length[surfacePoints]}]]
    }
   ]]

Clear[cyl];
cyl[{pt1_, pt2_}, r_: 1, n_: 90] := 
 Module[{circle = 
    r Table[{Cos[\[Phi]], Sin[\[Phi]]}, {\[Phi], Pi/n, 2 Pi, Pi/n}], 
   h = EuclideanDistance[pt1, pt2]}, 
  GeometricTransformation[prism[circle, h], 
   Composition[TranslationTransform[pt1], 
    Quiet[Check[RotationTransform[{{0, 0, 1.}, pt2 - pt1}], 
      Identity]]]]]

The actual work is done in prism, and the compatibility with Cylinder is provided by the wrapper cyl. Here is a test:

img = ExampleData[{"TestImage", "Lena"}];

Graphics3D[{Texture[img], EdgeForm[], 
  cyl[{{0, 0, 0}, {0, 0, 2 Pi}}, 1]}, Boxed -> False]

lenaTube

To get the smoothness of the surface, it's good to set the proper VertexNormals as I do in the prism function.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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