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.
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!
"""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")
name = mgGetName (rec)
if (mgGetCode(rec) != fltPolygon):
mgSendMessage (MMSG_ERROR, "Select a polygon")
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.
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)
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)
# 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")
Perfect! Thanks so much for your help!