diff Vis.cpp @ 194:650d96af8855

Vis overhaul; sprites can be picked by mouse
author Nomad
date Sat, 16 Feb 2013 18:32:37 +0200
parents 1860917d953f
children 982c1ec5a983
line wrap: on
line diff
--- a/Vis.cpp	Sat Feb 16 13:28:34 2013 +0400
+++ b/Vis.cpp	Sat Feb 16 18:32:37 2013 +0200
@@ -1,21 +1,29 @@
+#include <assert.h>
+
 #include "Vis.h"
 #include "Outdoor.h"
 #include "Game.h"
 #include "Actor.h"
 #include "IndoorCamera.h"
 #include "Viewport.h"
-#include "stru157.h"
 
 #include "mm7_data.h"
 //#include "MM7.h"
 
 
-static Vis_stru1 Vis_static_sub_4C1944_stru_F8BDE8;
+static Vis_SelectionList Vis_static_sub_4C1944_stru_F8BDE8;
+
+Vis_SelectionFilter vis_sprite_filter_1 = {VisObjectType_Sprite, OBJECT_Decoration,  0, 0,         2}; // 00F93E1C
+Vis_SelectionFilter vis_sprite_filter_2 = {VisObjectType_Sprite, OBJECT_Decoration,  0, 0,         2}; // 00F93E30
+Vis_SelectionFilter vis_face_filter     = {VisObjectType_Face,   OBJECT_Any,        -1, 0,         0}; // 00F93E44
+Vis_SelectionFilter vis_door_filter     = {VisObjectType_Face,   OBJECT_BLVDoor,    -1, 0x100000,  0}; // 00F93E58
+Vis_SelectionFilter vis_sprite_filter_3 = {VisObjectType_Sprite, OBJECT_Decoration, -1, 0,         4}; // 00F93E6C
+Vis_SelectionFilter vis_sprite_filter_4 = {VisObjectType_Any,    OBJECT_Item,       -1, 0,         0}; // static to sub_44EEA7
 
 
 
 //----- (004C1026) --------------------------------------------------------
-Vis_stru1_stru0 *Vis::_4C1026(BLVFace *a2, unsigned int a3, float a4)
+Vis_ObjectInfo *Vis::_4C1026(BLVFace *a2, unsigned int a3, float a4)
 {
   char *v4; // eax@4
   signed int v5; // ecx@4
@@ -29,8 +37,8 @@
   double v13; // st7@14
   signed int v14; // ebx@14
   Vis *v15; // ebx@15
-  Vis_stru1_stru0 *result; // eax@21
-  Vis_stru1_stru0 *v17; // ecx@24
+  Vis_ObjectInfo *result; // eax@21
+  Vis_ObjectInfo *v17; // ecx@24
   RenderVertexSoft pRay[2]; // [sp+20h] [bp-70h]@17
   int v20; // [sp+84h] [bp-Ch]@10
   int v21; // [sp+88h] [bp-8h]@16
@@ -39,7 +47,7 @@
 
   auto ecx0 = this;
 
-  static Vis_stru1 static_sub_4C1026_stru_F8FE00;
+  static Vis_SelectionList static_sub_4C1026_stru_F8FE00;
   static_sub_4C1026_stru_F8FE00.uNumPointers = 0;
 
   static bool _init_flag = false;
@@ -99,16 +107,16 @@
   if ( static_sub_4C1026_array_F8F200[0].vWorldViewPosition.x > (double)a4
     || (_4C1495(static_sub_4C1026_array_F8F200, v7, (float *)&v21, (float *)&v22),
         _4C12C3_FindSomeBillboard(static_sub_4C1026_array_F8F200, v7, *(float *)&v21, *(float *)&v22))
-    || ((CastPickRay(pRay, *(float *)&v21, *(float *)&v22, a4), uCurrentlyLoadedLevelType != LEVEL_Indoor) ? PickOutdoor(a4, pRay, &static_sub_4C1026_stru_F8FE00, &a5, 1) : PickIndoor(a4, pRay, &static_sub_4C1026_stru_F8FE00, &a5),
-        (static_sub_4C1026_stru_F8FE00.create_object_pointers(0),
+    || ((CastPickRay(pRay, *(float *)&v21, *(float *)&v22, a4), uCurrentlyLoadedLevelType != LEVEL_Indoor) ? PickOutdoor(a4, pRay, &static_sub_4C1026_stru_F8FE00, &vis_face_filter, 1) : PickIndoor(a4, pRay, &static_sub_4C1026_stru_F8FE00, &vis_face_filter),
+        (static_sub_4C1026_stru_F8FE00.create_object_pointers(Vis_SelectionList::All),
          sort_object_pointers(
-           static_sub_4C1026_stru_F8FE00.array_1804,
+           static_sub_4C1026_stru_F8FE00.object_pointers,
            0,
            static_sub_4C1026_stru_F8FE00.uNumPointers - 1),
          !static_sub_4C1026_stru_F8FE00.uNumPointers)
      || (result = static_sub_4C1026_stru_F8FE00.sub_4C2551(2, a3)) == 0
      || (signed int)static_sub_4C1026_stru_F8FE00.uNumPointers > 1
-     && ((signed int)static_sub_4C1026_stru_F8FE00.uNumPointers <= 0 ? (v17 = 0) : (v17 = static_sub_4C1026_stru_F8FE00.array_1804[0]),
+     && ((signed int)static_sub_4C1026_stru_F8FE00.uNumPointers <= 0 ? (v17 = 0) : (v17 = static_sub_4C1026_stru_F8FE00.object_pointers[0]),
          result != v17)) )
     result = 0;
   return result;
@@ -221,13 +229,13 @@
 
   memcpy(static_sub_4C1495_array_F8DDF8, Src, 48 * a2);
   sort_objects_2(static_sub_4C1495_array_F8DDF8, 0, a2 - 1);
-  *a3 = (*(float *)&Vis_static_sub_4C1944_stru_F8BDE8.array_1804[12 * a2 + 509]
+  *a3 = (*(float *)&Vis_static_sub_4C1944_stru_F8BDE8.object_pointers[12 * a2 + 509]
        - static_sub_4C1495_array_F8DDF8[0].vWorldViewProjX)
       * 0.5
       + static_sub_4C1495_array_F8DDF8[0].vWorldViewProjX;
   sort_objects_3(static_sub_4C1495_array_F8DDF8, 0, a2 - 1);
   result = a4;
-  *a4 = (*(float *)&Vis_static_sub_4C1944_stru_F8BDE8.array_1804[12 * a2 + 510]
+  *a4 = (*(float *)&Vis_static_sub_4C1944_stru_F8BDE8.object_pointers[12 * a2 + 510]
        - static_sub_4C1495_array_F8DDF8[0].vWorldViewProjY)
       * 0.5
       + static_sub_4C1495_array_F8DDF8[0].vWorldViewProjY;
@@ -235,46 +243,27 @@
 }
 
 //----- (004C1542) --------------------------------------------------------
-void Vis::PickBillboards(float fPickDepth, float fX, float fY, Vis_stru1 *a4, stru157 *a2)
+void Vis::PickBillboards_Mouse(float fPickDepth, float fX, float fY, Vis_SelectionList *list, Vis_SelectionFilter *filter)
 {
-  int v6; // ST1C_4@6
-  Vis_stru1_stru0 *v7; // edi@6
-  Vis *thisa; // [sp+20h] [bp-Ch]@1
-  RenderBillboardD3D *v9; // [sp+24h] [bp-8h]@2
-  unsigned int uD3DBillboardIdx; // [sp+28h] [bp-4h]@1
-
-  uD3DBillboardIdx = 0;
-  thisa = this;
-  if ( (signed int)pRenderer->uNumBillboardsToDraw > 0 )
+  for (uint i = 0; i < pRenderer->uNumBillboardsToDraw; ++i)
   {
-    v9 = pRenderer->pBillboardRenderListD3D;//[0].uParentBillboardID;
-    do
+    auto d3d_billboard = pRenderer->pBillboardRenderListD3D + i;
+    if (is_part_of_selection((void *)i, filter) && IsPointInsideD3DBillboard(d3d_billboard, fX, fY))
     {
-      if ( is_part_of_selection((BLVFace *)uD3DBillboardIdx, a2)
-        && IsPointInsideD3DBillboard((RenderBillboardD3D *)(v9 - 38), fX, fY) )
+      if (DoesRayIntersectBillboard(fPickDepth, i))
       {
-        if ( DoesRayIntersectBillboard(fPickDepth, uD3DBillboardIdx) )
-        {
-          v6 = pBillboardRenderList[v9->uParentBillboardID].sZValue;
-          v7 = &a4->array_0004[a4->uNumPointers];
-		  v7->pObjectInfo = (void *)v9->uParentBillboardID;
-          v7 = (Vis_stru1_stru0 *)((char *)v7 + 4);
-          v7->pObjectInfo = (void *)v6;
-          v7->sZValue = 1;
-          ++a4->uNumPointers;
-        }
+        auto billboard = &pBillboardRenderList[d3d_billboard->uParentBillboardID];
+
+        list->AddObject((void *)d3d_billboard->uParentBillboardID, VisObjectType_Sprite, billboard->sZValue);
       }
-      ++uD3DBillboardIdx;
-      ++v9;
     }
-    while ( (signed int)uD3DBillboardIdx < (signed int)pRenderer->uNumBillboardsToDraw );
   }
 }
 
 //----- (004C1607) --------------------------------------------------------
 bool Vis::IsPointInsideD3DBillboard(RenderBillboardD3D *a1, float x, float y)
 {
-  RenderBillboardD3D *result; // eax@1
+  //RenderBillboardD3D *result; // eax@1
   double v5; // st7@2
   float v6; // ecx@2
   float v7; // ST00_4@3
@@ -302,27 +291,28 @@
   float v29; // [sp+8h] [bp-4h]@2
   float a1a; // [sp+14h] [bp+8h]@2
 
-  result = a1;
   if ( a1->uParentBillboardID == -1 )
-    goto LABEL_14;
+    return false;
+
+  //result = a1;
   v5 = a1->pQuards[0].pos.x;
   a1a = a1->pQuards[3].pos.x;
-  v6 = result->pQuards[0].pos.y;
-  result = (RenderBillboardD3D *)LODWORD(result->pQuards[1].pos.y);
+  v6 = a1->pQuards[0].pos.y;
+  //result = (RenderBillboardD3D *)LODWORD(result->pQuards[1].pos.y);
   v29 = v6;
-  LODWORD(v28) = (int)result;
+  v28 = a1->pQuards[1].pos.y;
   if ( v5 > a1a )
   {
     v7 = v5;
-    HIWORD(result) = HIWORD(v7);
+    //HIWORD(result) = HIWORD(v7);
     v5 = a1a;
     a1a = v7;
   }
   if ( v6 > (double)v28 )
   {
-    result = (RenderBillboardD3D *)LODWORD(v28);
+    //result = (RenderBillboardD3D *)LODWORD(v28);
     v28 = v6;
-    LODWORD(v29) = (int)result;
+    v29 = v28;
   }
   v9 = x + 1.0;
   //UNDEF(v8);
@@ -330,19 +320,17 @@
   //v11 = 0;
   //v12 = v9 == v5;
   //BYTE1(result) = HIBYTE(v8);//crash
-  if ( v9 >= v5
-    && (v14 = x - 1.0, v14<=a1a)///*UNDEF(v13),*/ v15 = v14 < a1a, v16 = 0, v17 = v14 == a1a, BYTE1(result) = HIBYTE(v13), v15 | v17)
-    && (v19 = y + 1.0, v19>=v29)///*UNDEF(v18),*/ v20 = v19 < v29, v21 = 0, v22 = v19 == v29, BYTE1(result) = HIBYTE(v18), v19 >= v29)
-    && (v24 = y - 1.0, v24<=v28))///*UNDEF(v23),*/ v25 = v24 < v28, v26 = 0, v27 = v24 == v28, BYTE1(result) = HIBYTE(v23), v25 | v27) )
-    LOBYTE(result) = 1;
+  if (v9 >= v5 &&
+      (v14 = x - 1.0, v14<=a1a) &&///*UNDEF(v13),*/ v15 = v14 < a1a, v16 = 0, v17 = v14 == a1a, BYTE1(result) = HIBYTE(v13), v15 | v17)
+      (v19 = y + 1.0, v19>=v29) &&///*UNDEF(v18),*/ v20 = v19 < v29, v21 = 0, v22 = v19 == v29, BYTE1(result) = HIBYTE(v18), v19 >= v29)
+      (v24 = y - 1.0, v24<=v28))///*UNDEF(v23),*/ v25 = v24 < v28, v26 = 0, v27 = v24 == v28, BYTE1(result) = HIBYTE(v23), v25 | v27) )
+    return true;
   else
-LABEL_14:
-    LOBYTE(result) = 0;
-  return (bool)result;
+    return false;
 }
 
 //----- (004C16B4) --------------------------------------------------------
-void Vis::PickIndoor(float fDepth, RenderVertexSoft *pRay, Vis_stru1 *a4, stru157 *a5)
+void Vis::PickIndoor(float fDepth, RenderVertexSoft *pRay, Vis_SelectionList *list, Vis_SelectionFilter *filter)
 {
   int v5; // eax@1
   signed int v6; // edi@2
@@ -351,7 +339,7 @@
   int v9; // eax@7
   unsigned int *pNumPointers; // eax@7
   unsigned int v11; // ecx@7
-  Vis_stru1_stru0 *v12; // edi@7
+  Vis_ObjectInfo *v12; // edi@7
   RenderVertexSoft a1; // [sp+Ch] [bp-44h]@1
   BLVFace *v14; // [sp+3Ch] [bp-14h]@7
   void *v15; // [sp+40h] [bp-10h]@7
@@ -370,7 +358,7 @@
       if ( v6 < (signed int)pIndoor->uNumFaces )
       {
         v7 = v6;
-        if ( is_part_of_selection(&pIndoor->pFaces[v6], a5) )
+        if ( is_part_of_selection(&pIndoor->pFaces[v6], filter) )
         {
           if ( !pGame->pIndoorCameraD3D->IsCulled(&pIndoor->pFaces[v7]) )
           {
@@ -380,14 +368,14 @@
               v9 = _48B561_mess_with_scaling_along_z(/*v8, */a1.vWorldViewPosition.x);
               LOWORD(v9) = 0;
               v15 = (void *)((8 * v6 | 6) + v9);
-              pNumPointers = &a4->uNumPointers;
+              pNumPointers = &list->uNumPointers;
               v16 = 2;
-              v11 = a4->uNumPointers;
+              v11 = list->uNumPointers;
               v14 = &pIndoor->pFaces[v7];
-              v12 = &a4->array_0004[v11];
-              v12->pObjectInfo = &pIndoor->pFaces[v7];
-              v12 = (Vis_stru1_stru0 *)((char *)v12 + 4);
-              v12->pObjectInfo = v15;
+              v12 = &list->object_pool[v11];
+              v12->object = &pIndoor->pFaces[v7];
+              v12 = (Vis_ObjectInfo *)((char *)v12 + 4);
+              v12->object = v15;
               v12->sZValue = v16;
               ++*pNumPointers;
             }
@@ -400,7 +388,7 @@
 }
 
 //----- (004C17CF) --------------------------------------------------------
-void Vis::PickOutdoor(float fDepth, RenderVertexSoft *pRay, Vis_stru1 *a4, stru157 *a5, char a6)
+void Vis::PickOutdoor(float fDepth, RenderVertexSoft *pRay, Vis_SelectionList *list, Vis_SelectionFilter *filter, char a6)
 {
   int v6; // esi@1
   unsigned int v7; // ecx@1
@@ -411,7 +399,7 @@
   int v12; // ecx@12
   int v13; // eax@12
   unsigned int *pNumPointers; // eax@12
-  Vis_stru1_stru0 *v15; // edi@12
+  Vis_ObjectInfo *v15; // edi@12
   BLVFace thisa; // [sp+10h] [bp-B8h]@1
   RenderVertexSoft a1; // [sp+70h] [bp-58h]@1
   void *v18; // [sp+A0h] [bp-28h]@12
@@ -454,7 +442,7 @@
             do
             {
               v11 = (ODMFace *)((char *)v8->pFaces + v23);
-              if ( is_part_of_selection((BLVFace *)((char *)v8->pFaces + v23), a5) )
+              if ( is_part_of_selection((BLVFace *)((char *)v8->pFaces + v23), filter) )
               {
                 thisa.FromODM(v11);
                 if ( Intersect_Ray_Face(pRay, pRay + 1, &fDepth, &a1, &thisa, v26) )
@@ -465,11 +453,11 @@
                   LOWORD(v13) = 0;
                   v20 = 2;
                   v19 = (void *)((8 * (v27 | (v26 << 6)) | 6) + v13);
-                  pNumPointers = &a4->uNumPointers;
-                  v15 = &a4->array_0004[a4->uNumPointers];
-                  v15->pObjectInfo = v18;
-                  v15 = (Vis_stru1_stru0 *)((char *)v15 + 4);
-                  v15->pObjectInfo = v19;
+                  pNumPointers = &list->uNumPointers;
+                  v15 = &list->object_pool[list->uNumPointers];
+                  v15->object = v18;
+                  v15 = (Vis_ObjectInfo *)((char *)v15 + 4);
+                  v15->object = v19;
                   v15->sZValue = v20;
                   ++*pNumPointers;
                 }
@@ -501,39 +489,38 @@
 //{return DoesRayIntersectBillboard(fDepth, uD3DBillboardIdx);}
 
 //----- (004C1944) --------------------------------------------------------
-int Vis::_4C1944(int a2, unsigned int a3, int a4, int a5, int a6)
+int Vis::_4C1944(int object_id, unsigned int a3, int a4, int a5, int a6)
 {
   float v6; // ST00_4@3
   int result; // eax@4
-  stru157 v8; // [sp+18h] [bp-20h]@3
+  Vis_SelectionFilter v8; // [sp+18h] [bp-20h]@3
   __int64 v9; // [sp+2Ch] [bp-Ch]@3
   Vis *v14; // [sp+34h] [bp-4h]@1
 
   v14 = this;
 
-  static Vis_stru1 Vis_static_sub_4C1944_stru_F8BDE8;
+  static Vis_SelectionList Vis_static_sub_4C1944_stru_F8BDE8;
 
-  v8.field_4 = a2;
+  v8.object_id = object_id;
   v8.field_8 = a6;
   v8.field_C = a5;
   v8.field_10 = a4;
   v9 = a3;
   Vis_static_sub_4C1944_stru_F8BDE8.uNumPointers = 0;
   v6 = (double)a3;
-  v8.field_0 = 1;
-  _4C06F8(v6, &Vis_static_sub_4C1944_stru_F8BDE8, &v8);
-  Vis_static_sub_4C1944_stru_F8BDE8.create_object_pointers(1u);
+  v8.object_type = VisObjectType_Sprite;
+  PickBillboards_All(v6, &Vis_static_sub_4C1944_stru_F8BDE8, &v8);
+  Vis_static_sub_4C1944_stru_F8BDE8.create_object_pointers(Vis_SelectionList::Unique);
   sort_object_pointers(
-    Vis_static_sub_4C1944_stru_F8BDE8.array_1804,
+    Vis_static_sub_4C1944_stru_F8BDE8.object_pointers,
     0,
     Vis_static_sub_4C1944_stru_F8BDE8.uNumPointers - 1);
   if ( (signed int)Vis_static_sub_4C1944_stru_F8BDE8.uNumPointers <= 0 )
     result = -1;
   else
-    result = Vis_static_sub_4C1944_stru_F8BDE8.array_1804[0]->sZValue;
+    result = Vis_static_sub_4C1944_stru_F8BDE8.object_pointers[0]->sZValue;
   return result;
 }
-// F8DDF0: using guessed type char Vis_static_sub_4C1944_byte_F8DDF0_init;
 
 //----- (004C1A02) --------------------------------------------------------
 void Vis::_4C1A02()
@@ -626,39 +613,27 @@
 }
 
 //----- (004C1BAA) --------------------------------------------------------
-int Vis::get_object_zbuf_val(Vis_stru1_stru0 *a2)
+int Vis::get_object_zbuf_val(Vis_ObjectInfo *info)
 {
-  unsigned int v2; // eax@1
-  int result; // eax@3
-  std::string v4; // [sp-18h] [bp-1Ch]@4
-  const char *v5; // [sp-8h] [bp-Ch]@4
-  int v6; // [sp-4h] [bp-8h]@4
-  Vis *v7; // [sp+0h] [bp-4h]@1
+  switch (info->object_type)
+  {
+    case VisObjectType_Sprite:
+    case VisObjectType_Face:
+      return info->sZValue;
 
-  v7 = this;
-  v2 = a2->uObjectType;
-  if ( (signed int)v2 <= 0 || (signed int)v2 > 2 )
-  {
-    MessageBoxW(nullptr, L"Undefined type requested for: CVis::get_object_zbuf_val()", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Vis.cpp:1037", 0);
-    result = -1;
+    default:
+      MessageBoxW(nullptr, L"Undefined type requested for: CVis::get_object_zbuf_val()", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Vis.cpp:1037", 0);
+      return -1;
   }
-  else
-  {
-    result = a2->sZValue;
-  }
-  return result;
 }
 
 //----- (004C1BF1) --------------------------------------------------------
 int Vis::get_picked_object_zbuf_val()
 {
-  int result; // eax@2
+  if (!default_list.uNumPointers)
+    return -1;
 
-  if ( (signed int)this->stru1.uNumPointers <= 0 )
-    result = -1;
-  else
-    result = get_object_zbuf_val(this->stru1.array_1804[0]);
-  return result;
+  return get_object_zbuf_val(default_list.object_pointers[0]);
 }
 
 //----- (004C1C0C) --------------------------------------------------------
@@ -1126,12 +1101,12 @@
 }
 
 //----- (004C2551) --------------------------------------------------------
-Vis_stru1_stru0 *Vis_stru1::sub_4C2551(int a2, int a3)
+Vis_ObjectInfo *Vis_SelectionList::sub_4C2551(int a2, int a3)
 {
   unsigned int v3; // esi@1
   signed int v4; // edx@1
   char *v5; // eax@2
-  Vis_stru1_stru0 *result; // eax@6
+  Vis_ObjectInfo *result; // eax@6
 
   v3 = this->uNumPointers;
   v4 = 0;
@@ -1142,7 +1117,7 @@
   }
   else
   {
-    v5 = (char *)&this->array_0004[0].sZValue;
+    v5 = (char *)&this->object_pool[0].sZValue;
     while ( *((int *)v5 + 1) != a2 || (*(int *)v5 & 0xFFFF) != a3 )
     {
       ++v4;
@@ -1150,92 +1125,50 @@
       if ( v4 >= (signed int)v3 )
         goto LABEL_6;
     }
-    result = &this->array_0004[v4];
+    result = &this->object_pool[v4];
   }
   return result;
 }
 
 //----- (004C2591) --------------------------------------------------------
-Vis_stru1_stru0 **Vis_stru1::create_object_pointers(unsigned int flag)
+void Vis_SelectionList::create_object_pointers(PointerCreationType type)
 {
-  Vis_stru1_stru0 **result; // eax@1
-  signed int v3; // esi@2
-  Vis_stru1_stru0 *v4; // edx@3
-  unsigned __int8 v5; // zf@7
-  unsigned __int8 v6; // sf@7
-  Vis_stru1_stru0 **v7; // ebx@8
-  Vis_stru1_stru0 *v8; // esi@8
-  signed int v9; // edi@9
-  Vis_stru1_stru0 **v10; // edx@10
-  std::string v11; // [sp-18h] [bp-28h]@19
-  const char *v12; // [sp-8h] [bp-18h]@19
-  int v13; // [sp-4h] [bp-14h]@19
-  char v14; // [sp+Ch] [bp-4h]@19
+  switch (type)
+  {
+    case All:
+    {
+      for (uint i = 0; i < uNumPointers; ++i)
+        object_pointers[i] = &object_pool[i];
+    }
+    break;
 
-  result = 0;
-  if ( flag )
-  {
-    if ( flag == 1 )
-    {
-      v5 = this->uNumPointers == 0;
-      v6 = (this->uNumPointers & 0x80000000u) != 0;
-      BYTE3(flag) = 1;
-      if ( !(v6 | v5) )
+    case Unique: // seems quite retarted; the inner if condition will never trigger, since we compare pointers, not values. pointers will always be unique
+    {            // but it may be decompilation error thou
+      bool create = true;
+ 
+      for (uint i = 0; i < uNumPointers; ++i)
       {
-        v7 = this->array_1804;
-        v8 = this->array_0004;
-        do
+        for (uint j = 0; j < i; ++j)
         {
-          v9 = 0;
-          if ( (signed int)result > 0 )
+          if (object_pointers[j] == &object_pool[i])
           {
-            v10 = this->array_1804;
-            while ( *v10 != v8 )
-            {
-              ++v9;
-              ++v10;
-              if ( v9 >= (signed int)result )
-                goto LABEL_15;
-            }
-            BYTE3(flag) = 0;
+            create = false;
+            break;
           }
-LABEL_15:
-          if ( BYTE3(flag) )
-            *v7 = v8;
-          result = (Vis_stru1_stru0 **)((char *)result + 1);
-          ++v7;
-          ++v8;
         }
-        while ( (signed int)result < (signed int)this->uNumPointers );
+
+        if (create)
+          object_pointers[i] = &object_pool[i];
       }
     }
-    else
-    {
+
+    default:
       MessageBoxW(nullptr, L"Unknown pointer creation flag passed to ::create_object_pointers()", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Vis.cpp:1358", 0);
-    }
   }
-  else
-  {
-    v3 = 0;
-    if ( (signed int)this->uNumPointers > 0 )
-    {
-      result = this->array_1804;
-      v4 = this->array_0004;
-      do
-      {
-        *result = v4;
-        ++v3;
-        ++result;
-        ++v4;
-      }
-      while ( v3 < (signed int)this->uNumPointers );
-    }
-  }
-  return result;
 }
 
 //----- (004C264A) --------------------------------------------------------
-void Vis::sort_object_pointers(Vis_stru1_stru0 **pPointers, int left, int right)
+void Vis::sort_object_pointers(Vis_ObjectInfo **pPointers, int left, int right)
 {
   int v4; // edx@1
   int v5; // ebx@1
@@ -1244,9 +1177,9 @@
   int v8; // eax@3
   int v9; // ebx@4
   int v10; // ebx@6
-  Vis_stru1_stru0 *v11; // eax@7
+  Vis_ObjectInfo *v11; // eax@7
   Vis *thisa; // [sp+4h] [bp-4h]@1
-  Vis_stru1_stru0 *a3a; // [sp+14h] [bp+Ch]@2
+  Vis_ObjectInfo *a3a; // [sp+14h] [bp+Ch]@2
 
   v4 = left;
   v5 = right;
@@ -1410,9 +1343,8 @@
     memcpy(&v12, &v5[v8], sizeof(v12));
     memcpy(&v5[v8], v15, sizeof(v5[v8]));
     memcpy(v15, &v12, 0x20u);
-    //__debugbreak();
-    SortVerticesByX(v5, uStart, v8 - 1);
-    SortVerticesByX(a2, v8 + 1, uEnd);
+    SortVerticesByY(v5, uStart, v8 - 1);
+    SortVerticesByY(a2, v8 + 1, uEnd);
   }
   return true;
 }
@@ -1570,185 +1502,178 @@
 }
 
 //----- (004C055C) --------------------------------------------------------
-Vis_stru1::Vis_stru1()
+Vis_SelectionList::Vis_SelectionList()
 {
   for (uint i = 0; i < 512; ++i)
   {
-    array_0004[i].pObjectInfo = 0;
-    array_0004[i].sZValue = -1;
-    array_0004[i].uObjectType = 0;
+    object_pool[i].object = nullptr;
+    object_pool[i].sZValue = -1;
+    object_pool[i].object_type = VisObjectType_Any;
   }
   uNumPointers = 0;
 }
 
 //----- (004C05CC) --------------------------------------------------------
-bool Vis::PickKeyboard(Vis_stru1 *a2, stru157 *a3, stru157 *a4)
+bool Vis::PickKeyboard(Vis_SelectionList *list, Vis_SelectionFilter *sprite_filter, Vis_SelectionFilter *face_filter)
 {
-  Vis_stru1 *v4; // esi@1
-  Vis *v5; // ebx@1
-  char *v6; // edi@3
-  float v7; // ST00_4@3
-  bool result; // eax@6
-  float v9; // [sp+4h] [bp-14h]@3
+  if (!list)
+    list = &default_list;
+  list->uNumPointers = 0;
 
-  v4 = a2;
-  v5 = this;
-  if ( !a2 )
-    v4 = &this->stru1;
-  v4->uNumPointers = 0;
-  v6 = (char *)&this->field_20CC;
-  v7 = (double)this->field_20CC;
-  _4C06F8(v7, v4, a3);
-  v9 = (double)*(signed int *)v6;
-  if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
-    _4C0D32_BLV(v9, v4, a4);
+  PickBillboards_All(field_20CC, list, face_filter);
+  if (uCurrentlyLoadedLevelType == LEVEL_Indoor)
+    _4C0D32_KeyboardPickFaces_BLV(field_20CC, list, face_filter);
+  else if (uCurrentlyLoadedLevelType == LEVEL_Outdoor)
+    _4C0DEA_KeyboardPickFaces_ODM(field_20CC, list, face_filter);
   else
-    _4C0DEA_ODM(v9, v4, a4);
-  v4->create_object_pointers(1u);
-  sort_object_pointers(v4->array_1804, 0, v4->uNumPointers - 1);
+    assert(false);
+
+  list->create_object_pointers(Vis_SelectionList::Unique);
+  sort_object_pointers(list->object_pointers, 0, list->uNumPointers - 1);
+
   return true;
 }
 
 //----- (004C0646) --------------------------------------------------------
-bool Vis::PickMouse(float fDepth, float fMouseX, float fMouseY, stru157 *a5, stru157 *a6)
+bool Vis::PickMouse(float fDepth, float fMouseX, float fMouseY, Vis_SelectionFilter *sprite_filter, Vis_SelectionFilter *face_filter)
 {
   RenderVertexSoft pMouseRay[2]; // [sp+1Ch] [bp-60h]@1
 
-  stru1.uNumPointers = 0;
+  default_list.uNumPointers = 0;
   CastPickRay(pMouseRay, fMouseX, fMouseY, fDepth);
-  //PickBillboards(fDepth, fMouseX, fMouseY, &stru1, a5);//Ritor1: do comment to test
+  PickBillboards_Mouse(fDepth, fMouseX, fMouseY, &default_list, sprite_filter);
   if (uCurrentlyLoadedLevelType == LEVEL_Indoor)
-    PickIndoor(fDepth, pMouseRay, &stru1, a6);
+    PickIndoor(fDepth, pMouseRay, &default_list, face_filter);
   else
-    PickOutdoor(fDepth, pMouseRay, &stru1, a6, 0);
-  stru1.create_object_pointers(0);
-  sort_object_pointers(stru1.array_1804, 0, stru1.uNumPointers - 1);
+    PickOutdoor(fDepth, pMouseRay, &default_list, face_filter, 0);
+  default_list.create_object_pointers(Vis_SelectionList::All);
+  sort_object_pointers(default_list.object_pointers, 0, default_list.uNumPointers - 1);
+
   return true;
 }
 
 //----- (004C06F8) --------------------------------------------------------
-void Vis::_4C06F8(float arg0, Vis_stru1 *a3, stru157 *a2)
+void Vis::PickBillboards_All(float pick_depth, Vis_SelectionList *list, Vis_SelectionFilter *filter)
 {
-  int v4; // ST18_4@5
-  Vis_stru1_stru0 *v5; // edi@5
-  void **v7; // [sp+24h] [bp-8h]@2
-  unsigned int uD3DBillboardIdx; // [sp+28h] [bp-4h]@1
+  for (int i = 0; i < pRenderer->uNumBillboardsToDraw; ++i)
+  {
+    auto d3d_billboard = &pRenderer->pBillboardRenderListD3D[i];
 
-  uD3DBillboardIdx = 0;
-  auto ecx0 = this;
-  if ( (signed int)pRenderer->uNumBillboardsToDraw > 0 )
-  {
-    v7 = (void **)&pRenderer->pBillboardRenderListD3D[0].uParentBillboardID;
-    do
+    if (is_part_of_selection((void *)i, filter))
     {
-      if ( is_part_of_selection((BLVFace *)uD3DBillboardIdx, a2) )
+      if (DoesRayIntersectBillboard(pick_depth, i))
       {
-        if ( DoesRayIntersectBillboard(arg0, uD3DBillboardIdx) )
-        {
-          v4 = pBillboardRenderList[(int)*v7].sZValue;
-          v5 = &a3->array_0004[a3->uNumPointers];
-          v5->pObjectInfo = *v7;
-          v5 = (Vis_stru1_stru0 *)((char *)v5 + 4);
-          v5->pObjectInfo = (void *)v4;
-          v5->sZValue = 1;
-          ++a3->uNumPointers;
-        }
+        auto billboard = &pBillboardRenderList[d3d_billboard->uParentBillboardID];
+
+        list->AddObject((void *)d3d_billboard->uParentBillboardID, VisObjectType_Sprite, billboard->sZValue);
       }
-      ++uD3DBillboardIdx;
-      v7 += 39;
     }
-    while ( (signed int)uD3DBillboardIdx < (signed int)pRenderer->uNumBillboardsToDraw );
   }
 }
 
+
+// tests the object against selection filter to determine whether it can be picked or not
 //----- (004C0791) --------------------------------------------------------
-bool Vis::is_part_of_selection(BLVFace *uD3DBillboardIdx_or_pBLVFace_or_pODMFace, stru157 *a2)
+bool Vis::is_part_of_selection(void *uD3DBillboardIdx_or_pBLVFace_or_pODMFace, Vis_SelectionFilter *filter)
 {
-  stru157 *v3; // esi@1
-  int result; // eax@1
+  //stru157 *v3; // esi@1
+  //int result; // eax@1
   int v5; // edx@2
-  int v6; // ecx@2
-  char v7; // zf@3
+  //int v6; // ecx@2
+  //char v7; // zf@3
   int v8; // esi@5
   std::string *v9; // ecx@7
   Actor *v10; // edi@18
-  char v11; // zf@26
-  const char *v12; // [sp-20h] [bp-2Ch]@7
+  //const char *v12; // [sp-20h] [bp-2Ch]@7
   int v13; // [sp-1Ch] [bp-28h]@7
-  std::string v14; // [sp-18h] [bp-24h]@7
-  const char *v15; // [sp-8h] [bp-14h]@7
+  //std::string v14; // [sp-18h] [bp-24h]@7
+  //const char *v15; // [sp-8h] [bp-14h]@7
   int v16; // [sp-4h] [bp-10h]@7
 
-  v3 = a2;
-  result = a2->field_0;
-  if ( a2->field_0 != 1 )
+  switch (filter->object_type)
   {
-    if ( result != 2
-      || (uCurrentlyLoadedLevelType != LEVEL_Indoor ? (v11 = LOWORD(uD3DBillboardIdx_or_pBLVFace_or_pODMFace[3].pFacePlane.vNormal.y) == 0,
-                                            result = uD3DBillboardIdx_or_pBLVFace_or_pODMFace->pFacePlane_old.dist) : (v11 = pIndoor->pFaceExtras[uD3DBillboardIdx_or_pBLVFace_or_pODMFace->uFaceExtraID].uEventID == 0, result = uD3DBillboardIdx_or_pBLVFace_or_pODMFace->uAttributes),
-          a2->field_4 != 1) )
-      goto LABEL_16;
-    if ( v11 || result & a2->field_C )
-      goto LABEL_33;
-    v7 = (result & a2->field_8) == 0;
-    goto LABEL_32;
-  }
-  v5 = a2->field_10;
-  result = (pBillboardRenderList[pRenderer->pBillboardRenderListD3D[(int)uD3DBillboardIdx_or_pBLVFace_or_pODMFace].uParentBillboardID].sZValue & 0xFFFF) >> 3;
-  v6 = pBillboardRenderList[pRenderer->pBillboardRenderListD3D[(int)uD3DBillboardIdx_or_pBLVFace_or_pODMFace].uParentBillboardID].sZValue & 7;
-  if ( v5 & 2 )
-  {
-    v7 = v6 == a2->field_4;
-    goto LABEL_32;
-  }
-  if ( v5 & 4 )
-  {
-    v8 = a2->field_4;
-    if ( v6 != v8 )
-      goto LABEL_16;
-    if ( v8 != 5 )
+    case VisObjectType_Any:
+      return true;
+
+    case VisObjectType_Sprite:
     {
-      v15 = "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Vis.cpp:207";
-      v12 = "Unsupported \"exclusion if no event\" type in CVis::is_part_of_selection";
-LABEL_15:
-          MessageBoxA(nullptr, v12, v15, 0);
-      return true;
+      v5 = filter->field_10;
+      int object_idx = (pBillboardRenderList[pRenderer->pBillboardRenderListD3D[(int)uD3DBillboardIdx_or_pBLVFace_or_pODMFace].uParentBillboardID].object_pid & 0xFFFF) >> 3;
+      int object_type = pBillboardRenderList[pRenderer->pBillboardRenderListD3D[(int)uD3DBillboardIdx_or_pBLVFace_or_pODMFace].uParentBillboardID].object_pid & 7;
+      if ( v5 & 2 )
+      {
+        if (object_type == filter->object_id)
+          return false;
+        return true;
+      }
+      if ( v5 & 4 )
+      {
+        v8 = filter->object_id;
+        if ( object_type != filter->object_id)
+          return true;
+        if (v8 != OBJECT_Decoration)
+        {
+          MessageBoxA(nullptr, "Unsupported \"exclusion if no event\" type in CVis::is_part_of_selection", "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Vis.cpp:207", 0);
+          return true;
+        }
+        if (pLevelDecorations[object_idx].uCog || pLevelDecorations[object_idx].field_16_event_id)
+          return true;
+        return pLevelDecorations[object_idx].IsInteractive();
+      }
+      if (object_type == filter->object_id)
+      {
+        if (object_type != OBJECT_Actor)
+        {
+          MessageBoxA(nullptr, "Default case reached in VIS", "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Vis.cpp:245", 0);
+          return true;
+        }
+
+        v10 = &pActors[object_idx];
+        int result = 1 << LOBYTE(v10->uAIState);
+        if ( result & filter->field_C
+            || !(result & filter->field_8)
+            || v5 & 8 && (result = MonsterStats::BelongsToSupertype(v10->pMonsterInfo.uID, MONSTER_SUPERTYPE_UNDEAD)) == 0 )
+          return false;
+        if ( !(filter->field_10 & 1) )
+          return true;
+
+        result = v10->GetActorsRelation(nullptr);
+        if (result == 0)
+          return false;
+        return true;
+      }
+      return false;
     }
-    result *= 32;
-    if ( *(__int16 *)((char *)&pLevelDecorations[0].uCog + result)
-      || *(__int16 *)((char *)&pLevelDecorations[0].field_16_event_id + result) )
-      goto LABEL_16;
-    result = pLevelDecorations[result / sizeof(LevelDecoration)].IsInteractive();
-    goto LABEL_11;
-  }
-  if ( v6 == a2->field_4 )
-  {
-    if ( v6 != 3 )
+
+    case VisObjectType_Face:
     {
-      v15 = "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Vis.cpp:245";
-      v12 = "Default case reached in VIS";
-      goto LABEL_15;
+      uint face_attrib = 0;
+      bool no_event = true;
+      if (uCurrentlyLoadedLevelType == LEVEL_Outdoor)
+      {
+        auto face = (ODMFace *)uD3DBillboardIdx_or_pBLVFace_or_pODMFace;
+        no_event = face->sCogTriggeredID == 0;
+        face_attrib = face->uAttributes;
+      }
+      else if (uCurrentlyLoadedLevelType == LEVEL_Indoor) 
+      {
+        auto face = (BLVFace *)uD3DBillboardIdx_or_pBLVFace_or_pODMFace;
+        no_event = pIndoor->pFaceExtras[face->uFaceExtraID].uEventID == 0;
+        face_attrib = face->uAttributes;
+      }
+      else
+        assert(false);
+
+      if (filter->object_id != OBJECT_BLVDoor)
+        return true;
+      if (no_event || face_attrib & filter->field_C)
+        return false;
+      return (face_attrib & filter->field_8) != 0;
     }
-    v10 = &pActors[result];
-    result = 1 << LOBYTE(v10->uAIState);
-    if ( result & a2->field_C
-      || !(result & a2->field_8)
-      || v5 & 8 && (result = MonsterStats::BelongsToSupertype(v10->pMonsterInfo.uID, MONSTER_SUPERTYPE_UNDEAD)) == 0 )
-      goto LABEL_33;
-    if ( !(v3->field_10 & 1) )
-      goto LABEL_16;
-    result = v10->GetActorsRelation(nullptr);
-LABEL_11:
-    v7 = result == 0;
-LABEL_32:
-    if ( v7 )
-      goto LABEL_33;
-LABEL_16:
-    return true;
+
+    default:
+      assert(false);
   }
-LABEL_33:
-  LOBYTE(result) = 0;
-  return result;
 }
 
 //----- (004C091D) --------------------------------------------------------
@@ -1758,8 +1683,8 @@
   //signed int v5; // ecx@4
   //float v6; // ST04_4@6
   //float v7; // ST00_4@7
-  int v8; // eax@10
-  unsigned int v9; // eax@12
+  //int v8; // eax@10
+  //unsigned int v9; // eax@12
   int v10; // eax@17
   double v11; // st6@18
   double v12; // st7@18
@@ -1768,8 +1693,8 @@
   float v15; // ST08_4@22
   //float v16; // ST04_4@23
   //float v17; // ST00_4@24
-  signed int v18; // eax@27
-  unsigned int v19; // eax@29
+  //signed int v18; // eax@27
+  //unsigned int v19; // eax@29
   double v20; // st6@32
   double v21; // st7@32
   int v22; // eax@32
@@ -1789,13 +1714,13 @@
   float v34; // [sp+E4h] [bp-18h]@32
   int v35; // [sp+E8h] [bp-14h]@5
   int v36; // [sp+ECh] [bp-10h]@5
-  unsigned int v37; // [sp+F0h] [bp-Ch]@5
+  int v37; // [sp+F0h] [bp-Ch]@5
   float v38; // [sp+F4h] [bp-8h]@17
   //void *v39; // [sp+F8h] [bp-4h]@1
   signed int v40; // [sp+108h] [bp+Ch]@17
   float v41; // [sp+108h] [bp+Ch]@32
 
-  static Vis_stru1 Vis_static_stru_F91E10;
+  static Vis_SelectionList Vis_static_stru_F91E10;
   Vis_static_stru_F91E10.uNumPointers = 0;
   v3 = pRenderer->pBillboardRenderListD3D[uD3DBillboardIdx].uParentBillboardID;
   if (v3 == -1)
@@ -1805,26 +1730,20 @@
 LABEL_49:
     return false;
   }
-  else
-  {
+
     v37 = pBillboardRenderList[v3].sZValue & 0xFFFF0000;
     GetPolygonCenter(pRenderer->pBillboardRenderListD3D[v3].pQuards, 4, (float *)&v35, (float *)&v36);
-    this->CastPickRay(pPickingRay, *(float *)&v35, *(float *)&v36, fDepth);
-    if (uCurrentlyLoadedLevelType == 1)
-      PickIndoor(fDepth, pPickingRay, &Vis_static_stru_F91E10, &a5);
+    CastPickRay(pPickingRay, *(float *)&v35, *(float *)&v36, fDepth);
+    if (uCurrentlyLoadedLevelType == LEVEL_Indoor)
+      PickIndoor(fDepth, pPickingRay, &Vis_static_stru_F91E10, &vis_face_filter);
     else
-      PickOutdoor(fDepth, pPickingRay, &Vis_static_stru_F91E10, &a5, 0);
-    Vis_static_stru_F91E10.create_object_pointers(0);
-    sort_object_pointers(Vis_static_stru_F91E10.array_1804, 0, Vis_static_stru_F91E10.uNumPointers - 1);
+      PickOutdoor(fDepth, pPickingRay, &Vis_static_stru_F91E10, &vis_face_filter, 0);
+    Vis_static_stru_F91E10.create_object_pointers();
+    sort_object_pointers(Vis_static_stru_F91E10.object_pointers, 0, Vis_static_stru_F91E10.uNumPointers - 1);
     if (Vis_static_stru_F91E10.uNumPointers)
     {
-     if (Vis_static_stru_F91E10.uNumPointers <= 0)
-       v8 = 0;
-     else v8 = (int)Vis_static_stru_F91E10.array_1804;
-     v9 = *(_DWORD *)(v8 + 4);
-     LOWORD(v9) = 0;
-     if (v9 > v37)
-       return 1;
+       if (Vis_static_stru_F91E10.object_pointers[0]->actual_z > pBillboardRenderList[v3].actual_z)
+         return 1;
     }
     else if ((double)(pViewport->uScreenX) <= *(float *)&v35 &&
              (double)pViewport->uScreenZ >= *(float *)&v35 &&
@@ -1852,18 +1771,21 @@
                 v15 = v12;
                 CastPickRay(local_80, SLODWORD(v15), v14, fDepth);
                 if ( uCurrentlyLoadedLevelType == 1 )
-                  PickIndoor(fDepth, local_80, &Vis_static_stru_F91E10, &a5);
+                  PickIndoor(fDepth, local_80, &Vis_static_stru_F91E10, &vis_face_filter);
                 else
-                  PickOutdoor(fDepth, local_80, &Vis_static_stru_F91E10, &a5, 0);
-                Vis_static_stru_F91E10.create_object_pointers(0);
-                sort_object_pointers(Vis_static_stru_F91E10.array_1804, 0, Vis_static_stru_F91E10.uNumPointers - 1);
+                  PickOutdoor(fDepth, local_80, &Vis_static_stru_F91E10, &vis_face_filter, 0);
+                Vis_static_stru_F91E10.create_object_pointers();
+                sort_object_pointers(Vis_static_stru_F91E10.object_pointers, 0, Vis_static_stru_F91E10.uNumPointers - 1);
                 if ( !Vis_static_stru_F91E10.uNumPointers )
                   break;
-                v18 = Vis_static_stru_F91E10.uNumPointers <= 0 ? 0 : (int)Vis_static_stru_F91E10.array_1804;
-                v19 = *(_DWORD *)(v18 + 4);
-                LOWORD(v19) = 0;
-                if ( v19 > v37 )
+                else
+                {
+                //v18 = Vis_static_stru_F91E10.uNumPointers <= 0 ? 0 : (int);
+                //v19 = *(_DWORD *)(v18 + 4);
+                //LOWORD(v19) = 0;
+                if (Vis_static_stru_F91E10.object_pointers[0]->actual_z > pBillboardRenderList[v3].actual_z)
                   break;
+                }
               }
             }
           }
@@ -1896,12 +1818,12 @@
             || (double)pViewport->uScreenY > v41
             || (double)pViewport->uScreenW < v41
             || ((v25 = v23, CastPickRay(local_80, SLODWORD(v25), v41, fDepth), uCurrentlyLoadedLevelType != 1) ? 
-             (PickOutdoor(fDepth, local_80, &Vis_static_stru_F91E10, &a5, 0)) : 
-             (PickIndoor(fDepth, local_80, &Vis_static_stru_F91E10, &a5)),
-             (Vis_static_stru_F91E10.create_object_pointers(0),
-              sort_object_pointers(Vis_static_stru_F91E10.array_1804, 0, Vis_static_stru_F91E10.uNumPointers - 1),
+             (PickOutdoor(fDepth, local_80, &Vis_static_stru_F91E10, &vis_face_filter, 0)) : 
+             (PickIndoor(fDepth, local_80, &Vis_static_stru_F91E10, &vis_face_filter)),
+             (Vis_static_stru_F91E10.create_object_pointers(),
+              sort_object_pointers(Vis_static_stru_F91E10.object_pointers, 0, Vis_static_stru_F91E10.uNumPointers - 1),
               Vis_static_stru_F91E10.uNumPointers)
-             && (Vis_static_stru_F91E10.uNumPointers <= 0 ? (v28 = 0) : (v28 = (int)Vis_static_stru_F91E10.array_1804),
+             && (Vis_static_stru_F91E10.uNumPointers <= 0 ? (v28 = 0) : (v28 = (int)Vis_static_stru_F91E10.object_pointers),
                  v29 = *(_DWORD *)(v28 + 4),
                  LOWORD(v29) = 0,
                  v29 <= v37)) )
@@ -1909,23 +1831,21 @@
           break;
         }
       }
-    result = 1;
-  }
-  return result;
+  return true;
 }
 // F93E18: using guessed type char static_byte_F93E18_init;
 
 //----- (004C0D32) --------------------------------------------------------
-int Vis::_4C0D32_BLV(float a1, Vis_stru1 *arg4, stru157 *a2)
+int Vis::_4C0D32_KeyboardPickFaces_BLV(float pick_depth, Vis_SelectionList *list, Vis_SelectionFilter *filter)
 {
   int result; // eax@1
   signed int v5; // esi@2
   BLVFace *v6; // edi@4
   unsigned int v7; // eax@6
-  Vis_stru1_stru0 *v8; // eax@6
-  int v9; // ST18_4@7
-  unsigned int v10; // ST1C_4@7
-  unsigned int v11; // ecx@7
+  Vis_ObjectInfo *v8; // eax@6
+  //int v9; // ST18_4@7
+  //unsigned int v10; // ST1C_4@7
+  //unsigned int v11; // ecx@7
   signed int i; // [sp+18h] [bp-8h]@1
   Vis *thisa; // [sp+1Ch] [bp-4h]@1
 
@@ -1941,21 +1861,13 @@
         v6 = &pIndoor->pFaces[v5];
         if ( !pGame->pIndoorCameraD3D->IsCulled(&pIndoor->pFaces[v5]) )
         {
-          if ( is_part_of_selection(v6, a2) )
+          if ( is_part_of_selection(v6, filter) )
           {
             v7 = 8 * v5;
-            LOBYTE(v7) = 8 * v5 | 6;
-            v8 = _4C1026(v6, v7, a1);
+            LOBYTE(v7) = 8 * v5 | OBJECT_BModel;
+            v8 = _4C1026(v6, v7, pick_depth);
             if ( v8 )
-            {
-              v9 = v8->sZValue;
-              v10 = v8->uObjectType;
-              v11 = 3 * arg4->uNumPointers;
-              arg4->array_0004[arg4->uNumPointers].pObjectInfo = v8->pObjectInfo;
-              arg4->array_0004[4 * v11 / 0xC].sZValue = v9;
-              arg4->array_0004[4 * v11 / 0xC].uObjectType = v10;
-              ++arg4->uNumPointers;
-            }
+              list->AddObject(v8->object, v8->object_type, v8->sZValue);
           }
         }
       }
@@ -1966,7 +1878,7 @@
 }
 
 //----- (004C0DEA) --------------------------------------------------------
-void Vis::_4C0DEA_ODM(float arg0, Vis_stru1 *a3, stru157 *a2)
+void Vis::_4C0DEA_KeyboardPickFaces_ODM(float pick_depth, Vis_SelectionList *list, Vis_SelectionFilter *filter)
 {
   int v4; // esi@1
   BSPModel *v5; // ebx@3
@@ -1975,12 +1887,12 @@
   unsigned __int8 v8; // of@5
   ODMFace *v9; // esi@7
   unsigned int v10; // eax@8
-  Vis_stru1_stru0 *v11; // eax@8
-  unsigned int v12; // ecx@9
+  Vis_ObjectInfo *v11; // eax@8
+  //unsigned int v12; // ecx@9
   BLVFace f; // [sp+10h] [bp-84h]@1
-  void *v14; // [sp+70h] [bp-24h]@9
-  int v15; // [sp+74h] [bp-20h]@9
-  unsigned int v16; // [sp+78h] [bp-1Ch]@9
+  //void *v14; // [sp+70h] [bp-24h]@9
+  //int v15; // [sp+74h] [bp-20h]@9
+  //unsigned int v16; // [sp+78h] [bp-1Ch]@9
   int v17; // [sp+7Ch] [bp-18h]@1
   Vis *v18; // [sp+80h] [bp-14h]@1
   int v19; // [sp+84h] [bp-10h]@6
@@ -2013,23 +1925,24 @@
             do
             {
               v9 = (ODMFace *)((char *)v5->pFaces + v19);
-              if ( is_part_of_selection((BLVFace *)((char *)v5->pFaces + v19), a2) )
+              if ( is_part_of_selection((BLVFace *)((char *)v5->pFaces + v19), filter) )
               {
                 f.FromODM(v9);
                 v10 = 8 * (v21 | (a1 << 6));
-                LOBYTE(v10) = v10 | 6;
-                v11 = _4C1026(&f, v10, arg0);
+                LOBYTE(v10) = v10 | OBJECT_BModel;
+                v11 = _4C1026(&f, v10, pick_depth);
                 if ( v11 )
                 {
-                  v14 = v11->pObjectInfo;
+                  /*v14 = v11->object;
                   v15 = v11->sZValue;
                   v12 = a3->uNumPointers;
-                  v16 = v11->uObjectType;
+                  //v16 = v11->uObjectType;
                   v12 *= 3;
-                  *((int *)&a3->array_0004[0].pObjectInfo + v12) = (int)v14;
-                  *(&a3->array_0004[0].sZValue + v12) = v15;
-                  *(&a3->array_0004[0].uObjectType + v12) = v16;
-                  ++a3->uNumPointers;
+                  *((int *)&a3->object_pool[0].object + v12) = (int)v14;
+                  *(&a3->object_pool[0].sZValue + v12) = v15;
+                  *(&a3->object_pool[0].object_type + v12) = v11->object_type;
+                  ++a3->uNumPointers;*/
+                  list->AddObject(v11->object, v11->object_type, v11->sZValue);
                 }
               }
               ++v21;