Files
BlitzNext/Runtime/blitz3d/meshutil.cpp
T
Michael Fabian 'Xaymar' Dirks 2196cb8419 runtime: Formatting
2019-01-18 17:04:17 +01:00

239 lines
6.6 KiB
C++

#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);
}
}
}
}