How to set custom Normals to get natural trees.

Here is a simple script. What it does is to recalculate the normals of each poly in the model to point directly away from the object’s center, this gives a more volumetric apearance to the leaves, which are afterall, just single planes with a partly transparent texture on them.

here’s the code for 2.49b:

import Mathutils

# get controller
cont = GameLogic.getCurrentController()
 
# get object the controller is attached to
own = cont.owner
 
# get the 1st mesh
mesh = own.meshes[0]
 
# get first material
matID = 0

# get array length of the material
length = mesh.getVertexArrayLength(matID)
 
# loop through array
for array in range( 0, length):
     
    # get vertex
    vert = mesh.getVertex(matID,array)
     
    pos = vert.getXYZ()
    
    a = [0.0,0.0,0.0]
    b = pos
    
    ab = (b[0] - a[0],b[1] - a[1],b[2] - a[2])
        
    vect1 = Mathutils.Vector(ab[0], ab[1], ab[2])
    
    # normalize the vector
        
    vert.setNormal(vect1.normalize())

and for 2.63:

import bge
import mathutils

cont = bge.logic.getCurrentController()
 
# get object the controller is attached to
own = cont.owner
 
# get the 1st mesh
mesh = own.meshes[0]
 
# get first material
matID = 0

# get array length of the material
length = mesh.getVertexArrayLength(matID)
 
# loop through array
for array in range( 0, length):
     
    # get vertex
    vert = mesh.getVertex(matID,array)
     
    pos = vert.getXYZ()
    
    a = [0.0,0.0,0.0]
    b = pos
    
    ab = (b[0] - a[0],b[1] - a[1],b[2] - a[2])
        
    vect1 = mathutils.Vector((ab[0], ab[1], ab[2]))
    
    # normalize the vector
    
    vect1.normalize()
        
    vert.setNormal(vect1)

Simply run it on on an object the includes only your tree’s leaves, it’s very fast and can be done when your game level starts.

There is only one big limitation, it can only run on objects that are not rigged.

You could also use it to create more realistic grass, though you may have to edit the “a” variable to be [pos[0], pos[1], 0.0] to get the best effect.

Here’s a preview of what it does:

Attachments



Nice work, I’ll be able to make good use of this. :slight_smile:

I’d been thinking of making something similar myself for quite a while. Perhaps sometime in the future I might make a script that gives the user more control over the normals.

There is only one big limitation, it can only run on objects that are not rigged.

This could be worked around by animating trees with vertex shader. So animated trees are quite possible with this.

The real limitiation that I was thinking of is that it can’t be used to control the normals in a rigged character’s hair. This would give much nicer results for clip alpha style hair, but it can’t work because the game engine uses vertex data to do bone deformations in the game, making this information unavailable for editing. You also can’t do the following:
Set vertex colours on a rigged mesh.
Change the XYZ position of verts in a rigged mesh.

This also applies to shape keyed meshes, but you can make a script to animate the verts individually.
Anyway, thanks for trying the script and giving feedback. :slight_smile:

I added a 2.63 version of the script in the first post.

No replies? I don’t want this thread to go unnoticed, because this script can really add to the look of round-ish trees, shrubs, and grass. The example pictures don’t quite do it justice; I’ve gotten excellent results with it.

Wow thats nice, i got to be using this to fix my actual grass and trees.

Cool! Finally found a script that does this (I am very new to programming). Can’t use it yet, but i’ll try when I find more time.

Hi, Thanks for sharing this.

I’m trying to make it work on Blender 2.70 but I get this error:

ImportError: No module name ´bge´

Am I missing something?

You don’t need to import bge any more, it’s imported automatically.

Hi, I don’t know how well this works in recent versions of Blender. It was originally done for single texture, and I don’t know if it has any real effect with GLSL.

This is an old post . . . but.
Very cool of you to take the time to write a script for 2.49. I’ll have to check this out.
At the moment, My Macbook doesn’t support GLSL, or shaders, lights. shadows, etc.
(Even with Unity)
So this should be perfect for me. Thank You.

Hey, this is a useful good script, what do you think about make it a bpy script and run it in the viewport? of this way you don’t have to run the script everytime the game starts.

Hi, this functionality should be in blender 2.74 already. I’m going to be exploring the new modifier and seeing what results i can get.

Also, check your code… Normalize should return None, you want normalized

That’s right isn’t it?

vect1.normalize()

is essentially the same as:

vect1 = vect1.normalized()

Though it’s probably not good practice to use:

vert.setNormal(vect1.normalize())

Actually this is a very old code snippet. It’s from 2012, today I would probably just use:


for v in range(length):
     vert = mesh.getVertex(matID,v)
     
     normal_vector = vert.getXYZ().copy().normalized()

     vert.setNormal(normal_vector)

Since subtracting a zero vector doesn’t really do anything. You’d only need to do the vector combination if the center target of the normals (the point which they radiate from) is not the center of the mesh. Also array was a terrible name for a variable meant to represent the vertex index count. :slight_smile: