Group Abstract Group Abstract

Message Boards Message Boards

How do I place a texture on an irregular 3D model?

Just a note: I posted the same question on stackexchange but I haven't been able to find a workable solution.

I'm trying to reproduce a textured head in Mathematica, and I'm using a kind of 'net' of a head which contains all the features on the face. The texture looks like this:

which is supposed to look something like this:

Here's the code I'm using:
ListSurfacePlot3D[Import["inputImage.obj", "VertexData"],
PlotStyle -> Texture[texture], Mesh -> None, MaxPlotPoints -> 80,
TextureCoordinateFunction -> ({#1, -#2, #3} &)]

which produces

Another problem is that the texture is reflected about the origin (ie the face is plastered on the back of the head as well). It should instead be black on the back of the head mesh. I suppose this is suppose to do with the head being centered at the origin. I also need to have the texture to 'follow' the head when I change the coordinates of the mesh later on.

I have attempted using
   Polygon[polygon, VertexTextureCoordinates -> mesh]]}]
which gives me

I need to be able to reproduce this in Mathematica as I have some coordinate transformations which I need to apply, and thereafter, 'wrap' the mesh with the texture. Are these possible?

The link to the model is located at if anyone needs it.

One of the commenters said this:  

The problem is that the mesh in the OBJ file comes equipped with texture coordinates, but Mathematica throws them away when importing it. Thus it is not possible to correctly map the texture on the imported mesh, unless you write your own OBJ parser that retains the texture coordinates. Fortunately the OBJ file format is quite easy to parse, but someone with more free time than me should do it.

Does anyone know if this is doable in Mathematica?

EDIT: I've tried converting the OBJ to PLY and I did this
Import["inputImage.ply", "UserExtensions"][[2]]
Import["inputImage.ply", "UserExtensions"][[3]]

which gave an output of
"texture_u" -> {..}
"texture_v" -> {..}

where .. was a bunch of numbers which had a Length of 3066 for both. My guess was that these are texture coordinates (where u is horizontal and v is vertical).

I attempted to create a list of coordinates from these two list in the following manner
texturecoord = {Import["inputImage.ply", "UserExtensions"][[2]][[2]],
   Import["inputImage.ply", "UserExtensions"][[3]][[2]]} // Transpose

Then, I tried doing
   Polygon[polygon, VertexTextureCoordinates -> mesh]]}]
But that gives me this

POSTED BY: Kenneth Ho
2 years ago
Kenneth could you attache your model as a file to your post please?
POSTED BY: Moderation Team
1 year ago

Here is a basic OBJ parser that should do as you request, per Rahul Narain's suggestions. Replace "inputImage.obj" and "inputImage_tex.jpeg" as necessary.

t = Import["inputImage.obj", "text"]; 
tex = Import["inputImage_tex.jpeg"];
Clear[x, y, z];
v =
  {ToExpression[#[[1]]], ToExpression[#[[2]]], 
     ToExpression[#[[3]]]} & /@ (StringCases[t, 
       "v " ~~ x__ ~~ " " ~~ y__ ~~ " " ~~ z__ ~~ EndOfLine] -> {x, y,
vt = {ToExpression[#[[1]]], ToExpression[#[[2]]]} & /@ (StringCases[t,
      Shortest["vt " ~~ x__ ~~ " " ~~ y__ ~~ EndOfLine] -> {x, y}]);
f = {ToExpression[#[[1]]], ToExpression[#[[2]]], 
     ToExpression[#[[3]]]} & /@ (StringCases[t, 
       "f " ~~ x__ ~~ "/" ~~ a__ ~~ " " ~~ y__ ~~ "/" ~~ b__ ~~ " " ~~
         z__ ~~ "/" ~~ c__ ~~ EndOfLine] -> {x, y, z}]);
ft = {ToExpression[#[[1]]], ToExpression[#[[2]]], 
     ToExpression[#[[3]]]} & /@ (StringCases[t, 
       "f " ~~ x__ ~~ "/" ~~ a__ ~~ " " ~~ y__ ~~ "/" ~~ b__ ~~ " " ~~
         z__ ~~ "/" ~~ c__ ~~ EndOfLine] -> {a, b, c}]);
Graphics3D[{Texture[tex], EdgeForm[None], 
     VertexTextureCoordinates -> {vt[[ft[[i]][[1]]]], 
       vt[[ft[[i]][[2]]]], vt[[ft[[i]][[3]]]]}], {i, 1, Length[f]}]]},
  Lighting -> "Neutral"]

This is what I get when using some sample files from this website, the same one I suspect you got your 3D model from.

3D Model


POSTED BY: Christopher Cooley
1 year ago