Given a mesh, I want to assign each triangle a color.

I tried to do it in this way:

MeshVertices[mesh_] := First@Cases[mesh, GraphicsComplex[x_, __] :> x, Infinity]

MeshFaces[mesh_] := Block[{faces},
    faces = Cases[mesh, Polygon[x_, ___] :> x, Infinity];
    If [faces == {}, 
        faces = Cases[mesh, Triangle[x_, ___] :> x, Infinity];
    If [faces == {}, {}, First@faces]

bunny = ExampleData[{"Geometry3D", "StanfordBunny"}];

faces = MeshFaces[bunny];
nFaces = Length[faces];
faceColors = RGBColor[#, 0.0, 0.0] & /@ (Range[nFaces] / (0.0 + nFaces));

vertices = MeshVertices[bunny];
coloredBunny = Graphics3D[
        Thread[{faceColors, Triangle /@ faces}]
    Boxed -> False

The rendering was quite slow, and the result was not what I wanted:

Colored Bunny

Are there any ways to color the bunny? Thank you.

  • $\begingroup$ One quick fix is to insert and EdgeForm[None] into your graphics expression to get rid of the many black edges. You can get polygon data also directly: bunny = ExampleData[{"Geometry3D", "StanfordBunny"}, "PolygonObjects"]; {EdgeForm[None], Red, bunny} // Graphics3D $\endgroup$
    – Yves Klett
    Commented May 19, 2016 at 8:02
  • $\begingroup$ @YvesKlett This also works! Thank you. $\endgroup$
    – Purboo
    Commented May 19, 2016 at 8:38
  • $\begingroup$ BTW the slow rendering is due to the less efficient rendering of many individual polygons as compared to the much more efficient GraphicsComplex. $\endgroup$
    – Yves Klett
    Commented May 19, 2016 at 8:41

2 Answers 2


There are 69,451 different polygons in the bunny, so that is why it takes so long to plot, so let's use a simpler example with only ~1,400 polygons:

MeshVertices[mesh_] := 
 First@Cases[mesh, GraphicsComplex[x_, __] :> x, Infinity]
MeshFaces[mesh_] := 
   faces = Cases[mesh, Polygon[x_, ___] :> x, Infinity];
   If[faces == {}, 
    faces = Cases[mesh, Triangle[x_, ___] :> x, Infinity];];
   If[faces == {}, {}, First@faces]];
donut = ParametricPlot3D[{(3 + Cos[v]) Cos[u], (3 + Cos[v]) Sin[u], 
    Sin[v]}, {u, 0, 2 Pi}, {v, 0, 2 Pi}, Mesh -> None];
faces = MeshFaces[donut];
nFaces = Length[faces];
faceColors = RGBColor[#, 0.0, 0.0] & /@ Rest[Subdivide[1.0, nFaces]];
vertices = MeshVertices[donut];

When you run your code, it places a black border around every triangle. Compare these

Graphics3D /@ {Triangle[{{0, 0, 0}, {1, 0, 0}, {0, 1, 
     1}}], {EdgeForm[], Triangle[{{0, 0, 0}, {1, 0, 0}, {0, 1, 1}}]}}

two triangles

So you need to turn off the EdgeForm[] in your final line,

coloredDonut = 
   Thread[{faceColors, {EdgeForm[], Polygon[#]} & /@ faces}]], 
  Boxed -> False]

red donut

Here is what it looks like with the borders:

red donut with borders

When you apply this to your bunny, here is the result:

colored bunny

By the way, here is slightly shorter code that produces the exact same result,

bunny = ExampleData[{"Geometry3D", "StanfordBunny"}];
colors = RGBColor[#, 0.0, 0.0] & /@ 
    Length[Cases[Normal@bunny, Polygon[__], Infinity]]];
i = 1;
Normal[bunny] /. {Polygon[a__] :> 
   Sequence[i++; colors[[i]], Polygon[a]]}

The above code with replacement rule should work on many Graphics3D objects, like the donut above. But in that case it is necessary to adjust the lighting by adding another replacement rule HoldPattern[Lighting -> {__}] :> Lighting -> {{"Ambient", Red}}

But since you are working on a ExampleData["Geometry3D"] object, you can get the polygons as a list directly and then just use Thread to combine them with colors. Thanks to Yves Klett for pointing this out

With[{pgons = 
   ExampleData[{"Geometry3D", "UtahVWBug"}, "PolygonObjects"]}, 
   Thread[{RGBColor[#, 0.0, 0.0] & /@ 
      Subdivide[1.0, Length@pgons - 1], pgons}]}, Boxed -> False]

red Volkswagen

Or a one-liner to give a psychedelic bunny

Normal[ExampleData[{"Geometry3D", "StanfordBunny"}]] /. {Polygon[
    a__] :> Sequence[RandomColor[], Polygon[a]]}

psychedelic bunny

  • $\begingroup$ Awesome! Thank you! $\endgroup$
    – Purboo
    Commented May 19, 2016 at 8:37
  • 1
    $\begingroup$ Jason, what about getting the polygon data directly: ExampleData[{"Geometry3D", "StanfordBunny"}, "PolygonObjects"]? $\endgroup$
    – Yves Klett
    Commented May 19, 2016 at 8:39
  • $\begingroup$ @YvesKlett - that does make for a shorter code, I hadn't thought of it (and then when I saw your comment I didn't want to take it in case you wanted to use it) $\endgroup$
    – Jason B.
    Commented May 19, 2016 at 8:45
  • 2
    $\begingroup$ Na, your answer is so nice already, please feel free to include if it makes sense to you :D Actually, your psycho bunny reminds me of my oneliner cow, although that one uses VertexColors. $\endgroup$
    – Yves Klett
    Commented May 19, 2016 at 8:49
  • $\begingroup$ That cow is great! I wasn't really aware of the ExampleData["Geometry3D"] stuff before $\endgroup$
    – Jason B.
    Commented May 19, 2016 at 9:14

Jason already said a lot of what I wanted to say, so I'll just offer this little snippet that avoids Normal[] chicanery:

gc = ExampleData[{"Geometry3D", "StanfordBunny"}, "GraphicsComplex"];
Graphics3D[Insert[gc, EdgeForm[], {2, 1}] /. Polygon[m_?MatrixQ] :> 
           Riffle[Table[RandomColor[], {Length[m]}], Polygon /@ m]]

one crazily colored bunny

Just for variety, here's another method for coloring the bunny. Recall that GraphicsComplex[] takes a VertexColors option to specify how the polygons within should be colored. (Line[] objects are not affected by this, which may or may not be wanted in an application.) Thus,

(* some color function that takes a point as an argument *)
woody[pt_?VectorQ] := Blend[{RGBColor[3/4, 22/41, 1/3], RGBColor[1/2, 2/9, 7/38]}, 
                            Haversine[π SawtoothWave[50 EuclideanDistance[pt,
              {0.08, 0.06, 0.08}]]]]

Graphics3D[Insert[gc, EdgeForm[], {2, 1}] /. 
           gc : GraphicsComplex[pts_, rest___] :> 
           Append[gc, VertexColors -> (woody /@ pts)], Lighting -> "Neutral"]

wavy bunny

  • 1
    $\begingroup$ ...and as much as I'm averse to self-promotion: noisy bunnies $\endgroup$ Commented May 19, 2016 at 9:32
  • $\begingroup$ What do you have against Normal? GraphicsComplexes are great for the system I'm sure, but they're a pain to work with sometimes $\endgroup$
    – Jason B.
    Commented May 19, 2016 at 10:03
  • $\begingroup$ Jason, "user21" and me mentioned some of the reasons in this thread; that being said, a number of my previous Gravatars needed the services of Normal[] at some point, and I agree that GraphicsComplex[] can be difficult to manipulate for sufficiently intricate operations. $\endgroup$ Commented May 19, 2016 at 11:53
  • $\begingroup$ lol, user21 didn't used to have such a mysterious username I see.... And I can see the benefit now that it's pointed out $\endgroup$
    – Jason B.
    Commented May 19, 2016 at 11:55

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.