#include "meshutil.hpp" #include "std.hpp" MeshModel* MeshUtil::createCube(const Brush& b) { static Vector norms[] = {Vector(0, 0, -1), Vector(1, 0, 0), Vector(0, 0, 1), Vector(-1, 0, 0), Vector(0, 1, 0), Vector(0, -1, 0)}; static Vector tex_coords[] = {Vector(0, 0, 1), Vector(1, 0, 1), Vector(1, 1, 1), Vector(0, 1, 1)}; static int verts[] = {2, 3, 1, 0, 3, 7, 5, 1, 7, 6, 4, 5, 6, 2, 0, 4, 6, 7, 3, 2, 0, 1, 5, 4}; static Box box(Vector(-1, -1, -1), Vector(1, 1, 1)); MeshModel* m = new MeshModel(); Surface* s = m->createSurface(b); Surface::Vertex v; Surface::Triangle t; for (int k = 0; k < 24; k += 4) { const Vector& normal = norms[k / 4]; for (int j = 0; j < 4; ++j) { v.coords = box.corner(verts[k + j]); v.normal = normal; v.tex_coords[0][0] = v.tex_coords[1][0] = tex_coords[j].x; v.tex_coords[0][1] = v.tex_coords[1][1] = tex_coords[j].y; s->addVertex(v); } t.verts[0] = k; t.verts[1] = k + 1; t.verts[2] = k + 2; s->addTriangle(t); t.verts[1] = k + 2; t.verts[2] = k + 3; s->addTriangle(t); } return m; } MeshModel* MeshUtil::createSphere(const Brush& b, int segs) { int h_segs = segs * 2, v_segs = segs; MeshModel* m = new MeshModel(); Surface* s = m->createSurface(b); Surface::Vertex v; Surface::Triangle t; v.coords = v.normal = Vector(0, 1, 0); int k; for (k = 0; k < h_segs; ++k) { v.tex_coords[0][0] = v.tex_coords[1][0] = (k + .5f) / h_segs; v.tex_coords[0][1] = v.tex_coords[1][1] = 0; s->addVertex(v); } for (k = 1; k < v_segs; ++k) { float pitch = k * PI / v_segs - HALFPI; for (int j = 0; j <= h_segs; ++j) { float yaw = (j % h_segs) * TWOPI / h_segs; v.coords = v.normal = rotationMatrix(pitch, yaw, 0).k; v.tex_coords[0][0] = v.tex_coords[1][0] = float(j) / float(h_segs); v.tex_coords[0][1] = v.tex_coords[1][1] = float(k) / float(v_segs); s->addVertex(v); } } v.coords = v.normal = Vector(0, -1, 0); for (k = 0; k < h_segs; ++k) { v.tex_coords[0][0] = v.tex_coords[1][0] = (k + .5f) / h_segs; v.tex_coords[0][1] = v.tex_coords[1][1] = 1; s->addVertex(v); } for (k = 0; k < h_segs; ++k) { t.verts[0] = k; t.verts[1] = t.verts[0] + h_segs + 1; t.verts[2] = t.verts[1] - 1; s->addTriangle(t); } for (k = 1; k < v_segs - 1; ++k) { for (int j = 0; j < h_segs; ++j) { t.verts[0] = k * (h_segs + 1) + j - 1; t.verts[1] = t.verts[0] + 1; t.verts[2] = t.verts[1] + h_segs + 1; s->addTriangle(t); t.verts[1] = t.verts[2]; t.verts[2] = t.verts[1] - 1; s->addTriangle(t); } } for (k = 0; k < h_segs; ++k) { t.verts[0] = (h_segs + 1) * (v_segs - 1) + k - 1; t.verts[1] = t.verts[0] + 1; t.verts[2] = t.verts[1] + h_segs; s->addTriangle(t); } return m; } MeshModel* MeshUtil::createCylinder(const Brush& b, int segs, bool solid) { MeshModel* m = new MeshModel(); Surface::Vertex v; Surface::Triangle t; Surface* s = m->createSurface(b); int k; for (k = 0; k <= segs; ++k) { float yaw = (k % segs) * TWOPI / segs; v.coords = rotationMatrix(0, yaw, 0).k; v.coords.y = 1; v.normal = Vector(v.coords.x, 0, v.coords.z); v.tex_coords[0][0] = v.tex_coords[1][0] = float(k) / segs; v.tex_coords[0][1] = v.tex_coords[1][1] = 0; s->addVertex(v); v.coords.y = -1; v.tex_coords[0][0] = v.tex_coords[1][0] = float(k) / segs; v.tex_coords[0][1] = v.tex_coords[1][1] = 1; s->addVertex(v); } for (k = 0; k < segs; ++k) { t.verts[0] = k * 2; t.verts[1] = t.verts[0] + 2; t.verts[2] = t.verts[1] + 1; s->addTriangle(t); t.verts[1] = t.verts[2]; t.verts[2] = t.verts[1] - 2; s->addTriangle(t); } if (!solid) return m; s = m->createSurface(b); for (k = 0; k < segs; ++k) { float yaw = k * TWOPI / segs; v.coords = rotationMatrix(0, yaw, 0).k; v.coords.y = 1; v.normal = Vector(0, 1, 0); v.tex_coords[0][0] = v.tex_coords[1][0] = v.coords.x * .5f + .5f; v.tex_coords[0][1] = v.tex_coords[1][1] = v.coords.z * .5f + .5f; s->addVertex(v); v.coords.y = -1; v.normal = Vector(0, -1, 0); s->addVertex(v); } for (k = 2; k < segs; ++k) { t.verts[0] = 0; t.verts[1] = k * 2; t.verts[2] = (k - 1) * 2; s->addTriangle(t); t.verts[0] = 1; t.verts[1] = (k - 1) * 2 + 1; t.verts[2] = k * 2 + 1; s->addTriangle(t); } return m; } MeshModel* MeshUtil::createCone(const Brush& b, int segs, bool solid) { MeshModel* m = new MeshModel(); Surface::Vertex v; Surface::Triangle t; Surface* s; s = m->createSurface(b); int k; v.coords = v.normal = Vector(0, 1, 0); for (k = 0; k < segs; ++k) { v.tex_coords[0][0] = v.tex_coords[1][0] = (k + .5f) / segs; v.tex_coords[0][1] = v.tex_coords[1][1] = 0; s->addVertex(v); } for (k = 0; k <= segs; ++k) { float yaw = (k % segs) * TWOPI / segs; v.coords = yawMatrix(yaw).k; v.coords.y = -1; v.normal = Vector(v.coords.x, 0, v.coords.z); v.tex_coords[0][0] = v.tex_coords[1][0] = float(k) / segs; v.tex_coords[0][1] = v.tex_coords[1][1] = 1; s->addVertex(v); } for (k = 0; k < segs; ++k) { t.verts[0] = k; t.verts[1] = k + segs + 1; t.verts[2] = k + segs; s->addTriangle(t); } if (!solid) return m; s = m->createSurface(b); for (k = 0; k < segs; ++k) { float yaw = k * TWOPI / segs; v.coords = yawMatrix(yaw).k; v.coords.y = -1; v.normal = Vector(v.coords.x, 0, v.coords.z); v.tex_coords[0][0] = v.tex_coords[1][0] = v.coords.x * .5f + .5f; v.tex_coords[0][1] = v.tex_coords[1][1] = v.coords.z * .5f + .5f; s->addVertex(v); } t.verts[0] = 0; for (k = 2; k < segs; ++k) { t.verts[1] = k - 1; t.verts[2] = k; s->addTriangle(t); } return m; } void MeshUtil::lightMesh(MeshModel* m, const Vector& pos, const Vector& rgb, float range) { if (range) { float att = 1.0f / range; const MeshModel::SurfaceList& surfs = m->getSurfaces(); for (int k = 0; k < surfs.size(); ++k) { Surface* s = surfs[k]; for (int j = 0; j < s->numVertices(); ++j) { const Surface::Vertex& v = s->getVertex(j); Vector lv = pos - v.coords; float dp = v.normal.normalized().dot(lv); if (dp <= 0) continue; float d = lv.length(); float i = 1 / (d * att) * (dp / d); s->setColor(j, s->getColor(j) + rgb * i); } } } else { const MeshModel::SurfaceList& surfs = m->getSurfaces(); for (int k = 0; k < surfs.size(); ++k) { Surface* s = surfs[k]; for (int j = 0; j < s->numVertices(); ++j) { const Surface::Vertex& v = s->getVertex(j); s->setColor(j, s->getColor(j) + rgb); } } } }