From a78955610e5101e57d466c52cbd36aaa67bfcdd4 Mon Sep 17 00:00:00 2001
From: rdb <git@rdb.name>
Date: Sat, 24 Jan 2015 17:59:53 +0100
Subject: [PATCH] Automatically calculate "Generated" (ORCO) coordinate sets
 when used

---
 yabee_libs/egg_writer.py        | 47 +++++++++++++++++++++++++++++++++++++++--
 yabee_libs/texture_processor.py |  8 +++++--
 2 files changed, 51 insertions(+), 4 deletions(-)

diff --git a/yabee_libs/egg_writer.py b/yabee_libs/egg_writer.py
index 9002483..eebaa36 100644
--- a/yabee_libs/egg_writer.py
+++ b/yabee_libs/egg_writer.py
@@ -420,6 +420,18 @@ class EGGMeshObjectData(EGGBaseObjectData):
         if CALC_TBS == 'BLENDER':
             self.tangent_layers = self.pre_calc_TBS()
 
+        # Check if we may need to generate ORCO coordinates.
+        need_orco = False
+        for f in self.obj_ref.data.polygons:
+            if f.material_index >= len(obj.data.materials):
+                continue
+            for slot in obj.data.materials[f.material_index].texture_slots:
+                if slot.texture_coords == 'ORCO':
+                    need_orco = True
+                    break
+
+        if need_orco:
+            self.pre_calc_ORCO()
 
     #-------------------------------------------------------------------
     #                           AUXILIARY                               
@@ -501,7 +513,38 @@ class EGGMeshObjectData(EGGBaseObjectData):
                 tangents.append(loop.tangent[:]+loop.bitangent[:])
             tangent_layers.append(tangents)
         return tangent_layers
-    
+
+    def pre_calc_ORCO(self):
+        """ Generate texture coordinates for ORCO slots
+        """
+        # We first have to calculate the min and max vertex position...
+        minmax = None
+        for f in self.obj_ref.data.polygons:
+            for v in f.vertices:
+                pos = self.obj_ref.data.vertices[v].co
+                if minmax is None:
+                    minmax = (list(pos), list(pos))
+                for i in range(3):
+                    minmax[0][i] = min(pos[i], minmax[0][i])
+                    minmax[1][i] = max(pos[i], minmax[1][i])
+
+        if not minmax:
+            return
+
+        inv_dims = [0, 0, 0]
+        for i in (0, 1, 2):
+            delta = (minmax[1][i] - minmax[0][i])
+            if delta > 0: # Prevent divide by zero
+                inv_dims[i] = 1.0 / delta
+
+        data = []
+        for f in self.obj_ref.data.polygons:
+            for v in f.vertices:
+                pos = self.obj_ref.data.vertices[v].co
+                orco = [(pos[i] - minmax[0][i]) * inv_dims[i] for i in (0, 1, 2)]
+                data.append(orco)
+
+        self.uvs_list.append(('ORCO', data))
 
     #-------------------------------------------------------------------
     #                           VERTICES                                
@@ -570,7 +613,7 @@ class EGGMeshObjectData(EGGBaseObjectData):
         """
         for i, uv in enumerate(self.uvs_list):
             name, data = uv
-            if i == 0: name = ''
+            if i == 0 and name != 'ORCO': name = ''
             tbs = ''
             if self.tangent_layers:
                 tbs = '\n    <Tangent> {%f %f %f}\n    <Binormal> {%f %f %f}' % self.tangent_layers[i][ividx]
diff --git a/yabee_libs/texture_processor.py b/yabee_libs/texture_processor.py
index 5edeece..40fd8a4 100644
--- a/yabee_libs/texture_processor.py
+++ b/yabee_libs/texture_processor.py
@@ -25,7 +25,7 @@ class SimpleTextures():
         
     def is_slot_valid(self, tex):
         if ((tex) and (not tex.texture.use_nodes)):
-            if tex.texture_coords in ('UV', 'GLOBAL'):
+            if tex.texture_coords in ('UV', 'GLOBAL', 'ORCO'):
                 if tex.texture.type == 'IMAGE' and tex.texture.image and tex.texture.image.source == 'FILE':
                     return True
 
@@ -82,7 +82,7 @@ class SimpleTextures():
 
                 # General textures
                 for f in obj.data.polygons:
-                    if obj.data.uv_textures and f.material_index < len(obj.data.materials):
+                    if f.material_index < len(obj.data.materials):
                         valid_slots = self.get_valid_slots(obj.data.materials[f.material_index].texture_slots)
                         alpha_tex = self.get_alpha_slot(valid_slots)
                         alpha_map_assigned = False
@@ -102,6 +102,10 @@ class SimpleTextures():
                                 if uv_name:
                                     scalars.append(('uv-name', uv_name))
 
+                            elif tex.texture_coords == 'ORCO':
+                                # We generate a set of UVs for this elsewhere.
+                                scalars.append(('uv-name', 'ORCO'))
+
                             elif tex.texture_coords == 'GLOBAL':
                                 scalars.append(('tex-gen', 'WORLD_POSITION'))
                                 # Scale to Panda's coordinate system
-- 
1.8.4

