Skip to content

249 How It Works Materials

tngreene edited this page Nov 17, 2020 · 8 revisions

The material model from 2.49 is very different from 2.7x's file.

Relevant Files

  • XPlaneExport.py
    • line 269-475, definition of getTextures and checkdup
  • XPlaneExport8_util.py
    • line 182, definition of DEFMAT
    • line 349-408, class definition of Prim (the heart of the obj exporter)
    • line 574-618, OBJexport8.init's definitions of a bunch of class attributes and state variables
    • line 1190-1501, sortMesh (collection of data)
      • line 1223-1248, finding material props
      • lines 1262, 1276, important looking lines
      • line 1293-1348, finding face props
      • line 1391-1514, more of the same as 1293-1348?
    • line 1642-1984, XPlaneExport8_util.updateAttr - the thing that actually writes ATTRs
  • XPlaneMat2Tex.py, only a helper script. Doesn't help much, except with intentions?
  • XPlanePanelRegions.py, dialog box to interact with PanelRegionHandler in XPlaneUtils.py
  • XPlaneUtils.py
    • line 718, def tex_exists (but we might not need this)

Textures

Getting TEXTURE with 2.49 workflow:

  1. Make your Mesh
  2. Make your UV unwrap
  3. Do your made artistry, save a .png, .dds. (.bmp is only used in X-Plane 7)
  4. Assign this texture to your mesh's UV

Although you can have multiple UVs per object (Mesh > Data > UV Texture > Click New), only the active will be used. Some artists use this as part of a texture baking flow.

To Make Another UV:

  • Make a mesh
  • Unwrap it anyway you're going to
  • Go into the UV/Image Editor, assign an image from disk
  • You can make another by going to Buttons > Data > Editing (aka Data in 2.7x) > Mesh > UV Texture (But again, we only ever use the active one)

The exporter finds this texture on disk, but can also look for _LIT and _NML files (hard-coded case sensitive names, looked up with os.path.exists) If encountered it turns on normal and lit stuff.

For instance, this set: {tex.png, tex_LIT.png, tex_NML.png}

Getting TEXTURE_DRAPED with 2.49

  1. Do the regular steps 1-4
  2. Give the object a game property (any type, any value) call "ATTR_draped"
  3. Select your draped face and change the texture to your draped texture (no name requirements)
  4. Go to Buttons > Data > Editing and ensure "Tex" and "Tiles" are checked.
  5. There is no _LIT texture lookup because draped texture can't be _LIT
XPlaneExport.py
def getTexture(...):
...
    if objType == "Mesh":
        mesh=object.getData(mesh=True)
        if isLight(...)
            # Custom light stuff
            ....
        elif mesh.faceUV: # Blender 2.49 api, a bool. "The mesh contains UV-mapped textured faces."
            #print '%s (%d)' % (object.getName(), len(mesh.faces))
            for face in mesh.faces:
                has_draped = (face.mode&Mesh.FaceModes.TILES) and has_prop(object,'ATTR_draped')
                
                if (face.mode&Mesh.FaceModes.TEX) and face.image and has_draped == want_draped:
                    # Draped stuff
                    ...
                else:
                    #face.image.filename is the file from the UV/Image editor's editor
                    #thisdir is the dir of the blend file
                    #texture by this point is None
                    #texlist = []
                    texture=checkdup(face.image.filename, thisdir, texture, texlist, multierr, object)
                    texlist at this point will have multiple textures and we do..... nothing with it!
                    
                

Face Buttons We Care About

Materials

Materials are far less used in 2.49. They are only used (per object or, gulp, per face) for specific buttons and setting the Specularity slider. A material's texture is ignored (unlike 2.7x)

A list of buttons that concern us:

2.49 Location 2.49 API Name 2.7x Material Location* Blender 2.7x API Name
Texture Face > Tex Mesh.FaceModes.TEX Hidden, material.c, line 1856 Not exposed***
Texture Face > Tiles Mesh.FaceModes.TILES Parse name, find flag Not exposed***
Texture Face > Light Mesh.FaceModes.LIGHT Hidden, material.c, line 1862 Not exposed***
Texture Face > Invisible Mesh.FaceModes.INVISIBLE Game Settings > Invisible game_settings.invisible
Texture Face > Collision Mesh.FaceModes.DYNAMIC [ ] Physics game_settings.physics
Texture Face > Two Side Mesh.FaceModes.TWOSIDE Game Settings > Backface Culling game_settings.use_backface_culling
Texture Face > Shadow Mesh.FaceModes.SHADOW Game Settings > Face Orientation > Shadow game_settings.face_orientation = "SHADOW"
2.49 Location 2.49 API Name 2.7x Material Location* Blender 2.7x API Name
Texture Face > Alpha Mesh.FaceTranspModes.ALPHA Game Settings > Alpha Blend > Alpha game_settings.alpha_blend = "ALPHA"
Texture Face > Clip Alpha Mesh.FaceTranspModes.CLIP Game Settings > Alpha Blend > Alpha Clip? game_settings.alpha_blend = "CLIP"

*Texture Face = Select Mesh > Edit Mode > Select Face > Editing (aka Data) > Texture Face

**Blender's Render Engine must be "Blender Game" to see it in the UI

***See blender/blenkernel/intern/material.c, lines 1834 to 1869 for whats really up! By using CTypes we can get the real value per face.

How These Buttons Are Used

All in XPlaneExport8_util.py

Has TEX

Line # 2.49 Use 2.49 Effect 2.78 Use
558 if TEX TEX must be active to get the image for the face None/exporter internals
1276 if TEX TEX takes UV from face's UV for VT table None/exporter internals
1474 if TEX TEX takes UV from face's UV for VT table None/exporter internals
Line # 2.49 Use 2.49 Effect 2.78 Use
1320, 1416 if TEX and f.transp == Mesh.FaceTranspModes.ALPHA and has_prop("ATTR_shadow_blend") Writes ATTR_shadow_blend 0.5 (default) mat.xplane.blend_v1000 = "shadow"
1322, 1419 if TEX and f.transp == Mesh.FaceTranspModes.ALPHA and has_prop("GLOBAL_shadow_blend") Writes GLOBAL_shadow_blend 0.5 (default) mat.xplane.blend_v1000 = "shadow"
Line # 2.49 Use 2.49 Effect 2.78 Use
1327, 1424 if TEX and f.transp == Mesh.FaceTranspModes.CLIP and has_prop("ATTR_no_blend") Writes ATTR_no_blend 0.5 (default) mat.xplane.blend_v1000 = "off"
1327, 1426 if TEX and f.transp == Mesh.FaceTranspModes.CLIP and has_prop("GLOBAL_no_blend") Writes GLOBAL_no_blend 0.5 (default) mat.xplane.blend_v1000 = "off"

Panel Regions

Line # 2.49 Use 2.49 Effect 2.78 Use
1343+ if TEX and self.ispanelok and mode&Mesh.FaceModes.TEX Sets flags and regions None?
1347 if TEX and f.image and 'panel.' in f.image.name.lower() Sets PANEL, enables others to write ATTR_(no)_cockpit, ATTR_cockpit_region, ATTR_manip_panel

Has TILES, LIGHT

line 1338-1341, 1435-1438 (repeats because of giant if hasanim block {?})

2.49 Use 2.49 Effect 2.78 Use
if not ISCOCKPIT and (has TILES or LIGHT) and no "ATTR_draped" Writes ATTR_poly_os 2 and resets to ATTR_poly_os 0 mat.xplane.poly_os = 2 (see line 1752)
if not ISCOCKPIT and (has TILES or LIGHT) and "ATTR_draped" Writes ATTR_draped mat.xplane.draped = True

Has INVISIBLE

Line # 2.49 Use 2.49 Effect 2.78 Use
1266 if not INVISIBLE Prevents geometry for this {face? This Object?} from becoming part of VT Table mat.xplane.draw = False, a small performance hit until we can implement #409
1300, 1396 if not INVISIBLE, append material write ATTR_diffuse_rgb, ATTR_emission_rgb, ATTR_shiny_rat if INVISIBLE we don't get to here anyway

Has DYNAMIC

Line # 2.49 Use 2.49 Effect 2.78 Use
1350, 1447 if not INVISIBLE and not self.iscockpit and (self.additive_lod or object.Layer&1) and not DYNAMIC DYNAMIC = True by default, DYNAMIC = False semantically means on. Writes, ATTR_hard mat.xplane.solid_camera = True

Has TWOSIDE

Line # 2.49 Use 2.49 Effect 2.78 Use
1334, 1431 if TWOSIDE write ATTR_cull writes ATTR_cull None. We don't use ATTR_cull or ATT_no_cull. Easy!

Has SHADOW

Line # 2.49 Use 2.49 Effect 2.78 Use
903 if instanced and not DRAPED and SHADOW, set GLOBAL_no_shadow None, we turn on GLOBAL_no_shadow differently
1354, 1452 if SHADOW Writes ATTR_shadow We don't have ATTR_shadow!

Game Properties We Care About

has_prop type default Dest
'GLOBAL_no_blend' float-like 0.5 Force "Instanced Scenery", make something "ATTR_no_blend" (maybe make a new empty "FORCE_GLOBALS" to fake it during conversion?)
'GLOBAL_specular' anything (but hopefully a float-like) 'XXX' Force "Instanced Scenery"
'GLOBAL_shadow_blend' float-like 0.5 Force "Instanced Scenery"
'GLOBAL_tint' (but hopefully a float-like) 'XXX' Force "Instanced Scenery" and some mat.options.tint
'COCKPIT_REGION' exists at all. Forces ATTR_cockpit_region 0 for all.... Set cockpit region 0 for all? Unsure?
'NORMAL_METALNESS' check exists None make all materials have NORMAL_METALNESS (otherwise we'd throw an error)
'BLEND_GLASS' check exists None make all materials have BLEND_GLASS (otherwise we'd throw an error)
'additive_lod' int
'instanced' int-like int('additive_lod') hint layer type xplane.layer.export_type
has_prop type default Dest
'lit_level' dref str stripped '' mat.xplane.lightlevel_dataref # A synonym of ATTR_light_level (overwrite this)
'ATTR_light_level' dref str stripped '' mat.xplane.lightlevel_dataref
'ATTR_light_level_v1' str '0.0' mat.xplane.lightlevel_v1
'ATTR_light_level_v2' str '1.0' mat.xplane.lightlevel_v2
has_prop type default Dest
'ATTR_draw_disable' check exists None not mat.xplane.draw, for us (for now until #409) it is an alternative for INVISIBLE
'ATTR_solid_camera' check exists None None, used internally for error checking
'surface' str "" mat.xplane.surfaceType
'deck' bool like False mat.xplane.deck (shown when a surface type is shown)
'up_norm' int or float 0 Makes Normals face up always? if up_nrm: norm=Vertex(0,0,1, anim_matrix from makeAnim)
'ATTR_no_blend' int or float 0.5 mat.xplane.blendRatio
'ATTR_shadow_blend' int or float 0.5 mat.xplane.blendRatio
'ATTR_draped' bool? check exists None mat.xplane.draped

Material Settings

2.49 doesn't have many. Diffuse and Emissive RGB have been deprecated, so Buttons > Material > Shaders > Spec is really all we care about.

Object-linked Material Datablocks are ignored by XPlane2Blender 2.49.

2.7x conversion plan

Then in 2.7x we'll

  • Take each object, and separate the odd faces out in terms of non-uniform buttons, into as few Meshes as possible
  • For each mesh, make sure the material has the relevant buttons copied over to the new properties
  • That the texture assigned to the face's UV, and put it in the Material's Texture Slot.

Also, if they have a _LIT and _NML texture on disk where it is supposed to be, make texture slots for those too