FixBlenderImportRotation

From Unify Community Wiki
Revision as of 11:50, 2 November 2013 by Benjamin Schaaf (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Author: Benjamin Schaaf

Description

This script modifies the mesh and object data before and imported blender file is saved to disk. This get's rid of all the problems caused by blenders forward axis to be X rather than Unity's Z. Instead of all the objects in the object to be rotated by x-90 degrees, the mesh data is properly rotated, meaning transform.forward is the real forward axis, and lookAt actually works!

Usage

The script needs to be placed in a folder called Editor. It will run automatically when a blender asset is imported, so if blender files already exist, they should be reimported for the fix to take place.

Note that this will not change any prefab rotations, so you might have to go through your prefabs and subtract x-90 degrees from their rotation.

Code

Some optimisations could probably be done, but this won't run during runtime anyway (or even be built for that matter), so who really cares?

#pragma strict
 
import System.IO;
import System.Linq;
 
/*
Author: Benjamin Schaaf
*/
class BlenderAssetProcessor extends AssetPostprocessor {
    //quaternions are expensive
    private var rotation:Quaternion = Quaternion.Euler(90, 0, 0);
 
    //After an asset was imported, but before it is saved to disk
    public function OnPostprocessModel(object:GameObject):void {
 
        //only perform corrections with blender files
        var importer : ModelImporter = assetImporter as ModelImporter;
        if (Path.GetExtension(importer.assetPath) == ".blend") {
            RotateObject(object.transform);
        }
 
        //Don't know why we need this...
        //Fixes wrong parent rotation
        object.transform.rotation = Quaternion.identity;
    }
 
    //recursively rotate a object tree individualy
    private function RotateObject(object:Transform):void {
        object.eulerAngles.x += 90;
 
        //if a meshFilter is attached, we rotate the vertex mesh data
        var meshFilter:MeshFilter = object.GetComponent(typeof(MeshFilter)) as MeshFilter;
        if (meshFilter) {
            RotateMesh(meshFilter.sharedMesh);
        }
 
        //do this too for all our children
        //Casting is done to get rid of implicit downcast errors
        for (var child:Transform in (object as IEnumerable).Cast.<Transform>()) {
            RotateObject(child);
        }
    }
 
    //"rotate" the mesh data
    private function RotateMesh(mesh:Mesh):void {
        var index:int = 0;
 
        //switch all vertex z values with y values
        var vertices:Vector3[] = mesh.vertices;
        for (index = 0; index < vertices.length; index++) {
            vertices[index] = Vector3(vertices[index].x, vertices[index].z, vertices[index].y);
        }
        mesh.vertices = vertices;
 
        //for each submesh, we invert the order of vertices for all triangles
        //for some reason changing the vertex positions flips all the normals???
        for (var submesh:int = 0; submesh < mesh.subMeshCount; submesh++) {
            var triangles:int[] = mesh.GetTriangles(submesh);
            for (index = 0; index < triangles.length; index += 3) {
                var intermediate:int = triangles[index];
                triangles[index] = triangles[index + 2];
                triangles[index + 2] = intermediate;
            }
            mesh.SetTriangles(triangles, submesh);
        }
 
        //recalculate other relevant mesh data
        mesh.RecalculateNormals();
        mesh.RecalculateBounds();
    }
}
Personal tools
Namespaces

Variants
Actions
Navigation
Extras
Toolbox