Start a new topic

Texture Mapping from Polygon

Original Post by: clamoreaux Fri Sep 20 15:40:36 2013


Is there a way in version 3.5 to create a texture mapping entry in a mapping palette from a the texture applied on a polygon? I need this in a stand-alone environment. I am writing a python script that opens x number of flight files, one at a time, processes them, and saves and closes them.


Original Post by: SteveThompson Fri Sep 20 16:27:08 2013


Here is a script that shows how you might do this.

The main function, MakeTextureMappingForFace, can be used in either Creator or a stand-alone script. The bits below the function show how you might use this function in Creator.


Be aware that if you simply called this for every face in your db, you are very likely to get "duplicate" entries in your Texture Mapping Palette since presumably multiple faces might be mapped with exactly the same "mapping".


Other potential "gotchas" on this script:

1) Does not verify face has texture applied

2) Not a lot of error checking

3) Assumes nice "regular" texture mapping on the face (no perspective or warping)

4) Assumes 3 points of the face are not colinear


Even with these caveats, this should get you started. Have fun!


def MakeTextureMappingForFace(face):

"""Build a texture mapping palette entry based on the

current texture mapping (in layer 0) of a face."""

# get the db this face belongs to

db = mgRec2Db(face)

# use the name of the face for the name of

# the new texture mapping palette entry

name = mgGetName(face)

# create the new texture mapping palette entry

tm,index = mgNewTextureMapping (db, 1, name);

# to make the texture mapping palette entry

# we need 3 points in XYZ and 3 corresponding UVs

# we'll just grab the first 3 vertices of the

# face to get these points

# first get 3 vertices of the face

v1 = mgGetChild (face)

v2 = mgGetNext(v1)

v3 = mgGetNext(v2)

# next get XYZ and UV of these points

ok, x1,y1,z1 = mgGetVtxCoord (v1)

ok, x2,y2,z2 = mgGetVtxCoord (v2)

ok, x3,y3,z3 = mgGetVtxCoord (v3)

numAttr,code,u1,code,v1 = mgGetAttList (v1, fltVU, fltVV)

numAttr,code,u2,code,v2 = mgGetAttList (v2, fltVU, fltVV)

numAttr,code,u3,code,v3 = mgGetAttList (v3, fltVU, fltVV)

# finally set these points on the texture mapping

ok = mgSetCoord3d (tm, fltTM3PtOriginUV, u1,v1,0.0)

ok = mgSetCoord3d (tm, fltTM3PtAlignUV, u2,v2,0.0)

ok = mgSetCoord3d (tm, fltTM3PtShearUV, u3,v3,0.0)

ok = mgSetCoord3d (tm, fltTM3PtOriginXYZ, x1,y1,z1)

ok = mgSetCoord3d (tm, fltTM3PtAlignXYZ, x2,y2,z2)

ok = mgSetCoord3d (tm, fltTM3PtShearXYZ, x3,y3,z3)

# if you do this inside Creator you need to tell

# Creator to rebuild some stuff so the mapping works

# properly in the open database

ok = mgUpdateTextureMapping (tm);

# if you do this in a stand alone script (outside of

# Creator) or close and reopen the file you don't need

# to call mgUpdateTextureMapping


db = mgGetCurrentDb()

selectList = mgGetSelectList (db)

rec,m = mgGetNextRecInList (selectList)

if (rec is None):

mgSendMessage (MMSG_ERROR, "Nothing selected")

else:

name = mgGetName (rec)

if (mgGetCode(rec) != fltPolygon):

mgSendMessage (MMSG_ERROR, "Select a polygon")

else:

MakeTextureMappingForFace(rec)


Original Post by: clamoreaux Fri Sep 20 17:21:08 2013


Thanks!


Now is there a way to use that mapping to apply texture to a polygon without putting the mapping number in the polygon -- in other words, apply that texture to a polygon by inserting the appropriate u,v values in the vertices.


I am trying to extend vertices on some building model into the ground to create foundations but I want to preserve the texture mapping. I don't want to keep all the texture pallete entries because there will be dozens in one model.


We can't do this by had with the vertex plant commant because there are 1000's of models. I need to write a script (or C++ program) to do this.

Original Post by: SteveThompson Fri Sep 20 17:55:16 2013


If I had known this is where you ultimately wanted to go, I would have suggested a different approach. Instead of making a texture mapping from a polygon and then applying that mapping to other polygons to "extend" the texture onto those other polygons, there is a shortcut not involving texture mapping entries at all. In Creator there is a tool to do this called "Flow Texture" so I will use that terminology in my post below.


There is a useful utility function called mgMatrixFormXYZToUV that can be used here directly. It creates a matrix that represents the transformation from XYZ coordinates to UV texture coordinates for a polygon in a given texture layer. So if you calculate and store this matrix for a polygon, you can use it to "flow" UVs onto other polygons. These new UVs on those other polygons will map into the same texture mapping space of the original polygon (hence the term "flow").


Note that mgMatrixFormXYZToUV works well if your polygon was texture mapped "nicely" (like using 3 Point Put, for example). If you have any warping applied, it will not work so well.


If you do want to continue to use texture mapping palette entries, you can also get the XYZ -> UV matrix from it using mgGetTextureMappingMatrix.


Here is a script that "flows" the UVs from a "fromFace" onto a "toFace". If fromFace has a texture mapping palette entry, it gets the matrix from that texture mapping entry. Otherwise it gets the matrix from the face directly using mgMatrixFormXYZToUV . In either case (no matter how it got the matrix), applying the matrix to the "toFace" UVs is the same.


Hope this helps.



def FlowTexture(toFace, fromFace):

db = mgRec2Db(fromFace)

# if fromFace has texture mapping, get matrix from it

# if fromFace has texture but no texture mapping, get

# matrix using utility function gMatrixFormXYZToUV

numAttr,code,texMapIndex = mgGetAttList (fromFace, fltPolyTexmap)

if (texMapIndex != -1):

uvMat = mgGetTextureMappingMatrix (db, texMapIndex)

else:

b,uvMat = mgMatrixFormXYZToUV (fromFace, 0)

numAttr,code,index = mgGetAttList (fromFace, fltPolyTexture)


# no matter how we got the XYZ -> UV matrix, use it to

# change the UVs on toFace

xyz = mgcoord3d()

vtx = mgGetChild (toFace)

mgSetAttList (toFace, fltPolyTexture, index)


while (vtx):

# get the XYZ of this vertex

b, xyz.x, xyz.y, xyz.z = mgGetVtxCoord (vtx)


# calculate the UV texture coordinates for this uvMat

uv = mgCoord3dTransform (uvMat, xyz)


# finally update the UV texture coordinates on

# the vertex of toFace

# the U value is in the y coordinate

# the V value is in the y coordinate

# the z coordinate is not interesting here

mgSetAttList (vtx, fltVU, uv.x, fltVV, uv.y)


# get ready to process next vertex of toFace

vtx = mgGetNext (vtx)

db = mgGetCurrentDb()

selectList = mgGetSelectList (db)

fromFace,m = mgGetNextRecInList (selectList)

toFace,m = mgGetNextRecInList (selectList)


if (fromFace is None) or (toFace is None):

mgSendMessage (MMSG_ERROR, "Select 2 faces")

else:

FlowTexture(toFace, fromFace)

Original Post by: clamoreaux Mon Sep 23 13:17:04 2013


Perfect! Thanks so much for your help!

Login to post a comment