how to flip normals in game

how would i go about doing this?
i have been told one way is to find 3 verts of a face and switch 2 of them around but how do i find faces then the verts there of?

please dont say its impossible

What are you trying to achieve?
You probably won’t be able to change collision of the face if that’s what.
Or making a wall/door transparent is probably better done with shifting uv.

Anyway.
It is better said, that reversing the order of vertices in the face changes the normal direction.
[v1,v2,v3] -> [v3,v2,v1] or [v1,v2,v3,v4] -> [v4,v3,v2,v1]

That is, when you create the mesh, in bge in is bit different.
Each vertex has normals that are used for shading I think.

If you want to flip the face, for backface culling, then you have to move the vertices also.

import bge

def main():
    cont = bge.logic.getCurrentController()
    own = cont.owner
    
    mesh = own.meshes[0] 
    
    for faceIndex in range( mesh.numPolygons ):
        face = mesh.getPolygon(faceIndex)
        
        faceVerts = [ face.v1,face.v2,face.v3]
        if face.getNumVertex()==4:
            faceVerts.append( face.v4 )     
            
        
        # collect vertex posiions and change 'normal'
        vertexPositions = []
        for vertIndex in faceVerts:
            vert = mesh.getVertex(0, vertIndex) 
            
            vertexPositions.append( vert.XYZ )            
            vert.normal = -vert.normal
       
        # flip the face by reversing the positions of the vertex
        for index,vertIndex in enumerate(reversed(faceVerts)):
            vert = mesh.getVertex(0, vertIndex) 
            vert.XYZ = vertexPositions[ index ] 

main()

Attachments

normalFlip.blend (505 KB)

I tried, it works on some shapes very well (Cube, subdivided cube, so on), but doesn’t work on some other things (Like the Monkey/Sphere)

import bge
owner=bge.logic.getCurrentController().owner
for m in owner.meshes:
    for mi in range(len(m.materials)):
        for x in range(m.numPolygons):
            p=m.getPolygon(x)
            v1=m.getVertex(mi,p.v1)
            v2=m.getVertex(mi,p.v2)
            v3=m.getVertex(mi,p.v3)
            m.getVertex(mi,p.v1).setNormal(-v1.normal)
            m.getVertex(mi,p.v2).setNormal(-v2.normal)
            m.getVertex(mi,p.v3).setNormal(-v3.normal)
            if p.getNumVertex()>3:
                v4=m.getVertex(mi,p.v4)
                m.getVertex(mi,p.v4).setNormal(-v4.normal)
            xyz=v3.getXYZ()
            v3.setXYZ(v1.getXYZ())
            v1.setXYZ(xyz)

Basically it flips the 1st and 3rd vertices by switching their XYZs and it also flips the normal value of each vertice (which controls the direction they will receive light from)

wow cool last time i asked this all i got was its impossible :smiley:
BUT how can i have this with smooth shading enabled ? or is there a way to rip faces or something?
the obj has each vert moved out in the normal witch disconnects each face if not in smooth shading mode
this is what i am getting


this is what i need


I think there’s a node input in material node for normal, you might want to try inverting the normal output from geometry node and controlling it with lamp data energy / object colours.

ha i did not even think about the nodes… but then there is still the problem of how can i give an obj the material in game and without it messing with the textures

Only use the node texture on the second version?

Just have it assigned in a material Slot, but not used in regular model?

Also, what does object.localScale= (-1,-1,-1)
Do? Scale by neg 1 in ui flips normals, what about in engine?

the point of the script i am trying to make is you can have outlines around anything with no extra models and no setup(apart from turning on the emit to anything other than 0 so it acts shadeless) so i would need to be able to add the nodes entirely with in bge

if i flip it inside out like that on an asymmetric model i will not be able to line it back up with the base model to give the outline effect

Ensure you recalculate the vertex normals or just copy it from the vertex the current one switched place. This is included in facefire333’ snippet.

i mean it looks like this with smooth shading on (i turned off the blue glow so you can see the effect better)


this is using facefire333 code
so it looks like not having smooth shading is like having an edge split modifier

there are 2 (long) ways i can think of to get around this
using a Nearest neighbor search to “reattach” the points (wont be pretty but it should look ok)
or making storying a copy of all the points that are at the same loc before the scaling along the normals then moving them all to the midpoint of the current loc

what would be more efficient ?

Too me it looks like some faces are completely distorted as you can see the holes. Even with incorrect vertex normals it should look compact (just incorrectly illuminated).

Edit: I just tested with a pretty complex object. It seams that not all faces are included in the polygon.
Edit2: The number of vertices is correct. But I have the impression the mapping polygon -> vertex index is not correct.

Maybe you should slow down and think about what you are trying to do.

You want the inverted normals to show as a halo around the object to indicate something about the state of the object right?
Like a special power or mouse over highlighting.

Why recalculate the normals in game? You can do it in Blender easily:

  • Shift + “d” to duplicate the mesh,
  • Use alt + “s” to scale along normals and fatten the mesh
  • Control + “f” in edit mode and then select “flip normals”

then just hide the highlighting object when it’s not being highlighted. Either by using

object.visible =False

or adding an action that controls object color.

Here’s what i did in the past:

I can’t think of any reason you’d have to recalculate the normals manually in game to get this effect.

Here’s a demo blend to show what I’m talking about:
highlighting.blend (755 KB)

You don’t have to contain both meshes in one object, but it’s possible to do so if you turn off object color in the texture panel of your main no highlighting mesh and combine them together.

Dictionary lookup definitely.


Lazy code:

 for index,vertIndex in enumerate(reversed(faceVerts)):            vert = mesh.getVertex(0, vertIndex) 
            vert.XYZ = vertexPositions[ index ]
            
            pos = tuple(vert.XYZ)
            if not pos in pairDict:
                pairDict[pos] = []
            pairDict[pos].append( vertIndex )           
            
            vert.XYZ = vert.XYZ - 0.1*vert.normal
   
    for pairIndex in pairDict:
        averagePos = Vector([0,0,0])
        for vertIndex in pairDict[pairIndex]:
            averagePos += mesh.getVertex(0, vertIndex).XYZ
        averagePos /= len( pairDict[pairIndex] )
        for vertIndex in pairDict[pairIndex]:
           mesh.getVertex(0, vertIndex).XYZ = averagePos

            

Also, bit offtopic, there seems to be a bug with quads and triangles mixed creating a different glitchi result by every refresh? With both scripts, mine and flamefire333’s. Triangulating the mesh solves it.

Notice, that the default eyes of monkey are triangles while the rest are quads.

EDIT:

Seems to be an actual thing an not only me…

ya sorry here without the glow on flat shading


smooth shading connects faces to each other so they share virts
flat shading keeps each face separately
to flip the normal each face in the mesh has its verts switched (so vert 1-2 and 2-3 switch places for each face) so whats going on with smooth shading would go something like this if you had one row of verts (every 2 being the top of a face)
1,2,3,4,5,6
flipping face 1
2,1,3,4,5,6
flipping face 2
3,1,2,4,5,6
and so on until the last one is
6,1,2,3,4,5
which works just fine on something like a tube with only 1 edge loop for the entire model and is entirely made of qouds but when you dont… well you see what happens

the point of this “script” is to make a “highlight” effect without any extra stuff eg duplicate models (tho it does need an emit value > 0 for the shaddless look)

i just put my model thro zbrush remesh to get it all quads to stop the triangle glitches but any good model should be all quads any way so i am told lol

the point of it is that you need no setting up at apart from loading the scripts and inputting an identifier for highlightable things (all tho the emit value seems unavoidable right now)
and all the “computing” will be done in a loading screen so as long as each outline setup is under 1s or so it should be fine

also i think i just came up with a way for it to only ever need to do it once ever :smiley:
i will do testing tomorrow

Ah, yes, I guess if you’ve got 32 objects it could be a pain to go through each and every one to create a custom mesh.
Or if you’ve got like 200 weapons and items which need doing…

However, I’ve used BPY quite a bit recently and I can say there’s a lot of more useful functions in there for doing bulk mesh conversion with a more simple script, such as This function.

Still, I see the appeal of the challenge. :slight_smile:

For getting smooth shaded polys, you can use vert.setNormal, it’s great for setting shading normal, even though it doesn’t recalculate the z_buffer (so even inside out meshes will overdraw things inside them).

You need to do something similar to what @VegetableJuiceF did with the dict entries. Get all the verts that share a single position, sum all their normal vectors, and divide by the number of verts. You can start with an empty Vector:

base_vector = mathutils.Vector()
number = len(dict_entry)

for vector in dict_entry:
    base_vector += vector

new_vector = base_vector / number

Then set the vertex normals to this new normal. That’ll give you the correct smooth shading effect.

well i got it working :smiley: but it was taking about 5mins to 9000*about 4 verts on my test model but i did figure out a way to get that down to about 2s (including libload and all that)

i say “9000*about 4 verts” as each face has its own verts but there is not 3 other faces at every corner (all faces are quads)

but still this could be way too long for the start of every scene in the game so i was thinking of having it run on game startup and exporting a text doc with the loc of each vert so if that doc is already there it can save a bit of time not worrying about finding doubles and flipping/moving normals… tho that will not help with the libload delay

just keeping people updated and i will post the script when i get the improved one working and clean it up… tho that may take a few days lol i am a very messy coder and don’t name things so i am told my code is painful to look at XD but hey as long as it works i say lol

gameObject.meshes[0].invert_Normals() should be a function.

Nice Work Jesse.

If you are already creating external files and such, I would suggest running a bpy script.

Best case would be pressing p would first launch the bpy script and then open the game itself.

It shouldn’t be too hard the create inverted double models in bpy or bmesh.