#include #include #include "Decals.h" #define NORMAL_OFFSET 0.02f enum corner { SW, SE, NE, NW }; void bind(struct Decals *d, XYZ location, float size, XYZ normal, int poly, Model *model, XYZ move, float rotation, XYZ right, XYZ up, enum corner direction) { float x, y; switch (direction) { case SW: x = -1.0f; y = -1.0f; break; case NW: x = 1.0f; y = -1.0f; break; case NE: x = 1.0f; y = 1.0f; break; case SE: x = -1.0f; y = 1.0f; break; } size_t i = d->len * 8 + d->numpoints[d->len]; d->points[i] = location + right * x + up * y; d->texcoordsx[i] = x * 0.5f + 0.5f; d->texcoordsy[i] = y * 0.5f + 0.5f; XYZ temp; if ((move.x == 0 && move.y == 0 && move.z == 0 && rotation == 0) || segCrossTrigon(d->points[i] + normal / 25, d->points[i] - normal / 25, model->vertex + model->Triangles[poly].vertex[0], model->vertex + model->Triangles[poly].vertex[1], model->vertex + model->Triangles[poly].vertex[2], &normal, &temp)) { d->numpoints[d->len]++; return; } const auto n = normal / 25.0f; const float countinc = std::max(0.01f, std::min(1.0f / size, 0.2f)); int good = -1; float count = 1.0f - countinc; while (good == -1 && count > -1.0f) { d->texcoordsx[i] = x * 0.5f + 0.5f; d->texcoordsy[i] = y * count * 0.5f + 0.5f; d->points[i] = location + right * x + up * (y * count); count -= countinc; good = model->LineCheck2(d->points[i] + n, d->points[i] - n, &temp, move, rotation); } if (good > -1) { d->numpoints[d->len]++; i++; } good = -1; count = 1.0f - countinc; while (good == -1 && count > -1.0f) { d->texcoordsx[i] = x * count * 0.5f + 0.5f; d->texcoordsy[i] = y * 0.5f + 0.5f; d->points[i] = location + right * (x * count) + up * y; count -= countinc; good = model->LineCheck2(d->points[i] + n, d->points[i] - n, &temp, move, rotation); } if (good > -1) { d->numpoints[d->len]++; return; } float count2 = 1.0f - countinc; while (good == -1 && count2 > -1.0f){ count = 1.0f - countinc; while (good == -1 && count > -1.0f) { d->texcoordsx[i] = x * count2 * 0.5f + 0.5f; d->texcoordsy[i] = y * count * 0.5f + 0.5f; d->points[i] = location + right * (x * count2) + up * (y * count); count -= countinc; good = model->LineCheck2(d->points[i] + n, d->points[i] - n, &temp, move, rotation); } count2 -= countinc; } if (good > -1) d->numpoints[d->len]++; } void addDecal(struct Decals *d, enum decal kind, XYZ location, float size, XYZ normal, int poly, Model *model, XYZ move, float rotation) { if (d->len >= MAX_DECALS) return; d->kind[d->len] = kind; d->alive[d->len] = 0; float normalv[] = {abs(normal.x), abs(normal.y), abs(normal.z)}; unsigned char major = 0; if (normalv[1] > normalv[major]) major = 1; if (normalv[2] > normalv[major]) major = 2; XYZ right = {0.0f}; if (normalv[0] == 1.0f || normalv[1] == 1.0f || normalv[2] == 1.0f) { if ((major == 0 && normal.x > 0) || major == 1) right.z = -1.0f; else if (major == 0) right.z = 1.0f; else right.x = normal.z; } else { XYZ axis = {0.0f}; ((float *) &axis)[major] = 1.0f; right = crossProduct(axis, normal); } d->numpoints[d->len] = 0; XYZ up = normalize(crossProduct(normal, right)) * (size / 3); right = normalize(right) * (size / 3); bind(d, location, size, normal, poly, model, move, rotation, right, up, SW); bind(d, location, size, normal, poly, model, move, rotation, right, up, NW); bind(d, location, size, normal, poly, model, move, rotation, right, up, NE); bind(d, location, size, normal, poly, model, move, rotation, right, up, SE); for (int i = 0; i < d->numpoints[d->len]; ++i) d->points[d->len * 8 + i] += normal * NORMAL_OFFSET; d->len++; }