]> git.jsancho.org Git - lugaru.git/blobdiff - Source/Graphic/Models.cpp
Added braces to all statements with clang-tidy and ran clang-format again
[lugaru.git] / Source / Graphic / Models.cpp
index 38e2447085c528abba18ce2dfe35c2d77332f4bc..eedaea0753cf5040ad19e21803b30fa27875b997 100644 (file)
@@ -28,13 +28,10 @@ extern float viewdistance;
 extern XYZ viewer;
 extern float fadestart;
 extern float texdetail;
-extern bool decals;
+extern bool decalstoggle;
 
-extern bool visibleloading;
-
-int Model::LineCheck(XYZ *p1, XYZ *p2, XYZ *p, XYZ *move, float *rotate)
+int Model::LineCheck(XYZ* p1, XYZ* p2, XYZ* p, XYZ* move, float* rotate)
 {
-    static int j;
     static float distance;
     static float olddistance;
     static int intersecting;
@@ -43,16 +40,19 @@ int Model::LineCheck(XYZ *p1, XYZ *p2, XYZ *p, XYZ *move, float *rotate)
 
     *p1 = *p1 - *move;
     *p2 = *p2 - *move;
-    if (*rotate)
+    if (*rotate) {
         *p1 = DoRotation(*p1, 0, -*rotate, 0);
-    if (*rotate)
+    }
+    if (*rotate) {
         *p2 = DoRotation(*p2, 0, -*rotate, 0);
-    if (!sphere_line_intersection(p1, p2, &boundingspherecenter, &boundingsphereradius))
+    }
+    if (!sphere_line_intersection(p1, p2, &boundingspherecenter, &boundingsphereradius)) {
         return -1;
+    }
     firstintersecting = -1;
 
-    for (j = 0; j < TriangleNum; j++) {
-        intersecting = LineFacetd(p1, p2, &vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]], &facenormals[j], &point);
+    for (unsigned int j = 0; j < Triangles.size(); j++) {
+        intersecting = LineFacetd(p1, p2, &vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]], &Triangles[j].facenormal, &point);
         distance = (point.x - p1->x) * (point.x - p1->x) + (point.y - p1->y) * (point.y - p1->y) + (point.z - p1->z) * (point.z - p1->z);
         if ((distance < olddistance || firstintersecting == -1) && intersecting) {
             olddistance = distance;
@@ -61,15 +61,15 @@ int Model::LineCheck(XYZ *p1, XYZ *p2, XYZ *p, XYZ *move, float *rotate)
         }
     }
 
-    if (*rotate)
+    if (*rotate) {
         *p = DoRotation(*p, 0, *rotate, 0);
+    }
     *p = *p + *move;
     return firstintersecting;
 }
 
-int Model::LineCheckPossible(XYZ *p1, XYZ *p2, XYZ *p, XYZ *move, float *rotate)
+int Model::LineCheckPossible(XYZ* p1, XYZ* p2, XYZ* p, XYZ* move, float* rotate)
 {
-    static int j;
     static float distance;
     static float olddistance;
     static int intersecting;
@@ -78,36 +78,38 @@ int Model::LineCheckPossible(XYZ *p1, XYZ *p2, XYZ *p, XYZ *move, float *rotate)
 
     *p1 = *p1 - *move;
     *p2 = *p2 - *move;
-    if (!sphere_line_intersection(p1, p2, &boundingspherecenter, &boundingsphereradius))
+    if (!sphere_line_intersection(p1, p2, &boundingspherecenter, &boundingsphereradius)) {
         return -1;
+    }
     firstintersecting = -1;
-    if (*rotate)
+    if (*rotate) {
         *p1 = DoRotation(*p1, 0, -*rotate, 0);
-    if (*rotate)
+    }
+    if (*rotate) {
         *p2 = DoRotation(*p2, 0, -*rotate, 0);
+    }
 
-    if (numpossible > 0 && numpossible < TriangleNum)
-        for (j = 0; j < numpossible; j++) {
-            if (possible[j] >= 0 && possible[j] < TriangleNum) {
-                intersecting = LineFacetd(p1, p2, &vertex[Triangles[possible[j]].vertex[0]], &vertex[Triangles[possible[j]].vertex[1]], &vertex[Triangles[possible[j]].vertex[2]], &facenormals[possible[j]], &point);
-                distance = (point.x - p1->x) * (point.x - p1->x) + (point.y - p1->y) * (point.y - p1->y) + (point.z - p1->z) * (point.z - p1->z);
-                if ((distance < olddistance || firstintersecting == -1) && intersecting) {
-                    olddistance = distance;
-                    firstintersecting = possible[j];
-                    *p = point;
-                }
+    for (unsigned int j = 0; j < possible.size(); j++) {
+        if (possible[j] < Triangles.size()) {
+            intersecting = LineFacetd(p1, p2, &vertex[Triangles[possible[j]].vertex[0]], &vertex[Triangles[possible[j]].vertex[1]], &vertex[Triangles[possible[j]].vertex[2]], &Triangles[possible[j]].facenormal, &point);
+            distance = (point.x - p1->x) * (point.x - p1->x) + (point.y - p1->y) * (point.y - p1->y) + (point.z - p1->z) * (point.z - p1->z);
+            if ((distance < olddistance || firstintersecting == -1) && intersecting) {
+                olddistance = distance;
+                firstintersecting = possible[j];
+                *p = point;
             }
         }
+    }
 
-    if (*rotate)
+    if (*rotate) {
         *p = DoRotation(*p, 0, *rotate, 0);
+    }
     *p = *p + *move;
     return firstintersecting;
 }
 
-int Model::LineCheckSlidePossible(XYZ *p1, XYZ *p2, XYZ *p, XYZ *move, float *rotate)
+int Model::LineCheckSlidePossible(XYZ* p1, XYZ* p2, XYZ* move, float* rotate)
 {
-    static int j;
     static float distance;
     static float olddistance;
     static int intersecting;
@@ -116,40 +118,43 @@ int Model::LineCheckSlidePossible(XYZ *p1, XYZ *p2, XYZ *p, XYZ *move, float *ro
 
     *p1 = *p1 - *move;
     *p2 = *p2 - *move;
-    if (!sphere_line_intersection(p1, p2, &boundingspherecenter, &boundingsphereradius))
+    if (!sphere_line_intersection(p1, p2, &boundingspherecenter, &boundingsphereradius)) {
         return -1;
+    }
     firstintersecting = -1;
-    if (*rotate)
+    if (*rotate) {
         *p1 = DoRotation(*p1, 0, -*rotate, 0);
-    if (*rotate)
+    }
+    if (*rotate) {
         *p2 = DoRotation(*p2, 0, -*rotate, 0);
+    }
 
-    if (numpossible)
-        for (j = 0; j < numpossible; j++) {
-            if (possible[j] >= 0 && possible[j] < TriangleNum) {
-                intersecting = LineFacetd(p1, p2, &vertex[Triangles[possible[j]].vertex[0]], &vertex[Triangles[possible[j]].vertex[1]], &vertex[Triangles[possible[j]].vertex[2]], &facenormals[possible[j]], &point);
-                distance = (point.x - p1->x) * (point.x - p1->x) + (point.y - p1->y) * (point.y - p1->y) + (point.z - p1->z) * (point.z - p1->z);
-                if ((distance < olddistance || firstintersecting == -1) && intersecting) {
-                    olddistance = distance;
-                    firstintersecting = possible[j];
-                }
+    for (unsigned int j = 0; j < possible.size(); j++) {
+        if (possible[j] < Triangles.size()) {
+            intersecting = LineFacetd(p1, p2, &vertex[Triangles[possible[j]].vertex[0]], &vertex[Triangles[possible[j]].vertex[1]], &vertex[Triangles[possible[j]].vertex[2]], &Triangles[possible[j]].facenormal, &point);
+            distance = (point.x - p1->x) * (point.x - p1->x) + (point.y - p1->y) * (point.y - p1->y) + (point.z - p1->z) * (point.z - p1->z);
+            if ((distance < olddistance || firstintersecting == -1) && intersecting) {
+                olddistance = distance;
+                firstintersecting = possible[j];
             }
         }
+    }
 
     if (firstintersecting > 0) {
-        distance = abs((facenormals[firstintersecting].x * p2->x) + (facenormals[firstintersecting].y * p2->y) + (facenormals[firstintersecting].z * p2->z) - ((facenormals[firstintersecting].x * vertex[Triangles[firstintersecting].vertex[0]].x) + (facenormals[firstintersecting].y * vertex[Triangles[firstintersecting].vertex[0]].y) + (facenormals[firstintersecting].z * vertex[Triangles[firstintersecting].vertex[0]].z)));
-        *p2 -= facenormals[firstintersecting] * distance;
+        distance = abs((Triangles[firstintersecting].facenormal.x * p2->x) + (Triangles[firstintersecting].facenormal.y * p2->y) + (Triangles[firstintersecting].facenormal.z * p2->z) - ((Triangles[firstintersecting].facenormal.x * vertex[Triangles[firstintersecting].vertex[0]].x) + (Triangles[firstintersecting].facenormal.y * vertex[Triangles[firstintersecting].vertex[0]].y) + (Triangles[firstintersecting].facenormal.z * vertex[Triangles[firstintersecting].vertex[0]].z)));
+        *p2 -= Triangles[firstintersecting].facenormal * distance;
     }
 
-    if (*rotate)
+    if (*rotate) {
         *p2 = DoRotation(*p2, 0, *rotate, 0);
+    }
     *p2 = *p2 + *move;
     return firstintersecting;
 }
 
-int Model::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate)
+int Model::SphereCheck(XYZ* p1, float radius, XYZ* p, XYZ* move, float* rotate)
 {
-    static int i, j;
+    static int i;
     static float distance;
     static float olddistance;
     static int intersecting;
@@ -161,27 +166,33 @@ int Model::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate)
 
     oldp1 = *p1;
     *p1 = *p1 - *move;
-    if (*rotate)
+    if (*rotate) {
         *p1 = DoRotation(*p1, 0, -*rotate, 0);
-    if (distsq(p1, &boundingspherecenter) > radius * radius + boundingsphereradius * boundingsphereradius)
+    }
+    if (distsq(p1, &boundingspherecenter) > radius * radius + boundingsphereradius * boundingsphereradius) {
         return -1;
+    }
 
     for (i = 0; i < 4; i++) {
-        for (j = 0; j < TriangleNum; j++) {
+        for (unsigned int j = 0; j < Triangles.size(); j++) {
             intersecting = 0;
-            distance = abs((facenormals[j].x * p1->x) + (facenormals[j].y * p1->y) + (facenormals[j].z * p1->z) - ((facenormals[j].x * vertex[Triangles[j].vertex[0]].x) + (facenormals[j].y * vertex[Triangles[j].vertex[0]].y) + (facenormals[j].z * vertex[Triangles[j].vertex[0]].z)));
+            distance = abs((Triangles[j].facenormal.x * p1->x) + (Triangles[j].facenormal.y * p1->y) + (Triangles[j].facenormal.z * p1->z) - ((Triangles[j].facenormal.x * vertex[Triangles[j].vertex[0]].x) + (Triangles[j].facenormal.y * vertex[Triangles[j].vertex[0]].y) + (Triangles[j].facenormal.z * vertex[Triangles[j].vertex[0]].z)));
             if (distance < radius) {
-                point = *p1 - facenormals[j] * distance;
-                if (PointInTriangle( &point, facenormals[j], &vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]]))
+                point = *p1 - Triangles[j].facenormal * distance;
+                if (PointInTriangle(&point, Triangles[j].facenormal, &vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]])) {
                     intersecting = 1;
-                if (!intersecting)
+                }
+                if (!intersecting) {
                     intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], p1, &radius);
-                if (!intersecting)
+                }
+                if (!intersecting) {
                     intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]], p1, &radius);
-                if (!intersecting)
+                }
+                if (!intersecting) {
                     intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[2]], p1, &radius);
+                }
                 if (intersecting) {
-                    *p1 += facenormals[j] * (distance - radius);
+                    *p1 += Triangles[j].facenormal * (distance - radius);
                 }
             }
             if ((distance < olddistance || firstintersecting == -1) && intersecting) {
@@ -191,18 +202,19 @@ int Model::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate)
             }
         }
     }
-    if (*rotate)
+    if (*rotate) {
         *p = DoRotation(*p, 0, *rotate, 0);
+    }
     *p = *p + *move;
-    if (*rotate)
+    if (*rotate) {
         *p1 = DoRotation(*p1, 0, *rotate, 0);
+    }
     *p1 += *move;
     return firstintersecting;
 }
 
-int Model::SphereCheckPossible(XYZ *p1, float radius, XYZ *move, float *rotate)
+int Model::SphereCheckPossible(XYZ* p1, float radius, XYZ* move, float* rotate)
 {
-    static int j;
     static float distance;
     static float olddistance;
     static int intersecting;
@@ -215,31 +227,35 @@ int Model::SphereCheckPossible(XYZ *p1, float radius, XYZ *move, float *rotate)
     oldp1 = *p1;
     *p1 = *p1 - *move;
 
-    numpossible = 0;
+    possible.clear();
 
-    if (*rotate)
+    if (*rotate) {
         *p1 = DoRotation(*p1, 0, -*rotate, 0);
+    }
     if (distsq(p1, &boundingspherecenter) > radius * radius + boundingsphereradius * boundingsphereradius) {
         *p1 = oldp1;
         return -1;
     }
 
-    for (j = 0; j < TriangleNum; j++) {
+    for (unsigned int j = 0; j < Triangles.size(); j++) {
         intersecting = 0;
-        distance = abs((facenormals[j].x * p1->x) + (facenormals[j].y * p1->y) + (facenormals[j].z * p1->z) - ((facenormals[j].x * vertex[Triangles[j].vertex[0]].x) + (facenormals[j].y * vertex[Triangles[j].vertex[0]].y) + (facenormals[j].z * vertex[Triangles[j].vertex[0]].z)));
+        distance = abs((Triangles[j].facenormal.x * p1->x) + (Triangles[j].facenormal.y * p1->y) + (Triangles[j].facenormal.z * p1->z) - ((Triangles[j].facenormal.x * vertex[Triangles[j].vertex[0]].x) + (Triangles[j].facenormal.y * vertex[Triangles[j].vertex[0]].y) + (Triangles[j].facenormal.z * vertex[Triangles[j].vertex[0]].z)));
         if (distance < radius) {
-            point = *p1 - facenormals[j] * distance;
-            if (PointInTriangle( &point, facenormals[j], &vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]]))
+            point = *p1 - Triangles[j].facenormal * distance;
+            if (PointInTriangle(&point, Triangles[j].facenormal, &vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]])) {
                 intersecting = 1;
-            if (!intersecting)
+            }
+            if (!intersecting) {
                 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], p1, &radius);
-            if (!intersecting)
+            }
+            if (!intersecting) {
                 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]], p1, &radius);
-            if (!intersecting)
+            }
+            if (!intersecting) {
                 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[2]], p1, &radius);
+            }
             if (intersecting) {
-                possible[numpossible] = j;
-                numpossible++;
+                possible.push_back(j);
             }
         }
         if ((distance < olddistance || firstintersecting == -1) && intersecting) {
@@ -247,146 +263,148 @@ int Model::SphereCheckPossible(XYZ *p1, float radius, XYZ *move, float *rotate)
             firstintersecting = j;
         }
     }
-    if (*rotate)
+    if (*rotate) {
         *p1 = DoRotation(*p1, 0, *rotate, 0);
+    }
     *p1 += *move;
+
     return firstintersecting;
 }
 
-
 void Model::UpdateVertexArray()
 {
-    if (type != normaltype && type != decalstype)
+    if (type != normaltype && type != decalstype) {
         return;
-    static int i;
-    static int j;
-    if (!flat)
-        for (i = 0; i < TriangleNum; i++) {
-            j = i * 24;
+    }
+
+    if (flat) {
+        for (unsigned int i = 0; i < Triangles.size(); i++) {
+            unsigned int j = i * 24;
             vArray[j + 0] = Triangles[i].gx[0];
             vArray[j + 1] = Triangles[i].gy[0];
-            vArray[j + 2] = normals[Triangles[i].vertex[0]].x;
-            vArray[j + 3] = normals[Triangles[i].vertex[0]].y;
-            vArray[j + 4] = normals[Triangles[i].vertex[0]].z;
+            vArray[j + 2] = Triangles[i].facenormal.x * -1;
+            vArray[j + 3] = Triangles[i].facenormal.y * -1;
+            vArray[j + 4] = Triangles[i].facenormal.z * -1;
             vArray[j + 5] = vertex[Triangles[i].vertex[0]].x;
             vArray[j + 6] = vertex[Triangles[i].vertex[0]].y;
             vArray[j + 7] = vertex[Triangles[i].vertex[0]].z;
 
             vArray[j + 8] = Triangles[i].gx[1];
             vArray[j + 9] = Triangles[i].gy[1];
-            vArray[j + 10] = normals[Triangles[i].vertex[1]].x;
-            vArray[j + 11] = normals[Triangles[i].vertex[1]].y;
-            vArray[j + 12] = normals[Triangles[i].vertex[1]].z;
+            vArray[j + 10] = Triangles[i].facenormal.x * -1;
+            vArray[j + 11] = Triangles[i].facenormal.y * -1;
+            vArray[j + 12] = Triangles[i].facenormal.z * -1;
             vArray[j + 13] = vertex[Triangles[i].vertex[1]].x;
             vArray[j + 14] = vertex[Triangles[i].vertex[1]].y;
             vArray[j + 15] = vertex[Triangles[i].vertex[1]].z;
 
             vArray[j + 16] = Triangles[i].gx[2];
             vArray[j + 17] = Triangles[i].gy[2];
-            vArray[j + 18] = normals[Triangles[i].vertex[2]].x;
-            vArray[j + 19] = normals[Triangles[i].vertex[2]].y;
-            vArray[j + 20] = normals[Triangles[i].vertex[2]].z;
+            vArray[j + 18] = Triangles[i].facenormal.x * -1;
+            vArray[j + 19] = Triangles[i].facenormal.y * -1;
+            vArray[j + 20] = Triangles[i].facenormal.z * -1;
             vArray[j + 21] = vertex[Triangles[i].vertex[2]].x;
             vArray[j + 22] = vertex[Triangles[i].vertex[2]].y;
             vArray[j + 23] = vertex[Triangles[i].vertex[2]].z;
         }
-    if (flat)
-        for (i = 0; i < TriangleNum; i++) {
-            j = i * 24;
+    } else {
+        for (unsigned int i = 0; i < Triangles.size(); i++) {
+            unsigned int j = i * 24;
             vArray[j + 0] = Triangles[i].gx[0];
             vArray[j + 1] = Triangles[i].gy[0];
-            vArray[j + 2] = facenormals[i].x * -1;
-            vArray[j + 3] = facenormals[i].y * -1;
-            vArray[j + 4] = facenormals[i].z * -1;
+            vArray[j + 2] = normals[Triangles[i].vertex[0]].x;
+            vArray[j + 3] = normals[Triangles[i].vertex[0]].y;
+            vArray[j + 4] = normals[Triangles[i].vertex[0]].z;
             vArray[j + 5] = vertex[Triangles[i].vertex[0]].x;
             vArray[j + 6] = vertex[Triangles[i].vertex[0]].y;
             vArray[j + 7] = vertex[Triangles[i].vertex[0]].z;
 
             vArray[j + 8] = Triangles[i].gx[1];
             vArray[j + 9] = Triangles[i].gy[1];
-            vArray[j + 10] = facenormals[i].x * -1;
-            vArray[j + 11] = facenormals[i].y * -1;
-            vArray[j + 12] = facenormals[i].z * -1;
+            vArray[j + 10] = normals[Triangles[i].vertex[1]].x;
+            vArray[j + 11] = normals[Triangles[i].vertex[1]].y;
+            vArray[j + 12] = normals[Triangles[i].vertex[1]].z;
             vArray[j + 13] = vertex[Triangles[i].vertex[1]].x;
             vArray[j + 14] = vertex[Triangles[i].vertex[1]].y;
             vArray[j + 15] = vertex[Triangles[i].vertex[1]].z;
 
             vArray[j + 16] = Triangles[i].gx[2];
             vArray[j + 17] = Triangles[i].gy[2];
-            vArray[j + 18] = facenormals[i].x * -1;
-            vArray[j + 19] = facenormals[i].y * -1;
-            vArray[j + 20] = facenormals[i].z * -1;
+            vArray[j + 18] = normals[Triangles[i].vertex[2]].x;
+            vArray[j + 19] = normals[Triangles[i].vertex[2]].y;
+            vArray[j + 20] = normals[Triangles[i].vertex[2]].z;
             vArray[j + 21] = vertex[Triangles[i].vertex[2]].x;
             vArray[j + 22] = vertex[Triangles[i].vertex[2]].y;
             vArray[j + 23] = vertex[Triangles[i].vertex[2]].z;
-
         }
+    }
 }
 
 void Model::UpdateVertexArrayNoTex()
 {
-    if (type != normaltype && type != decalstype)
+    if (type != normaltype && type != decalstype) {
         return;
-    static int i;
-    static int j;
-    if (!flat)
-        for (i = 0; i < TriangleNum; i++) {
-            j = i * 24;
-            vArray[j + 2] = normals[Triangles[i].vertex[0]].x;
-            vArray[j + 3] = normals[Triangles[i].vertex[0]].y;
-            vArray[j + 4] = normals[Triangles[i].vertex[0]].z;
+    }
+
+    if (flat) {
+        for (unsigned int i = 0; i < Triangles.size(); i++) {
+            unsigned int j = i * 24;
+            vArray[j + 2] = Triangles[i].facenormal.x * -1;
+            vArray[j + 3] = Triangles[i].facenormal.y * -1;
+            vArray[j + 4] = Triangles[i].facenormal.z * -1;
             vArray[j + 5] = vertex[Triangles[i].vertex[0]].x;
             vArray[j + 6] = vertex[Triangles[i].vertex[0]].y;
             vArray[j + 7] = vertex[Triangles[i].vertex[0]].z;
 
-            vArray[j + 10] = normals[Triangles[i].vertex[1]].x;
-            vArray[j + 11] = normals[Triangles[i].vertex[1]].y;
-            vArray[j + 12] = normals[Triangles[i].vertex[1]].z;
+            vArray[j + 10] = Triangles[i].facenormal.x * -1;
+            vArray[j + 11] = Triangles[i].facenormal.y * -1;
+            vArray[j + 12] = Triangles[i].facenormal.z * -1;
             vArray[j + 13] = vertex[Triangles[i].vertex[1]].x;
             vArray[j + 14] = vertex[Triangles[i].vertex[1]].y;
             vArray[j + 15] = vertex[Triangles[i].vertex[1]].z;
 
-            vArray[j + 18] = normals[Triangles[i].vertex[2]].x;
-            vArray[j + 19] = normals[Triangles[i].vertex[2]].y;
-            vArray[j + 20] = normals[Triangles[i].vertex[2]].z;
+            vArray[j + 18] = Triangles[i].facenormal.x * -1;
+            vArray[j + 19] = Triangles[i].facenormal.y * -1;
+            vArray[j + 20] = Triangles[i].facenormal.z * -1;
             vArray[j + 21] = vertex[Triangles[i].vertex[2]].x;
             vArray[j + 22] = vertex[Triangles[i].vertex[2]].y;
             vArray[j + 23] = vertex[Triangles[i].vertex[2]].z;
         }
-    if (flat)
-        for (i = 0; i < TriangleNum; i++) {
-            j = i * 24;
-            vArray[j + 2] = facenormals[i].x * -1;
-            vArray[j + 3] = facenormals[i].y * -1;
-            vArray[j + 4] = facenormals[i].z * -1;
+    } else {
+        for (unsigned int i = 0; i < Triangles.size(); i++) {
+            unsigned int j = i * 24;
+            vArray[j + 2] = normals[Triangles[i].vertex[0]].x;
+            vArray[j + 3] = normals[Triangles[i].vertex[0]].y;
+            vArray[j + 4] = normals[Triangles[i].vertex[0]].z;
             vArray[j + 5] = vertex[Triangles[i].vertex[0]].x;
             vArray[j + 6] = vertex[Triangles[i].vertex[0]].y;
             vArray[j + 7] = vertex[Triangles[i].vertex[0]].z;
 
-            vArray[j + 10] = facenormals[i].x * -1;
-            vArray[j + 11] = facenormals[i].y * -1;
-            vArray[j + 12] = facenormals[i].z * -1;
+            vArray[j + 10] = normals[Triangles[i].vertex[1]].x;
+            vArray[j + 11] = normals[Triangles[i].vertex[1]].y;
+            vArray[j + 12] = normals[Triangles[i].vertex[1]].z;
             vArray[j + 13] = vertex[Triangles[i].vertex[1]].x;
             vArray[j + 14] = vertex[Triangles[i].vertex[1]].y;
             vArray[j + 15] = vertex[Triangles[i].vertex[1]].z;
 
-            vArray[j + 18] = facenormals[i].x * -1;
-            vArray[j + 19] = facenormals[i].y * -1;
-            vArray[j + 20] = facenormals[i].z * -1;
+            vArray[j + 18] = normals[Triangles[i].vertex[2]].x;
+            vArray[j + 19] = normals[Triangles[i].vertex[2]].y;
+            vArray[j + 20] = normals[Triangles[i].vertex[2]].z;
             vArray[j + 21] = vertex[Triangles[i].vertex[2]].x;
             vArray[j + 22] = vertex[Triangles[i].vertex[2]].y;
             vArray[j + 23] = vertex[Triangles[i].vertex[2]].z;
         }
+    }
 }
 
 void Model::UpdateVertexArrayNoTexNoNorm()
 {
-    if (type != normaltype && type != decalstype)
+    if (type != normaltype && type != decalstype) {
         return;
-    static int i;
-    static int j;
-    for (i = 0; i < TriangleNum; i++) {
-        j = i * 24;
+    }
+
+    for (unsigned int i = 0; i < Triangles.size(); i++) {
+        unsigned int j = i * 24;
         vArray[j + 5] = vertex[Triangles[i].vertex[0]].x;
         vArray[j + 6] = vertex[Triangles[i].vertex[0]].y;
         vArray[j + 7] = vertex[Triangles[i].vertex[0]].z;
@@ -401,42 +419,42 @@ void Model::UpdateVertexArrayNoTexNoNorm()
     }
 }
 
-bool Model::loadnotex(const std::string& filename )
+bool Model::loadnotex(const std::string& filename)
 {
-    FILE *tfile;
+    FILEtfile;
     long i;
+    short triangleNum;
 
     type = notextype;
     color = 0;
 
-    tfile = Folders::openMandatoryFile( Folders::getResourcePath(filename), "rb" );
+    tfile = Folders::openMandatoryFile(Folders::getResourcePath(filename), "rb");
 
     // read model settings
 
     fseek(tfile, 0, SEEK_SET);
-    funpackf(tfile, "Bs Bs", &vertexNum, &TriangleNum);
+    funpackf(tfile, "Bs Bs", &vertexNum, &triangleNum);
 
     // read the model data
     deallocate();
 
-    numpossible = 0;
+    possible.clear();
 
     owner = (int*)malloc(sizeof(int) * vertexNum);
-    possible = (int*)malloc(sizeof(int) * TriangleNum);
     vertex = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
-    Triangles = (TexturedTriangle*)malloc(sizeof(TexturedTriangle) * TriangleNum);
-    vArray = (GLfloat*)malloc(sizeof(GLfloat) * TriangleNum * 24);
+    Triangles.resize(triangleNum);
+    vArray = (GLfloat*)malloc(sizeof(GLfloat) * triangleNum * 24);
 
     for (i = 0; i < vertexNum; i++) {
         funpackf(tfile, "Bf Bf Bf", &vertex[i].x, &vertex[i].y, &vertex[i].z);
     }
 
-    for (i = 0; i < TriangleNum; i++) {
-        short vertex[ 6];
-        funpackf(tfile, "Bs Bs Bs Bs Bs Bs", &vertex[ 0], &vertex[ 1], &vertex[ 2], &vertex[ 3], &vertex[ 4], &vertex[ 5]);
-        Triangles[i].vertex[ 0] = vertex[ 0];
-        Triangles[i].vertex[ 1] = vertex[ 2];
-        Triangles[i].vertex[ 2] = vertex[ 4];
+    for (i = 0; i < triangleNum; i++) {
+        short vertex[6];
+        funpackf(tfile, "Bs Bs Bs Bs Bs Bs", &vertex[0], &vertex[1], &vertex[2], &vertex[3], &vertex[4], &vertex[5]);
+        Triangles[i].vertex[0] = vertex[0];
+        Triangles[i].vertex[1] = vertex[2];
+        Triangles[i].vertex[2] = vertex[4];
         funpackf(tfile, "Bf Bf Bf", &Triangles[i].gx[0], &Triangles[i].gx[1], &Triangles[i].gx[2]);
         funpackf(tfile, "Bf Bf Bf", &Triangles[i].gy[0], &Triangles[i].gy[1], &Triangles[i].gy[2]);
     }
@@ -449,10 +467,9 @@ bool Model::loadnotex(const std::string& filename )
         owner[i] = -1;
     }
 
-    static int j;
     boundingsphereradius = 0;
     for (i = 0; i < vertexNum; i++) {
-        for (j = 0; j < vertexNum; j++) {
+        for (int j = 0; j < vertexNum; j++) {
             if (j != i && distsq(&vertex[j], &vertex[i]) / 2 > boundingsphereradius) {
                 boundingsphereradius = distsq(&vertex[j], &vertex[i]) / 2;
                 boundingspherecenter = (vertex[i] + vertex[j]) / 2;
@@ -464,52 +481,49 @@ bool Model::loadnotex(const std::string& filename )
     return true;
 }
 
-
-bool Model::load(const std::string& filename, bool texture )
+bool Model::load(const std::string& filename)
 {
-    FILE *tfile;
+    FILEtfile;
     long i;
+    short triangleNum;
 
     LOGFUNC;
 
     LOG(std::string("Loading model...") + filename);
 
-    if (visibleloading)
-        Game::LoadingScreen();
+    Game::LoadingScreen();
 
     type = normaltype;
     color = 0;
 
-    tfile = Folders::openMandatoryFile( Folders::getResourcePath(filename), "rb" );
+    tfile = Folders::openMandatoryFile(Folders::getResourcePath(filename), "rb");
 
     // read model settings
 
     fseek(tfile, 0, SEEK_SET);
-    funpackf(tfile, "Bs Bs", &vertexNum, &TriangleNum);
+    funpackf(tfile, "Bs Bs", &vertexNum, &triangleNum);
 
     // read the model data
     deallocate();
 
-    numpossible = 0;
+    possible.clear();
 
     owner = (int*)malloc(sizeof(int) * vertexNum);
-    possible = (int*)malloc(sizeof(int) * TriangleNum);
     vertex = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
     normals = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
-    facenormals = (XYZ*)malloc(sizeof(XYZ) * TriangleNum);
-    Triangles = (TexturedTriangle*)malloc(sizeof(TexturedTriangle) * TriangleNum);
-    vArray = (GLfloat*)malloc(sizeof(GLfloat) * TriangleNum * 24);
+    Triangles.resize(triangleNum);
+    vArray = (GLfloat*)malloc(sizeof(GLfloat) * triangleNum * 24);
 
     for (i = 0; i < vertexNum; i++) {
         funpackf(tfile, "Bf Bf Bf", &vertex[i].x, &vertex[i].y, &vertex[i].z);
     }
 
-    for (i = 0; i < TriangleNum; i++) {
-        short vertex[ 6];
-        funpackf(tfile, "Bs Bs Bs Bs Bs Bs", &vertex[ 0], &vertex[ 1], &vertex[ 2], &vertex[ 3], &vertex[ 4], &vertex[ 5]);
-        Triangles[i].vertex[ 0] = vertex[ 0];
-        Triangles[i].vertex[ 1] = vertex[ 2];
-        Triangles[i].vertex[ 2] = vertex[ 4];
+    for (i = 0; i < triangleNum; i++) {
+        short vertex[6];
+        funpackf(tfile, "Bs Bs Bs Bs Bs Bs", &vertex[0], &vertex[1], &vertex[2], &vertex[3], &vertex[4], &vertex[5]);
+        Triangles[i].vertex[0] = vertex[0];
+        Triangles[i].vertex[1] = vertex[2];
+        Triangles[i].vertex[2] = vertex[4];
         funpackf(tfile, "Bf Bf Bf", &Triangles[i].gx[0], &Triangles[i].gx[1], &Triangles[i].gx[2]);
         funpackf(tfile, "Bf Bf Bf", &Triangles[i].gy[0], &Triangles[i].gy[1], &Triangles[i].gy[2]);
     }
@@ -539,56 +553,52 @@ bool Model::load(const std::string& filename, bool texture )
     return true;
 }
 
-bool Model::loaddecal(const std::string& filename, bool texture )
+bool Model::loaddecal(const std::string& filename)
 {
-    FILE *tfile;
+    FILEtfile;
     long i, j;
+    short triangleNum;
 
     LOGFUNC;
 
     LOG(std::string("Loading decal...") + Folders::getResourcePath(filename));
 
     type = decalstype;
-    numdecals = 0;
     color = 0;
 
-    tfile = Folders::openMandatoryFile( Folders::getResourcePath(filename), "rb" );
+    tfile = Folders::openMandatoryFile(Folders::getResourcePath(filename), "rb");
 
     // read model settings
 
     fseek(tfile, 0, SEEK_SET);
-    funpackf(tfile, "Bs Bs", &vertexNum, &TriangleNum);
+    funpackf(tfile, "Bs Bs", &vertexNum, &triangleNum);
 
     // read the model data
 
     deallocate();
 
-    numpossible = 0;
+    possible.clear();
 
     owner = (int*)malloc(sizeof(int) * vertexNum);
-    possible = (int*)malloc(sizeof(int) * TriangleNum);
     vertex = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
     normals = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
-    facenormals = (XYZ*)malloc(sizeof(XYZ) * TriangleNum);
-    Triangles = (TexturedTriangle*)malloc(sizeof(TexturedTriangle) * TriangleNum);
-    vArray = (GLfloat*)malloc(sizeof(GLfloat) * TriangleNum * 24);
-
+    Triangles.resize(triangleNum);
+    vArray = (GLfloat*)malloc(sizeof(GLfloat) * triangleNum * 24);
 
     for (i = 0; i < vertexNum; i++) {
         funpackf(tfile, "Bf Bf Bf", &vertex[i].x, &vertex[i].y, &vertex[i].z);
     }
 
-    for (i = 0; i < TriangleNum; i++) {
-        short vertex[ 6];
-        funpackf(tfile, "Bs Bs Bs Bs Bs Bs", &vertex[ 0], &vertex[ 1], &vertex[ 2], &vertex[ 3], &vertex[ 4], &vertex[ 5]);
-        Triangles[i].vertex[ 0] = vertex[ 0];
-        Triangles[i].vertex[ 1] = vertex[ 2];
-        Triangles[i].vertex[ 2] = vertex[ 4];
+    for (i = 0; i < triangleNum; i++) {
+        short vertex[6];
+        funpackf(tfile, "Bs Bs Bs Bs Bs Bs", &vertex[0], &vertex[1], &vertex[2], &vertex[3], &vertex[4], &vertex[5]);
+        Triangles[i].vertex[0] = vertex[0];
+        Triangles[i].vertex[1] = vertex[2];
+        Triangles[i].vertex[2] = vertex[4];
         funpackf(tfile, "Bf Bf Bf", &Triangles[i].gx[0], &Triangles[i].gx[1], &Triangles[i].gx[2]);
         funpackf(tfile, "Bf Bf Bf", &Triangles[i].gy[0], &Triangles[i].gy[1], &Triangles[i].gy[2]);
     }
 
-
     modelTexture.xsz = 0;
 
     fclose(tfile);
@@ -610,34 +620,14 @@ bool Model::loaddecal(const std::string& filename, bool texture )
     }
     boundingsphereradius = fast_sqrt(boundingsphereradius);
 
-    //allow decals
-    if (!decaltexcoords) {
-        decaltexcoords = (float***)malloc(sizeof(float**)*max_model_decals);
-        for (i = 0; i < max_model_decals; i++) {
-            decaltexcoords[i] = (float**)malloc(sizeof(float*) * 3);
-            for (j = 0; j < 3; j++) {
-                decaltexcoords[i][j] = (float*)malloc(sizeof(float) * 2);
-            }
-        }
-        decalvertex = (XYZ**)malloc(sizeof(XYZ*)*max_model_decals);
-        for (i = 0; i < max_model_decals; i++) {
-            decalvertex[i] = (XYZ*)malloc(sizeof(XYZ) * 3);
-        }
-
-        decaltype = (int*)malloc(sizeof(int) * max_model_decals);
-        decalopacity = (float*)malloc(sizeof(float) * max_model_decals);
-        decalrotation = (float*)malloc(sizeof(float) * max_model_decals);
-        decalalivetime = (float*)malloc(sizeof(float) * max_model_decals);
-        decalposition = (XYZ*)malloc(sizeof(XYZ) * max_model_decals);
-    }
-
     return true;
 }
 
 bool Model::loadraw(const std::string& filename)
 {
-    FILE *tfile;
+    FILEtfile;
     long i;
+    short triangleNum;
 
     LOGFUNC;
 
@@ -646,40 +636,37 @@ bool Model::loadraw(const std::string& filename)
     type = rawtype;
     color = 0;
 
-    tfile = Folders::openMandatoryFile( Folders::getResourcePath(filename), "rb" );
+    tfile = Folders::openMandatoryFile(Folders::getResourcePath(filename), "rb");
 
     // read model settings
 
     fseek(tfile, 0, SEEK_SET);
-    funpackf(tfile, "Bs Bs", &vertexNum, &TriangleNum);
+    funpackf(tfile, "Bs Bs", &vertexNum, &triangleNum);
 
     // read the model data
     deallocate();
 
-    numpossible = 0;
+    possible.clear();
 
     owner = (int*)malloc(sizeof(int) * vertexNum);
-    possible = (int*)malloc(sizeof(int) * TriangleNum);
     vertex = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
-    Triangles = (TexturedTriangle*)malloc(sizeof(TexturedTriangle) * TriangleNum);
-    vArray = (GLfloat*)malloc(sizeof(GLfloat) * TriangleNum * 24);
-
+    Triangles.resize(triangleNum);
+    vArray = (GLfloat*)malloc(sizeof(GLfloat) * triangleNum * 24);
 
     for (i = 0; i < vertexNum; i++) {
         funpackf(tfile, "Bf Bf Bf", &vertex[i].x, &vertex[i].y, &vertex[i].z);
     }
 
-    for (i = 0; i < TriangleNum; i++) {
-        short vertex[ 6];
-        funpackf(tfile, "Bs Bs Bs Bs Bs Bs", &vertex[ 0], &vertex[ 1], &vertex[ 2], &vertex[ 3], &vertex[ 4], &vertex[ 5]);
-        Triangles[i].vertex[ 0] = vertex[ 0];
-        Triangles[i].vertex[ 1] = vertex[ 2];
-        Triangles[i].vertex[ 2] = vertex[ 4];
+    for (i = 0; i < triangleNum; i++) {
+        short vertex[6];
+        funpackf(tfile, "Bs Bs Bs Bs Bs Bs", &vertex[0], &vertex[1], &vertex[2], &vertex[3], &vertex[4], &vertex[5]);
+        Triangles[i].vertex[0] = vertex[0];
+        Triangles[i].vertex[1] = vertex[2];
+        Triangles[i].vertex[2] = vertex[4];
         funpackf(tfile, "Bf Bf Bf", &Triangles[i].gx[0], &Triangles[i].gx[1], &Triangles[i].gx[2]);
         funpackf(tfile, "Bf Bf Bf", &Triangles[i].gy[0], &Triangles[i].gy[1], &Triangles[i].gy[2]);
     }
 
-
     fclose(tfile);
 
     for (i = 0; i < vertexNum; i++) {
@@ -689,11 +676,9 @@ bool Model::loadraw(const std::string& filename)
     return true;
 }
 
-
 void Model::UniformTexCoords()
 {
-    static int i;
-    for (i = 0; i < TriangleNum; i++) {
+    for (unsigned int i = 0; i < Triangles.size(); i++) {
         Triangles[i].gy[0] = vertex[Triangles[i].vertex[0]].y;
         Triangles[i].gy[1] = vertex[Triangles[i].vertex[1]].y;
         Triangles[i].gy[2] = vertex[Triangles[i].vertex[2]].y;
@@ -704,11 +689,9 @@ void Model::UniformTexCoords()
     UpdateVertexArray();
 }
 
-
 void Model::FlipTexCoords()
 {
-    static int i;
-    for (i = 0; i < TriangleNum; i++) {
+    for (unsigned int i = 0; i < Triangles.size(); i++) {
         Triangles[i].gy[0] = -Triangles[i].gy[0];
         Triangles[i].gy[1] = -Triangles[i].gy[1];
         Triangles[i].gy[2] = -Triangles[i].gy[2];
@@ -718,8 +701,7 @@ void Model::FlipTexCoords()
 
 void Model::ScaleTexCoords(float howmuch)
 {
-    static int i;
-    for (i = 0; i < TriangleNum; i++) {
+    for (unsigned int i = 0; i < Triangles.size(); i++) {
         Triangles[i].gx[0] *= howmuch;
         Triangles[i].gx[1] *= howmuch;
         Triangles[i].gx[2] *= howmuch;
@@ -756,18 +738,19 @@ void Model::Scale(float xscale, float yscale, float zscale)
 
 void Model::ScaleNormals(float xscale, float yscale, float zscale)
 {
-    if (type != normaltype && type != decalstype)
+    if (type != normaltype && type != decalstype) {
         return;
-    static int i;
-    for (i = 0; i < vertexNum; i++) {
+    }
+
+    for (int i = 0; i < vertexNum; i++) {
         normals[i].x *= xscale;
         normals[i].y *= yscale;
         normals[i].z *= zscale;
     }
-    for (i = 0; i < TriangleNum; i++) {
-        facenormals[i].x *= xscale;
-        facenormals[i].y *= yscale;
-        facenormals[i].z *= zscale;
+    for (unsigned int i = 0; i < Triangles.size(); i++) {
+        Triangles[i].facenormal.x *= xscale;
+        Triangles[i].facenormal.y *= yscale;
+        Triangles[i].facenormal.z *= zscale;
     }
     UpdateVertexArray();
 }
@@ -816,39 +799,39 @@ void Model::Rotate(float xang, float yang, float zang)
     boundingsphereradius = fast_sqrt(boundingsphereradius);
 }
 
-
 void Model::CalculateNormals(bool facenormalise)
 {
-    if (visibleloading)
-        Game::LoadingScreen();
-    static int i;
-    if (type != normaltype && type != decalstype)
+    Game::LoadingScreen();
+
+    if (type != normaltype && type != decalstype) {
         return;
+    }
 
-    for (i = 0; i < vertexNum; i++) {
+    for (int i = 0; i < vertexNum; i++) {
         normals[i].x = 0;
         normals[i].y = 0;
         normals[i].z = 0;
     }
 
-    for (i = 0; i < TriangleNum; i++) {
-        CrossProduct(vertex[Triangles[i].vertex[1]] - vertex[Triangles[i].vertex[0]], vertex[Triangles[i].vertex[2]] - vertex[Triangles[i].vertex[0]], &facenormals[i]);
+    for (unsigned int i = 0; i < Triangles.size(); i++) {
+        CrossProduct(vertex[Triangles[i].vertex[1]] - vertex[Triangles[i].vertex[0]], vertex[Triangles[i].vertex[2]] - vertex[Triangles[i].vertex[0]], &Triangles[i].facenormal);
 
-        normals[Triangles[i].vertex[0]].x += facenormals[i].x;
-        normals[Triangles[i].vertex[0]].y += facenormals[i].y;
-        normals[Triangles[i].vertex[0]].z += facenormals[i].z;
+        normals[Triangles[i].vertex[0]].x += Triangles[i].facenormal.x;
+        normals[Triangles[i].vertex[0]].y += Triangles[i].facenormal.y;
+        normals[Triangles[i].vertex[0]].z += Triangles[i].facenormal.z;
 
-        normals[Triangles[i].vertex[1]].x += facenormals[i].x;
-        normals[Triangles[i].vertex[1]].y += facenormals[i].y;
-        normals[Triangles[i].vertex[1]].z += facenormals[i].z;
+        normals[Triangles[i].vertex[1]].x += Triangles[i].facenormal.x;
+        normals[Triangles[i].vertex[1]].y += Triangles[i].facenormal.y;
+        normals[Triangles[i].vertex[1]].z += Triangles[i].facenormal.z;
 
-        normals[Triangles[i].vertex[2]].x += facenormals[i].x;
-        normals[Triangles[i].vertex[2]].y += facenormals[i].y;
-        normals[Triangles[i].vertex[2]].z += facenormals[i].z;
-        if (facenormalise)
-            Normalise(&facenormals[i]);
+        normals[Triangles[i].vertex[2]].x += Triangles[i].facenormal.x;
+        normals[Triangles[i].vertex[2]].y += Triangles[i].facenormal.y;
+        normals[Triangles[i].vertex[2]].z += Triangles[i].facenormal.z;
+        if (facenormalise) {
+            Normalise(&Triangles[i].facenormal);
+        }
     }
-    for (i = 0; i < vertexNum; i++) {
+    for (int i = 0; i < vertexNum; i++) {
         Normalise(&normals[i]);
         normals[i] *= -1;
     }
@@ -859,32 +842,35 @@ void Model::drawimmediate()
 {
     textureptr.bind();
     glBegin(GL_TRIANGLES);
-    for (int i = 0; i < TriangleNum; i++) {
+    for (unsigned int i = 0; i < Triangles.size(); i++) {
         glTexCoord2f(Triangles[i].gx[0], Triangles[i].gy[0]);
-        if (color)
+        if (color) {
             glColor3f(normals[Triangles[i].vertex[0]].x, normals[Triangles[i].vertex[0]].y, normals[Triangles[i].vertex[0]].z);
-        if (!color && !flat)
+        } else if (flat) {
+            glNormal3f(Triangles[i].facenormal.x, Triangles[i].facenormal.y, Triangles[i].facenormal.y);
+        } else {
             glNormal3f(normals[Triangles[i].vertex[0]].x, normals[Triangles[i].vertex[0]].y, normals[Triangles[i].vertex[0]].z);
-        if (!color && flat)
-            glNormal3f(facenormals[i].x, facenormals[i].y, facenormals[i].y);
+        }
         glVertex3f(vertex[Triangles[i].vertex[0]].x, vertex[Triangles[i].vertex[0]].y, vertex[Triangles[i].vertex[0]].z);
 
         glTexCoord2f(Triangles[i].gx[1], Triangles[i].gy[1]);
-        if (color)
+        if (color) {
             glColor3f(normals[Triangles[i].vertex[1]].x, normals[Triangles[i].vertex[1]].y, normals[Triangles[i].vertex[1]].z);
-        if (!color && !flat)
+        } else if (flat) {
+            glNormal3f(Triangles[i].facenormal.x, Triangles[i].facenormal.y, Triangles[i].facenormal.y);
+        } else {
             glNormal3f(normals[Triangles[i].vertex[1]].x, normals[Triangles[i].vertex[1]].y, normals[Triangles[i].vertex[1]].z);
-        if (!color && flat)
-            glNormal3f(facenormals[i].x, facenormals[i].y, facenormals[i].y);
+        }
         glVertex3f(vertex[Triangles[i].vertex[1]].x, vertex[Triangles[i].vertex[1]].y, vertex[Triangles[i].vertex[1]].z);
 
         glTexCoord2f(Triangles[i].gx[2], Triangles[i].gy[2]);
-        if (color)
+        if (color) {
             glColor3f(normals[Triangles[i].vertex[2]].x, normals[Triangles[i].vertex[2]].y, normals[Triangles[i].vertex[2]].z);
-        if (!color && !flat)
+        } else if (flat) {
+            glNormal3f(Triangles[i].facenormal.x, Triangles[i].facenormal.y, Triangles[i].facenormal.y);
+        } else {
             glNormal3f(normals[Triangles[i].vertex[2]].x, normals[Triangles[i].vertex[2]].y, normals[Triangles[i].vertex[2]].z);
-        if (!color && flat)
-            glNormal3f(facenormals[i].x, facenormals[i].y, facenormals[i].y);
+        }
         glVertex3f(vertex[Triangles[i].vertex[2]].x, vertex[Triangles[i].vertex[2]].y, vertex[Triangles[i].vertex[2]].z);
     }
     glEnd();
@@ -892,50 +878,28 @@ void Model::drawimmediate()
 
 void Model::draw()
 {
-    if (type != normaltype && type != decalstype)
+    if (type != normaltype && type != decalstype) {
         return;
+    }
 
     glEnableClientState(GL_NORMAL_ARRAY);
     glEnableClientState(GL_VERTEX_ARRAY);
     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 
-    if (!color)
-        glInterleavedArrays( GL_T2F_N3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
-    if (color)
-        glInterleavedArrays( GL_T2F_C3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
+    if (color) {
+        glInterleavedArrays(GL_T2F_C3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
+    } else {
+        glInterleavedArrays(GL_T2F_N3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
+    }
     textureptr.bind();
 
-    glDrawArrays(GL_TRIANGLES, 0, TriangleNum * 3);
+    glDrawArrays(GL_TRIANGLES, 0, Triangles.size() * 3);
 
-    if (!color)
-        glDisableClientState(GL_NORMAL_ARRAY);
-    if (color)
+    if (color) {
         glDisableClientState(GL_COLOR_ARRAY);
-    glDisableClientState(GL_VERTEX_ARRAY);
-    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-}
-
-//TODO: phase out in favor of Texture
-void Model::drawdifftex(GLuint texture)
-{
-    glEnableClientState(GL_NORMAL_ARRAY);
-    glEnableClientState(GL_VERTEX_ARRAY);
-    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-    if (!color)
-        glInterleavedArrays( GL_T2F_N3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
-    if (color)
-        glInterleavedArrays( GL_T2F_C3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
-
-    glBindTexture(GL_TEXTURE_2D, (unsigned long)texture);
-    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
-    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
-
-    glDrawArrays(GL_TRIANGLES, 0, TriangleNum * 3);
-
-    if (!color)
+    } else {
         glDisableClientState(GL_NORMAL_ARRAY);
-    if (color)
-        glDisableClientState(GL_COLOR_ARRAY);
+    }
     glDisableClientState(GL_VERTEX_ARRAY);
     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 }
@@ -945,96 +909,100 @@ void Model::drawdifftex(Texture texture)
     glEnableClientState(GL_NORMAL_ARRAY);
     glEnableClientState(GL_VERTEX_ARRAY);
     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-    if (!color)
-        glInterleavedArrays( GL_T2F_N3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
-    if (color)
-        glInterleavedArrays( GL_T2F_C3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
+    if (color) {
+        glInterleavedArrays(GL_T2F_C3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
+    } else {
+        glInterleavedArrays(GL_T2F_N3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
+    }
 
     texture.bind();
-    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
-    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
+    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
 
-    glDrawArrays(GL_TRIANGLES, 0, TriangleNum * 3);
+    glDrawArrays(GL_TRIANGLES, 0, Triangles.size() * 3);
 
-    if (!color)
-        glDisableClientState(GL_NORMAL_ARRAY);
-    if (color)
+    if (color) {
         glDisableClientState(GL_COLOR_ARRAY);
+    } else {
+        glDisableClientState(GL_NORMAL_ARRAY);
+    }
     glDisableClientState(GL_VERTEX_ARRAY);
     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 }
 
 void Model::drawdecals(Texture shadowtexture, Texture bloodtexture, Texture bloodtexture2, Texture breaktexture)
 {
-    if (decals) {
-        if (type != decalstype)
+    if (decalstoggle) {
+        if (type != decalstype) {
             return;
-        static int i;
-        static int lasttype;
-        static bool blend;
+        }
 
-        blend = 1;
+        bool blend = true;
+        int lasttype = -1;
 
-        lasttype = -1;
         glEnable(GL_BLEND);
         glDisable(GL_LIGHTING);
         glDisable(GL_CULL_FACE);
         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
         glDepthMask(0);
-        if (numdecals > max_model_decals)
-            numdecals = max_model_decals;
-        for (i = 0; i < numdecals; i++) {
-            if (decaltype[i] == blooddecalfast && decalalivetime[i] < 2)
-                decalalivetime[i] = 2;
-
-            if (decaltype[i] == shadowdecal && decaltype[i] != lasttype) {
-                shadowtexture.bind();
-                if (!blend) {
-                    blend = 1;
-                    glAlphaFunc(GL_GREATER, 0.0001);
-                    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-                }
+        for (unsigned int i = 0; i < decals.size(); i++) {
+            if (decals[i].type == blooddecalfast && decals[i].alivetime < 2) {
+                decals[i].alivetime = 2;
             }
-            if (decaltype[i] == breakdecal && decaltype[i] != lasttype) {
-                breaktexture.bind();
-                if (!blend) {
-                    blend = 1;
-                    glAlphaFunc(GL_GREATER, 0.0001);
-                    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+            if (decals[i].type != lasttype) {
+                if (decals[i].type == shadowdecal) {
+                    shadowtexture.bind();
+                    if (!blend) {
+                        blend = 1;
+                        glAlphaFunc(GL_GREATER, 0.0001);
+                        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+                    }
                 }
-            }
-            if ((decaltype[i] == blooddecal || decaltype[i] == blooddecalslow) && decaltype[i] != lasttype) {
-                bloodtexture.bind();
-                if (blend) {
-                    blend = 0;
-                    glAlphaFunc(GL_GREATER, 0.15);
-                    glBlendFunc(GL_ONE, GL_ZERO);
+                if (decals[i].type == breakdecal) {
+                    breaktexture.bind();
+                    if (!blend) {
+                        blend = 1;
+                        glAlphaFunc(GL_GREATER, 0.0001);
+                        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+                    }
                 }
-            }
-            if ((decaltype[i] == blooddecalfast) && decaltype[i] != lasttype) {
-                bloodtexture2.bind();
-                if (blend) {
-                    blend = 0;
-                    glAlphaFunc(GL_GREATER, 0.15);
-                    glBlendFunc(GL_ONE, GL_ZERO);
+                if (decals[i].type == blooddecal || decals[i].type == blooddecalslow) {
+                    bloodtexture.bind();
+                    if (blend) {
+                        blend = 0;
+                        glAlphaFunc(GL_GREATER, 0.15);
+                        glBlendFunc(GL_ONE, GL_ZERO);
+                    }
+                }
+                if (decals[i].type == blooddecalfast) {
+                    bloodtexture2.bind();
+                    if (blend) {
+                        blend = 0;
+                        glAlphaFunc(GL_GREATER, 0.15);
+                        glBlendFunc(GL_ONE, GL_ZERO);
+                    }
                 }
             }
-            if (decaltype[i] == shadowdecal) {
-                glColor4f(1, 1, 1, decalopacity[i]);
+            if (decals[i].type == shadowdecal) {
+                glColor4f(1, 1, 1, decals[i].opacity);
             }
-            if (decaltype[i] == breakdecal) {
-                glColor4f(1, 1, 1, decalopacity[i]);
-                if (decalalivetime[i] > 58)
-                    glColor4f(1, 1, 1, decalopacity[i] * (60 - decalalivetime[i]) / 2);
+            if (decals[i].type == breakdecal) {
+                glColor4f(1, 1, 1, decals[i].opacity);
+                if (decals[i].alivetime > 58) {
+                    glColor4f(1, 1, 1, decals[i].opacity * (60 - decals[i].alivetime) / 2);
+                }
             }
-            if ((decaltype[i] == blooddecal || decaltype[i] == blooddecalfast || decaltype[i] == blooddecalslow)) {
-                glColor4f(1, 1, 1, decalopacity[i]);
-                if (decalalivetime[i] < 4)
-                    glColor4f(1, 1, 1, decalopacity[i]*decalalivetime[i]*.25);
-                if (decalalivetime[i] > 58)
-                    glColor4f(1, 1, 1, decalopacity[i] * (60 - decalalivetime[i]) / 2);
+            if ((decals[i].type == blooddecal || decals[i].type == blooddecalfast || decals[i].type == blooddecalslow)) {
+                glColor4f(1, 1, 1, decals[i].opacity);
+                if (decals[i].alivetime < 4) {
+                    glColor4f(1, 1, 1, decals[i].opacity * decals[i].alivetime * .25);
+                }
+                if (decals[i].alivetime > 58) {
+                    glColor4f(1, 1, 1, decals[i].opacity * (60 - decals[i].alivetime) / 2);
+                }
             }
-            lasttype = decaltype[i];
+            lasttype = decals[i].type;
             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
 
@@ -1042,22 +1010,26 @@ void Model::drawdecals(Texture shadowtexture, Texture bloodtexture, Texture bloo
             glPushMatrix();
             glBegin(GL_TRIANGLES);
             for (int j = 0; j < 3; j++) {
-                glTexCoord2f(decaltexcoords[i][j][0], decaltexcoords[i][j][1]);
-                glVertex3f(decalvertex[i][j].x, decalvertex[i][j].y, decalvertex[i][j].z);
+                glTexCoord2f(decals[i].texcoords[j][0], decals[i].texcoords[j][1]);
+                glVertex3f(decals[i].vertex[j].x, decals[i].vertex[j].y, decals[i].vertex[j].z);
             }
             glEnd();
             glPopMatrix();
         }
-        for (i = numdecals - 1; i >= 0; i--) {
-            decalalivetime[i] += multiplier;
-            if (decaltype[i] == blooddecalslow)
-                decalalivetime[i] -= multiplier * 2 / 3;
-            if (decaltype[i] == blooddecalfast)
-                decalalivetime[i] += multiplier * 4;
-            if (decaltype[i] == shadowdecal)
+        for (int i = decals.size() - 1; i >= 0; i--) {
+            decals[i].alivetime += multiplier;
+            if (decals[i].type == blooddecalslow) {
+                decals[i].alivetime -= multiplier * 2 / 3;
+            }
+            if (decals[i].type == blooddecalfast) {
+                decals[i].alivetime += multiplier * 4;
+            }
+            if (decals[i].type == shadowdecal) {
                 DeleteDecal(i);
-            if ((decaltype[i] == blooddecal || decaltype[i] == blooddecalfast || decaltype[i] == blooddecalslow) && decalalivetime[i] >= 60)
+            }
+            if ((decals[i].type == blooddecal || decals[i].type == blooddecalfast || decals[i].type == blooddecalslow) && decals[i].alivetime >= 60) {
                 DeleteDecal(i);
+            }
         }
         glAlphaFunc(GL_GREATER, 0.0001);
         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@@ -1066,407 +1038,216 @@ void Model::drawdecals(Texture shadowtexture, Texture bloodtexture, Texture bloo
 
 void Model::DeleteDecal(int which)
 {
-    if (decals) {
-        if (type != decalstype)
+    if (decalstoggle) {
+        if (type != decalstype) {
             return;
-        decaltype[which] = decaltype[numdecals - 1];
-        decalposition[which] = decalposition[numdecals - 1];
-        for (int i = 0; i < 3; i++) {
-            decalvertex[which][i] = decalvertex[numdecals - 1][i];
-            decaltexcoords[which][i][0] = decaltexcoords[numdecals - 1][i][0];
-            decaltexcoords[which][i][1] = decaltexcoords[numdecals - 1][i][1];
         }
-        decalrotation[which] = decalrotation[numdecals - 1];
-        decalalivetime[which] = decalalivetime[numdecals - 1];
-        decalopacity[which] = decalopacity[numdecals - 1];
-        numdecals--;
+        decals.erase(decals.begin() + which);
     }
 }
 
-void Model::MakeDecal(int atype, XYZ *where, float *size, float *opacity, float *rotation)
+void Model::MakeDecal(decal_type atype, XYZ* where, float* size, float* opacity, float* rotation)
 {
-    if (decals) {
-        if (type != decalstype)
+    if (decalstoggle) {
+        if (type != decalstype) {
             return;
+        }
 
-        static float placex, placez;
         static XYZ rot;
         static float distance;
-        static int i, j;
-
-        if (*opacity > 0)
-            if (distsq(where, &boundingspherecenter) < (boundingsphereradius + *size) * (boundingsphereradius + *size))
-                for (i = 0; i < TriangleNum; i++) {
-                    if (facenormals[i].y < -.1 && (vertex[Triangles[i].vertex[0]].y < where->y || vertex[Triangles[i].vertex[1]].y < where->y || vertex[Triangles[i].vertex[2]].y < where->y)) {
-                        decalposition[numdecals] = *where;
-                        decaltype[numdecals] = atype;
-                        decalrotation[numdecals] = *rotation;
-                        decalalivetime[numdecals] = 0;
-                        distance = abs(((facenormals[i].x * where->x) + (facenormals[i].y * where->y) + (facenormals[i].z * where->z) - ((facenormals[i].x * vertex[Triangles[i].vertex[0]].x) + (facenormals[i].y * vertex[Triangles[i].vertex[0]].y) + (facenormals[i].z * vertex[Triangles[i].vertex[0]].z))) / facenormals[i].y);
-                        decalopacity[numdecals] = *opacity - distance / 10;
-
-                        if (decalopacity[numdecals > 0]) {
-                            placex = vertex[Triangles[i].vertex[0]].x;
-                            placez = vertex[Triangles[i].vertex[0]].z;
-
-                            decaltexcoords[numdecals][0][0] = (placex - where->x) / (*size) / 2 + .5;
-                            decaltexcoords[numdecals][0][1] = (placez - where->z) / (*size) / 2 + .5;
 
-                            decalvertex[numdecals][0].x = placex;
-                            decalvertex[numdecals][0].z = placez;
-                            decalvertex[numdecals][0].y = vertex[Triangles[i].vertex[0]].y;
-
-
-                            placex = vertex[Triangles[i].vertex[1]].x;
-                            placez = vertex[Triangles[i].vertex[1]].z;
-
-                            decaltexcoords[numdecals][1][0] = (placex - where->x) / (*size) / 2 + .5;
-                            decaltexcoords[numdecals][1][1] = (placez - where->z) / (*size) / 2 + .5;
-
-                            decalvertex[numdecals][1].x = placex;
-                            decalvertex[numdecals][1].z = placez;
-                            decalvertex[numdecals][1].y = vertex[Triangles[i].vertex[1]].y;
-
-
-                            placex = vertex[Triangles[i].vertex[2]].x;
-                            placez = vertex[Triangles[i].vertex[2]].z;
-
-                            decaltexcoords[numdecals][2][0] = (placex - where->x) / (*size) / 2 + .5;
-                            decaltexcoords[numdecals][2][1] = (placez - where->z) / (*size) / 2 + .5;
-
-                            decalvertex[numdecals][2].x = placex;
-                            decalvertex[numdecals][2].z = placez;
-                            decalvertex[numdecals][2].y = vertex[Triangles[i].vertex[2]].y;
-
-                            if (!(decaltexcoords[numdecals][0][0] < 0 && decaltexcoords[numdecals][1][0] < 0 && decaltexcoords[numdecals][2][0] < 0))
-                                if (!(decaltexcoords[numdecals][0][1] < 0 && decaltexcoords[numdecals][1][1] < 0 && decaltexcoords[numdecals][2][1] < 0))
-                                    if (!(decaltexcoords[numdecals][0][0] > 1 && decaltexcoords[numdecals][1][0] > 1 && decaltexcoords[numdecals][2][0] > 1))
-                                        if (!(decaltexcoords[numdecals][0][1] > 1 && decaltexcoords[numdecals][1][1] > 1 && decaltexcoords[numdecals][2][1] > 1)) {
-                                            if (decalrotation[numdecals]) {
-                                                for (j = 0; j < 3; j++) {
+        if (*opacity > 0) {
+            if (distsq(where, &boundingspherecenter) < (boundingsphereradius + *size) * (boundingsphereradius + *size)) {
+                for (unsigned int i = 0; i < Triangles.size(); i++) {
+                    if (Triangles[i].facenormal.y < -.1 && (vertex[Triangles[i].vertex[0]].y < where->y || vertex[Triangles[i].vertex[1]].y < where->y || vertex[Triangles[i].vertex[2]].y < where->y)) {
+                        distance = abs(((Triangles[i].facenormal.x * where->x) + (Triangles[i].facenormal.y * where->y) + (Triangles[i].facenormal.z * where->z) - ((Triangles[i].facenormal.x * vertex[Triangles[i].vertex[0]].x) + (Triangles[i].facenormal.y * vertex[Triangles[i].vertex[0]].y) + (Triangles[i].facenormal.z * vertex[Triangles[i].vertex[0]].z))) / Triangles[i].facenormal.y);
+
+                        if ((*opacity - distance / 10) > 0) {
+                            Decal decal(*where, atype, *opacity - distance / 10, *rotation, *size, *this, i, 0);
+
+                            if (!(decal.texcoords[0][0] < 0 && decal.texcoords[1][0] < 0 && decal.texcoords[2][0] < 0)) {
+                                if (!(decal.texcoords[0][1] < 0 && decal.texcoords[1][1] < 0 && decal.texcoords[2][1] < 0)) {
+                                    if (!(decal.texcoords[0][0] > 1 && decal.texcoords[1][0] > 1 && decal.texcoords[2][0] > 1)) {
+                                        if (!(decal.texcoords[0][1] > 1 && decal.texcoords[1][1] > 1 && decal.texcoords[2][1] > 1)) {
+                                            if (decal.rotation) {
+                                                for (int j = 0; j < 3; j++) {
                                                     rot.y = 0;
-                                                    rot.x = decaltexcoords[numdecals][j][0] - .5;
-                                                    rot.z = decaltexcoords[numdecals][j][1] - .5;
-                                                    rot = DoRotation(rot, 0, -decalrotation[numdecals], 0);
-                                                    decaltexcoords[numdecals][j][0] = rot.x + .5;
-                                                    decaltexcoords[numdecals][j][1] = rot.z + .5;
+                                                    rot.x = decal.texcoords[j][0] - .5;
+                                                    rot.z = decal.texcoords[j][1] - .5;
+                                                    rot = DoRotation(rot, 0, -decal.rotation, 0);
+                                                    decal.texcoords[j][0] = rot.x + .5;
+                                                    decal.texcoords[j][1] = rot.z + .5;
                                                 }
                                             }
-                                            if (numdecals < max_model_decals - 1)
-                                                numdecals++;
+                                            if (decals.size() < max_model_decals - 1) {
+                                                decals.push_back(decal);
+                                            }
                                         }
+                                    }
+                                }
+                            }
                         }
                     }
                 }
+            }
+        }
     }
 }
 
-void Model::MakeDecal(int atype, XYZ where, float size, float opacity, float rotation)
+void Model::MakeDecal(decal_type atype, XYZ where, float size, float opacity, float rotation)
 {
-    if (decals) {
-        if (type != decalstype)
+    if (decalstoggle) {
+        if (type != decalstype) {
             return;
+        }
 
-        static float placex, placez;
         static XYZ rot;
         static float distance;
-        static int i, j;
-
-        if (opacity > 0)
-            if (distsq(&where, &boundingspherecenter) < (boundingsphereradius + size) * (boundingsphereradius + size))
-                for (i = 0; i < TriangleNum; i++) {
-                    distance = abs(((facenormals[i].x * where.x) + (facenormals[i].y * where.y) + (facenormals[i].z * where.z) - ((facenormals[i].x * vertex[Triangles[i].vertex[0]].x) + (facenormals[i].y * vertex[Triangles[i].vertex[0]].y) + (facenormals[i].z * vertex[Triangles[i].vertex[0]].z))));
-                    if (distance < .02 && abs(facenormals[i].y) > abs(facenormals[i].x) && abs(facenormals[i].y) > abs(facenormals[i].z)) {
-                        decalposition[numdecals] = where;
-                        decaltype[numdecals] = atype;
-                        decalrotation[numdecals] = rotation;
-                        decalalivetime[numdecals] = 0;
-                        decalopacity[numdecals] = opacity - distance / 10;
-
-                        if (decalopacity[numdecals > 0]) {
-                            placex = vertex[Triangles[i].vertex[0]].x;
-                            placez = vertex[Triangles[i].vertex[0]].z;
-
-                            decaltexcoords[numdecals][0][0] = (placex - where.x) / (size) / 2 + .5;
-                            decaltexcoords[numdecals][0][1] = (placez - where.z) / (size) / 2 + .5;
-
-                            decalvertex[numdecals][0].x = placex;
-                            decalvertex[numdecals][0].z = placez;
-                            decalvertex[numdecals][0].y = vertex[Triangles[i].vertex[0]].y;
 
-
-                            placex = vertex[Triangles[i].vertex[1]].x;
-                            placez = vertex[Triangles[i].vertex[1]].z;
-
-                            decaltexcoords[numdecals][1][0] = (placex - where.x) / (size) / 2 + .5;
-                            decaltexcoords[numdecals][1][1] = (placez - where.z) / (size) / 2 + .5;
-
-                            decalvertex[numdecals][1].x = placex;
-                            decalvertex[numdecals][1].z = placez;
-                            decalvertex[numdecals][1].y = vertex[Triangles[i].vertex[1]].y;
-
-
-                            placex = vertex[Triangles[i].vertex[2]].x;
-                            placez = vertex[Triangles[i].vertex[2]].z;
-
-                            decaltexcoords[numdecals][2][0] = (placex - where.x) / (size) / 2 + .5;
-                            decaltexcoords[numdecals][2][1] = (placez - where.z) / (size) / 2 + .5;
-
-                            decalvertex[numdecals][2].x = placex;
-                            decalvertex[numdecals][2].z = placez;
-                            decalvertex[numdecals][2].y = vertex[Triangles[i].vertex[2]].y;
-
-                            if (!(decaltexcoords[numdecals][0][0] < 0 && decaltexcoords[numdecals][1][0] < 0 && decaltexcoords[numdecals][2][0] < 0))
-                                if (!(decaltexcoords[numdecals][0][1] < 0 && decaltexcoords[numdecals][1][1] < 0 && decaltexcoords[numdecals][2][1] < 0))
-                                    if (!(decaltexcoords[numdecals][0][0] > 1 && decaltexcoords[numdecals][1][0] > 1 && decaltexcoords[numdecals][2][0] > 1))
-                                        if (!(decaltexcoords[numdecals][0][1] > 1 && decaltexcoords[numdecals][1][1] > 1 && decaltexcoords[numdecals][2][1] > 1)) {
-                                            if (decalrotation[numdecals]) {
-                                                for (j = 0; j < 3; j++) {
+        if (opacity > 0) {
+            if (distsq(&where, &boundingspherecenter) < (boundingsphereradius + size) * (boundingsphereradius + size)) {
+                for (unsigned int i = 0; i < Triangles.size(); i++) {
+                    distance = abs(((Triangles[i].facenormal.x * where.x) + (Triangles[i].facenormal.y * where.y) + (Triangles[i].facenormal.z * where.z) - ((Triangles[i].facenormal.x * vertex[Triangles[i].vertex[0]].x) + (Triangles[i].facenormal.y * vertex[Triangles[i].vertex[0]].y) + (Triangles[i].facenormal.z * vertex[Triangles[i].vertex[0]].z))));
+                    if (distance < .02 && abs(Triangles[i].facenormal.y) > abs(Triangles[i].facenormal.x) && abs(Triangles[i].facenormal.y) > abs(Triangles[i].facenormal.z)) {
+                        if ((opacity - distance / 10) > 0) {
+                            Decal decal(where, atype, opacity - distance / 10, rotation, size, *this, i, 0);
+
+                            if (!(decal.texcoords[0][0] < 0 && decal.texcoords[1][0] < 0 && decal.texcoords[2][0] < 0)) {
+                                if (!(decal.texcoords[0][1] < 0 && decal.texcoords[1][1] < 0 && decal.texcoords[2][1] < 0)) {
+                                    if (!(decal.texcoords[0][0] > 1 && decal.texcoords[1][0] > 1 && decal.texcoords[2][0] > 1)) {
+                                        if (!(decal.texcoords[0][1] > 1 && decal.texcoords[1][1] > 1 && decal.texcoords[2][1] > 1)) {
+                                            if (decal.rotation) {
+                                                for (int j = 0; j < 3; j++) {
                                                     rot.y = 0;
-                                                    rot.x = decaltexcoords[numdecals][j][0] - .5;
-                                                    rot.z = decaltexcoords[numdecals][j][1] - .5;
-                                                    rot = DoRotation(rot, 0, -decalrotation[numdecals], 0);
-                                                    decaltexcoords[numdecals][j][0] = rot.x + .5;
-                                                    decaltexcoords[numdecals][j][1] = rot.z + .5;
+                                                    rot.x = decal.texcoords[j][0] - .5;
+                                                    rot.z = decal.texcoords[j][1] - .5;
+                                                    rot = DoRotation(rot, 0, -decal.rotation, 0);
+                                                    decal.texcoords[j][0] = rot.x + .5;
+                                                    decal.texcoords[j][1] = rot.z + .5;
                                                 }
                                             }
-                                            if (numdecals < max_model_decals - 1)
-                                                numdecals++;
+                                            if (decals.size() < max_model_decals - 1) {
+                                                decals.push_back(decal);
+                                            }
                                         }
+                                    }
+                                }
+                            }
                         }
-                    } else if (distance < .02 && abs(facenormals[i].x) > abs(facenormals[i].y) && abs(facenormals[i].x) > abs(facenormals[i].z)) {
-                        decalposition[numdecals] = where;
-                        decaltype[numdecals] = atype;
-                        decalrotation[numdecals] = rotation;
-                        decalalivetime[numdecals] = 0;
-                        decalopacity[numdecals] = opacity - distance / 10;
-
-                        if (decalopacity[numdecals > 0]) {
-                            placex = vertex[Triangles[i].vertex[0]].y;
-                            placez = vertex[Triangles[i].vertex[0]].z;
-
-                            decaltexcoords[numdecals][0][0] = (placex - where.y) / (size) / 2 + .5;
-                            decaltexcoords[numdecals][0][1] = (placez - where.z) / (size) / 2 + .5;
-
-                            decalvertex[numdecals][0].x = vertex[Triangles[i].vertex[0]].x;
-                            decalvertex[numdecals][0].z = placez;
-                            decalvertex[numdecals][0].y = placex;
-
-
-                            placex = vertex[Triangles[i].vertex[1]].y;
-                            placez = vertex[Triangles[i].vertex[1]].z;
-
-                            decaltexcoords[numdecals][1][0] = (placex - where.y) / (size) / 2 + .5;
-                            decaltexcoords[numdecals][1][1] = (placez - where.z) / (size) / 2 + .5;
-
-                            decalvertex[numdecals][1].x = vertex[Triangles[i].vertex[1]].x;
-                            decalvertex[numdecals][1].z = placez;
-                            decalvertex[numdecals][1].y = placex;
-
-
-                            placex = vertex[Triangles[i].vertex[2]].y;
-                            placez = vertex[Triangles[i].vertex[2]].z;
-
-                            decaltexcoords[numdecals][2][0] = (placex - where.y) / (size) / 2 + .5;
-                            decaltexcoords[numdecals][2][1] = (placez - where.z) / (size) / 2 + .5;
-
-                            decalvertex[numdecals][2].x = vertex[Triangles[i].vertex[2]].x;
-                            decalvertex[numdecals][2].z = placez;
-                            decalvertex[numdecals][2].y = placex;
-
-                            if (!(decaltexcoords[numdecals][0][0] < 0 && decaltexcoords[numdecals][1][0] < 0 && decaltexcoords[numdecals][2][0] < 0))
-                                if (!(decaltexcoords[numdecals][0][1] < 0 && decaltexcoords[numdecals][1][1] < 0 && decaltexcoords[numdecals][2][1] < 0))
-                                    if (!(decaltexcoords[numdecals][0][0] > 1 && decaltexcoords[numdecals][1][0] > 1 && decaltexcoords[numdecals][2][0] > 1))
-                                        if (!(decaltexcoords[numdecals][0][1] > 1 && decaltexcoords[numdecals][1][1] > 1 && decaltexcoords[numdecals][2][1] > 1)) {
-                                            if (decalrotation[numdecals]) {
-                                                for (j = 0; j < 3; j++) {
+                    } else if (distance < .02 && abs(Triangles[i].facenormal.x) > abs(Triangles[i].facenormal.y) && abs(Triangles[i].facenormal.x) > abs(Triangles[i].facenormal.z)) {
+                        if ((opacity - distance / 10) > 0) {
+                            Decal decal(where, atype, opacity - distance / 10, rotation, size, *this, i, 1);
+
+                            if (!(decal.texcoords[0][0] < 0 && decal.texcoords[1][0] < 0 && decal.texcoords[2][0] < 0)) {
+                                if (!(decal.texcoords[0][1] < 0 && decal.texcoords[1][1] < 0 && decal.texcoords[2][1] < 0)) {
+                                    if (!(decal.texcoords[0][0] > 1 && decal.texcoords[1][0] > 1 && decal.texcoords[2][0] > 1)) {
+                                        if (!(decal.texcoords[0][1] > 1 && decal.texcoords[1][1] > 1 && decal.texcoords[2][1] > 1)) {
+                                            if (decal.rotation) {
+                                                for (int j = 0; j < 3; j++) {
                                                     rot.y = 0;
-                                                    rot.x = decaltexcoords[numdecals][j][0] - .5;
-                                                    rot.z = decaltexcoords[numdecals][j][1] - .5;
-                                                    rot = DoRotation(rot, 0, -decalrotation[numdecals], 0);
-                                                    decaltexcoords[numdecals][j][0] = rot.x + .5;
-                                                    decaltexcoords[numdecals][j][1] = rot.z + .5;
+                                                    rot.x = decal.texcoords[j][0] - .5;
+                                                    rot.z = decal.texcoords[j][1] - .5;
+                                                    rot = DoRotation(rot, 0, -decal.rotation, 0);
+                                                    decal.texcoords[j][0] = rot.x + .5;
+                                                    decal.texcoords[j][1] = rot.z + .5;
                                                 }
                                             }
-                                            if (numdecals < max_model_decals - 1)
-                                                numdecals++;
+                                            if (decals.size() < max_model_decals - 1) {
+                                                decals.push_back(decal);
+                                            }
                                         }
+                                    }
+                                }
+                            }
                         }
-                    } else if (distance < .02 && abs(facenormals[i].z) > abs(facenormals[i].y) && abs(facenormals[i].z) > abs(facenormals[i].x)) {
-                        decalposition[numdecals] = where;
-                        decaltype[numdecals] = atype;
-                        decalrotation[numdecals] = rotation;
-                        decalalivetime[numdecals] = 0;
-                        decalopacity[numdecals] = opacity - distance / 10;
-
-                        if (decalopacity[numdecals > 0]) {
-                            placex = vertex[Triangles[i].vertex[0]].x;
-                            placez = vertex[Triangles[i].vertex[0]].y;
-
-                            decaltexcoords[numdecals][0][0] = (placex - where.x) / (size) / 2 + .5;
-                            decaltexcoords[numdecals][0][1] = (placez - where.y) / (size) / 2 + .5;
-
-                            decalvertex[numdecals][0].x = placex;
-                            decalvertex[numdecals][0].z = vertex[Triangles[i].vertex[0]].z;
-                            decalvertex[numdecals][0].y = placez;
-
-
-                            placex = vertex[Triangles[i].vertex[1]].x;
-                            placez = vertex[Triangles[i].vertex[1]].y;
-
-                            decaltexcoords[numdecals][1][0] = (placex - where.x) / (size) / 2 + .5;
-                            decaltexcoords[numdecals][1][1] = (placez - where.y) / (size) / 2 + .5;
-
-                            decalvertex[numdecals][1].x = placex;
-                            decalvertex[numdecals][1].z = vertex[Triangles[i].vertex[1]].z;
-                            decalvertex[numdecals][1].y = placez;
-
-
-                            placex = vertex[Triangles[i].vertex[2]].x;
-                            placez = vertex[Triangles[i].vertex[2]].y;
-
-                            decaltexcoords[numdecals][2][0] = (placex - where.x) / (size) / 2 + .5;
-                            decaltexcoords[numdecals][2][1] = (placez - where.y) / (size) / 2 + .5;
-
-                            decalvertex[numdecals][2].x = placex;
-                            decalvertex[numdecals][2].z = vertex[Triangles[i].vertex[2]].z;
-                            decalvertex[numdecals][2].y = placez;
-
-                            if (!(decaltexcoords[numdecals][0][0] < 0 && decaltexcoords[numdecals][1][0] < 0 && decaltexcoords[numdecals][2][0] < 0))
-                                if (!(decaltexcoords[numdecals][0][1] < 0 && decaltexcoords[numdecals][1][1] < 0 && decaltexcoords[numdecals][2][1] < 0))
-                                    if (!(decaltexcoords[numdecals][0][0] > 1 && decaltexcoords[numdecals][1][0] > 1 && decaltexcoords[numdecals][2][0] > 1))
-                                        if (!(decaltexcoords[numdecals][0][1] > 1 && decaltexcoords[numdecals][1][1] > 1 && decaltexcoords[numdecals][2][1] > 1)) {
-                                            if (decalrotation[numdecals]) {
-                                                for (j = 0; j < 3; j++) {
+                    } else if (distance < .02 && abs(Triangles[i].facenormal.z) > abs(Triangles[i].facenormal.y) && abs(Triangles[i].facenormal.z) > abs(Triangles[i].facenormal.x)) {
+                        if ((opacity - distance / 10) > 0) {
+                            Decal decal(where, atype, opacity - distance / 10, rotation, size, *this, i, 2);
+
+                            if (!(decal.texcoords[0][0] < 0 && decal.texcoords[1][0] < 0 && decal.texcoords[2][0] < 0)) {
+                                if (!(decal.texcoords[0][1] < 0 && decal.texcoords[1][1] < 0 && decal.texcoords[2][1] < 0)) {
+                                    if (!(decal.texcoords[0][0] > 1 && decal.texcoords[1][0] > 1 && decal.texcoords[2][0] > 1)) {
+                                        if (!(decal.texcoords[0][1] > 1 && decal.texcoords[1][1] > 1 && decal.texcoords[2][1] > 1)) {
+                                            if (decal.rotation) {
+                                                for (int j = 0; j < 3; j++) {
                                                     rot.y = 0;
-                                                    rot.x = decaltexcoords[numdecals][j][0] - .5;
-                                                    rot.z = decaltexcoords[numdecals][j][1] - .5;
-                                                    rot = DoRotation(rot, 0, -decalrotation[numdecals], 0);
-                                                    decaltexcoords[numdecals][j][0] = rot.x + .5;
-                                                    decaltexcoords[numdecals][j][1] = rot.z + .5;
+                                                    rot.x = decal.texcoords[j][0] - .5;
+                                                    rot.z = decal.texcoords[j][1] - .5;
+                                                    rot = DoRotation(rot, 0, -decal.rotation, 0);
+                                                    decal.texcoords[j][0] = rot.x + .5;
+                                                    decal.texcoords[j][1] = rot.z + .5;
                                                 }
                                             }
-                                            if (numdecals < max_model_decals - 1)
-                                                numdecals++;
+                                            if (decals.size() < max_model_decals - 1) {
+                                                decals.push_back(decal);
+                                            }
                                         }
+                                    }
+                                }
+                            }
                         }
                     }
                 }
+            }
+        }
+    }
+}
+
+const XYZ& Model::getTriangleVertex(unsigned triangleId, unsigned vertexId) const
+{
+    return vertex[Triangles[triangleId].vertex[vertexId]];
+}
+
+void Model::deleteDeadDecals()
+{
+    for (int i = decals.size() - 1; i >= 0; i--) {
+        if ((decals[i].type == blooddecal || decals[i].type == blooddecalslow) && decals[i].alivetime < 2) {
+            DeleteDecal(i);
+        }
     }
 }
 
 Model::~Model()
 {
     deallocate();
-    textureptr.destroy();
 }
 
 void Model::deallocate()
 {
-    int i = 0, j = 0;
-
-    if (owner)
+    if (owner) {
         free(owner);
+    }
     owner = 0;
 
-    if (possible)
-        free(possible);
-    possible = 0;
-
-    if (vertex)
+    if (vertex) {
         free(vertex);
+    }
     vertex = 0;
 
-    if (normals)
+    if (normals) {
         free(normals);
+    }
     normals = 0;
 
-    if (facenormals)
-        free(facenormals);
-    facenormals = 0;
-
-    if (Triangles)
-        free(Triangles);
-    Triangles = 0;
-
-    if (vArray)
+    if (vArray) {
         free(vArray);
-    vArray = 0;
-
-
-    //allow decals
-    if (decaltexcoords) {
-        for (i = 0; i < max_model_decals; i++) {
-            for (j = 0; j < 3; j++) {
-                free(decaltexcoords[i][j]);
-            }
-            free(decaltexcoords[i]);
-        }
-        free(decaltexcoords);
     }
-    decaltexcoords = 0;
-
-
-    if (decalvertex) {
-        for (i = 0; i < max_model_decals; i++) {
-            free(decalvertex[i]);
-        }
-        free(decalvertex);
-    }
-    decalvertex = 0;
-
-
-    free(decaltype);
-    decaltype = 0;
-
-    free(decalopacity);
-    decalopacity = 0;
-
-    free(decalrotation);
-    decalrotation = 0;
-
-    free(decalalivetime);
-    decalalivetime = 0;
-
-    free(decalposition);
-    decalposition = 0;
+    vArray = 0;
 
+    decals.clear();
 }
 
 Model::Model()
+    : vertexNum(0)
+    , type(nothing)
+    , owner(0)
+    , vertex(0)
+    , normals(0)
+    , vArray(0)
+    , color(0)
+    , boundingspherecenter()
+    , boundingsphereradius(0)
+    , flat(false)
 {
-    vertexNum = 0, TriangleNum = 0;
-    hastexture = 0;
-
-    type = 0, oldtype = 0;
-
-    possible = 0;
-    owner = 0;
-    vertex = 0;
-    normals = 0;
-    facenormals = 0;
-    Triangles = 0;
-    vArray = 0;
-
     memset(&modelTexture, 0, sizeof(modelTexture));
-    numpossible = 0;
-    color = 0;
-
-    boundingspherecenter = 0;
-    boundingsphereradius = 0;
-
-    decaltexcoords = 0;
-    decalvertex = 0;
-    decaltype = 0;
-    decalopacity = 0;
-    decalrotation = 0;
-    decalalivetime = 0;
-    decalposition = 0;
-
-    numdecals = 0;
-
-    flat = 0;
-
-    type = nothing;
 }
-