vector<Point> findPoly(int vertices, vector<Point> points) { double angle = (2 * M_PI) / ((double)vertices); double dist = radius(points); Point center = polyCenter(points); Point offset = center + Point(0, 2 * dist); vector<Point> result; vector<Point> polygon; Point first = rotateAround(center, offset, - (0.5 * angle)); polygon.push_back(first); for (int i = 0; i < vertices - 1; i++) { Point p = rotateAround(center, first, angle * (i+1)); polygon.push_back(p); } return correlate(polygon, points); }
bool MeshMod_FixPipe::apply(Mesh *mesh) { int i, j; rvfloat minHeights[8] = { -1e9,-1e9,-1e9,-1e9,-1e9,-1e9,-1e9,-1e9 }; Polygon *newPolys [8] = { NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL }; Vector polyCenters[8]; bool pipe = false; for (i = 0; i < mesh->data.num_polys; i++) { if (mesh->poly[i]->detTEPart() & TEP_PIPE) { pipe = true; break; } } if (!pipe) { return true; } rvfloat meshMinX = mesh->verts[0]->pos.coord[0]; rvfloat meshMaxX = mesh->verts[0]->pos.coord[0]; rvfloat meshMinZ = mesh->verts[0]->pos.coord[2]; rvfloat meshMaxZ = mesh->verts[0]->pos.coord[2]; for (i = 1; i < mesh->data.num_vecs; i++) { Vertex *v = mesh->verts[i]; if (meshMinX > v->pos.coord[0] - 0.5) { meshMinX = v->pos.coord[0]; } if (meshMaxX < v->pos.coord[0] + 0.5) { meshMaxX = v->pos.coord[0]; } if (meshMinZ > v->pos.coord[2] - 0.5) { meshMinZ = v->pos.coord[2]; } if (meshMaxZ < v->pos.coord[2] + 0.5) { meshMaxZ = v->pos.coord[2]; } } Vector meshCenter( floor((meshMinX + meshMaxX) / 2000 + 0.5) * 1000, 0.0f, floor((meshMinZ + meshMaxZ) / 2000 + 0.5) * 1000); for (i = 0; i < mesh->data.num_polys; i++) { Polygon *p = mesh->poly[i]; if (p->detTEPart() & (TEP_PWALL | TEP_PIPE)) { rvfloat minHeight = -1e9; Vector polyCenter(0.0, 0.0, 0.0); for (j = 0; j < p->numverts(); j++) { Vertex *v = mesh->verts[p->vertidx(j)]; polyCenter = polyCenter + v->pos; if (minHeight < v->pos.coord[1]) { minHeight = v->pos.coord[1]; } } Vector polyCoord = polyCenter * 0.25; polyCenter = polyCoord - meshCenter; int octant = (int) ((atan2(polyCenter.z(), polyCenter.x()) + M_PI) / (M_PI / 4)); if (p->detTEPart() & TEP_PIPE) { if (minHeights[octant] < minHeight) { minHeights[octant] = minHeight; } } if ((p->detTEPart() & TEP_PWALL) && p->numverts() == 4) { Vector& v0 = mesh->verts[p->vertidx(0)]->pos; Vector& v1 = mesh->verts[p->vertidx(1)]->pos; Vector& v2 = mesh->verts[p->vertidx(2)]->pos; rvfloat w = (v0 - v1).length(); rvfloat h = (v2 - v1).length(); if (fabs(w - 125.0) < 0.5 && fabs(h - 125.0) < 0.5) { // Check if we've encountered an indentical polygon before, // and if so, delete the current one so we don't end up with // duplicates bool found = false; for (j = 0; j < polyList.size(); j++) { if ((polyList[j].center - polyCoord).length() < 1.0) { found = true; break; } } if (found) { delete mesh->poly[i]; mesh->poly[i] = NULL; } else { polyList.push_back(PolyInfo(p, polyCoord)); } } } } } for (i = 0; i < mesh->data.num_polys; i++) { Polygon *p = mesh->poly[i]; if (p->isInTexture(0, 0.5,1.0, 0.0,0.375)) { rvfloat minX = 1.0e9f, maxX = -1.0e9f; rvfloat minZ = 1.0e9f, maxZ = -1.0e9f; Vector polyCenter(0.0, 0.0, 0.0); for (j = 0; j < p->numverts(); j++) { Vertex *v = mesh->verts[p->vertidx(j)]; polyCenter = polyCenter + v->pos; if (minX > v->pos.coord[0]) { minX = v->pos.coord[0]; } if (maxX < v->pos.coord[0]) { maxX = v->pos.coord[0]; } if (minZ > v->pos.coord[2]) { minZ = v->pos.coord[2]; } if (maxZ < v->pos.coord[2]) { maxZ = v->pos.coord[2]; } } Vector polyCoord = polyCenter / (rvfloat) p->numverts(); polyCenter = polyCoord - meshCenter; int octant = (int) ((atan2(polyCenter.z(), polyCenter.x()) + M_PI) / (M_PI / 4)); if (newPolys[octant] == NULL && (fabs(maxX - minX) < 0.5 || fabs(maxZ - minZ) < 0.5) && fabs(polyCenter.x()) > 10.0 && fabs(polyCenter.z()) > 10.0) { Vector p[4]; Vector norm; // Find the corners of the new polygon switch (octant) { case 0: p[3] = Vector(-500, minHeights[octant] + 125, -500); p[2] = Vector(-500, minHeights[octant] , -500); p[1] = Vector(-500, minHeights[octant] , -375); p[0] = Vector(-500, minHeights[octant] + 125, -375); norm = Vector(-1.0, 0.0, 0.0); break; case 1: p[0] = Vector(-375, minHeights[octant] , -500); p[1] = Vector(-375, minHeights[octant] + 125, -500); p[2] = Vector(-500, minHeights[octant] + 125, -500); p[3] = Vector(-500, minHeights[octant] , -500); norm = Vector(0.0, 0.0, -1.0); break; case 2: p[3] = Vector(375, minHeights[octant] , -500); p[2] = Vector(375, minHeights[octant] + 125, -500); p[1] = Vector(500, minHeights[octant] + 125, -500); p[0] = Vector(500, minHeights[octant] , -500); norm = Vector(0.0, 0.0, -1.0); break; case 3: p[0] = Vector(500, minHeights[octant] + 125, -500); p[1] = Vector(500, minHeights[octant] , -500); p[2] = Vector(500, minHeights[octant] , -375); p[3] = Vector(500, minHeights[octant] + 125, -375); norm = Vector(-1.0, 0.0, 0.0); break; case 4: p[3] = Vector(500, minHeights[octant] + 125, 500); p[2] = Vector(500, minHeights[octant] , 500); p[1] = Vector(500, minHeights[octant] , 375); p[0] = Vector(500, minHeights[octant] + 125, 375); norm = Vector(-1.0, 0.0, 0.0); break; case 5: p[0] = Vector(375, minHeights[octant] , 500); p[1] = Vector(375, minHeights[octant] + 125, 500); p[2] = Vector(500, minHeights[octant] + 125, 500); p[3] = Vector(500, minHeights[octant] , 500); norm = Vector(0.0, 0.0, -1.0); break; case 6: p[3] = Vector(-375, minHeights[octant] , 500); p[2] = Vector(-375, minHeights[octant] + 125, 500); p[1] = Vector(-500, minHeights[octant] + 125, 500); p[0] = Vector(-500, minHeights[octant] , 500); norm = Vector(0.0, 0.0, -1.0); break; case 7: p[0] = Vector(-500, minHeights[octant] + 125, 500); p[1] = Vector(-500, minHeights[octant] , 500); p[2] = Vector(-500, minHeights[octant] , 375); p[3] = Vector(-500, minHeights[octant] + 125, 375); norm = Vector(-1.0, 0.0, 0.0); break; } for (j = 0; j < 4; j++) { // Translate to the mesh position p[j] = p[j] + meshCenter; // Add the vertex Vertex vert(p[j], norm); mesh->add(new Vertex(&vert)); } // add a new polygon RV_Poly polyData = { 1, 0, { mesh->data.num_vecs - 4, mesh->data.num_vecs - 3, mesh->data.num_vecs - 2, mesh->data.num_vecs - 1 }, { {0xFFFFFF}, {0xFFFFFF}, {0xFFFFFF}, {0xFFFFFF} }, { { 0.0, 0.0 }, { 0.0, 0.0 }, { 0.0, 0.0 }, { 0.0, 0.0 } } }; polyCenter = (p[0] + p[1] + p[2] + p[3]) / 4; // Check if we've encountered an indentical polygon before, // and if so, use that instead of creating a new one bool found = false; for (j = 0; j < polyList.size(); j++) { if ((polyList[j].center - polyCenter).length() < 1.0) { found = true; break; } } if (found) { newPolys[octant] = polyList[j].poly; } else { newPolys[octant] = new Polygon(mesh, &polyData); mesh->add(newPolys[octant]); polyList.push_back(PolyInfo(newPolys[octant], polyCenter)); } polyCenters[octant] = polyCenter; } } } // Finally, put textures on the "missing pieces" for (i = 0; i < 8; i++) { if (newPolys[i]) { Polygon *p = newPolys[i]; p->data.texture = 0; for (int j = 0; j < p->numverts(); j++) { Vertex *v = mesh->verts[p->vertidx(j)]; Vector relPos = v->pos - Vector(meshMinX, 0, meshMinZ); rvfloat x = relPos.lengthXZ(); rvfloat y = relPos.y(); if ((relPos.x() < 0.5 || relPos.x() > 999.5) && (relPos.z() < 0.5 || relPos.z() > 999.5)) { p->data.texcoord[j].u = 0.504f; } else { p->data.texcoord[j].u = 0.625f; } if (relPos.y() > polyCenters[i].y() + 0.5) { p->data.texcoord[j].v = 0.371f; } else { p->data.texcoord[j].v = 0.250f; } p->data.color[j].value = 0xFFFFFF; } } } return true; }