asteroidgen/src/TextureMapper.h

202 lines
6.3 KiB
C++

#ifndef SRC_TEXTUREMAPPER_H_
#define SRC_TEXTUREMAPPER_H_
#include <vector>
#include <glm/vec3.hpp>
class TextureMapper {
public:
typedef std::vector<glm::uint8[3]> texture3_t;
typedef std::vector<uint8_t> texture1_t;
texture3_t diffuse;
texture3_t normal;
texture1_t roughness;
size_t textureSize;
TextureMapper(size_t textureSize) :
textureSize(textureSize), diffuse(textureSize * textureSize), normal(
textureSize * textureSize), roughness(
textureSize * textureSize) {
}
void map() {
cout << "Stage4: UV map" << endl;
TriMesh mappedMesh;
float texf = 1. / texture_size;
mesh.request_vertex_normals();
mesh.request_face_normals();
mesh.update_face_normals();
mesh.update_vertex_normals();
int rects = ceil(sqrt(mesh.n_faces())), rx = 0, ry = 0;
float rectSize = floor(float(texture_size) / rects) / texture_size;
size_t nfaces = mesh.n_faces(), iface = 0;
for (auto i = mesh.faces_begin(); i != mesh.faces_end(); i++) {
if (show_progress)
(cout << "\r " << int(100. * float(iface++) / nfaces) << "%").flush();
vec3 p[3], n[3];
int k = 0;
TriMesh::VertexHandle h[3];
for (auto j = mesh.fv_begin(*i); j != mesh.fv_end(*i); j++) {
if (!j->is_valid())
cout << "invalid vertex" << endl;
TriMesh::Point pt = mesh.point(*j);
p[k] = vec3(pt[0], pt[1], pt[2]);
TriMesh::Normal nm = mesh.calc_vertex_normal(*j);
n[k] = vec3(nm[0], nm[1], nm[2]);
h[k] = mappedMesh.add_vertex(pt);
mappedMesh.set_normal(h[k], nm);
k++;
if (k > 3)
cout << "not a triangle!" << endl;
}
mappedMesh.add_face(h, 3);
vec3 ex = normalize(p[1] - p[0]);
vec3 ey = normalize(cross(ex, p[2] - p[0]));
vec3 ez = normalize(cross(ex, ey));
mat3 base = mat3(ex, ey, ez);
vec3 t[3] = { p[0] * base, p[1] * base, p[2] * base };
vec3 lower = min(min(t[0], t[1]), t[2]);
vec3 upper = max(max(t[0], t[1]), t[2]);
t[0] -= lower;
t[1] -= lower;
t[2] -= lower;
vec3 extent = upper - lower;
float s = std::max(std::max(extent.x, extent.y), extent.z);
t[0] *= 0.8 * rectSize / s;
t[1] *= 0.8 * rectSize / s;
t[2] *= 0.8 * rectSize / s;
vec3 off(rx * rectSize, 0, ry * rectSize);
t[0] += off;
t[1] += off;
t[2] += off;
mappedMesh.set_texcoord2D(h[0],
TriMesh::TexCoord2D(t[0].x, t[0].z));
mappedMesh.set_texcoord2D(h[1],
TriMesh::TexCoord2D(t[1].x, t[1].z));
mappedMesh.set_texcoord2D(h[2],
TriMesh::TexCoord2D(t[2].x, t[2].z));
//if (rx == 0 && ry == 0) {
t[0].y = 0;
t[1].y = 0;
t[2].y = 0;
// cout << "ftex " << texf << endl;
// cout << "t[0] " << t[0].x << " " << t[0].z << endl;
// cout << "t[1] " << t[1].x << " " << t[1].z << endl;
// cout << "t[2] " << t[2].x << " " << t[2].z << endl;
// cout << "t[0]p " << t[0].x * ntex << " " << (1 - t[0].z) * ntex << endl;
// cout << "t[1]p " << t[1].x * ntex << " " << (1 - t[1].z) * ntex << endl;
// cout << "t[2]p " << t[2].x * ntex << " " << (1 - t[2].z) * ntex << endl;
// fill texture
// fill whole rect for now
int rpix = floor(rectSize * texture_size);
vec3 eb = t[1] - t[0];
float leb = length(eb);
vec3 ec = t[2] - t[0];
float lec = length(ec);
// mat2 textureBase = mat2(vec2(eb.x, eb.z), vec2(ec.x, ec.z));
// mat2 itextureBase = inverse(textureBase);
mat3 textureBase = mat3(eb, cross(eb, ec), ec);
mat3 itextureBase = inverse(textureBase);
// eb = normalize(eb);
// ec = normalize(ec);
vec3 db = p[1] - p[0];
vec3 dc = p[2] - p[0];
vec3 mb = normalize(p[1] - p[0]);
vec3 mc = normalize(p[2] - p[0]);
// mat2 faceBase = mat2(vec2(mb.x, mb.z), vec2(mc.x, mc.z));
// mat2 ifaceBase = inverse(faceBase);
mat3 faceBase = mat3(db, cross(db, dc), dc);
mat3 ifaceBase = inverse(faceBase);
// mat2 trafo = ifaceBase * textureBase * faceBase;
for (int ix = rx * rpix; ix < (rx + 1) * rpix; ix++) {
for (int iy = (texture_size - (ry + 1) * rpix);
iy < (texture_size - ry * rpix); iy++) {
// cout << "pix " << ix << " " << iy << endl;
// cout << "uv " << float(ix) * texf << " " << 1.f - float(iy) * texf << endl;
// pixel to uv space
vec3 res = vec3(float(ix) * texf, 0.f,
1.f - float(iy) * texf) - t[0];
// cout << "r = " << r.x << " " << r.y << endl;
res = faceBase * itextureBase * res;
// cout << "res = " << res.x << " " << res.y << endl;
// vec2 res = ifaceBase * textureBase * r * faceBase;
//
// cout << "pix " << ix << " " << res.x << " " << res.y << " " << res.z << endl;
// float fb = dot(r, eb) / leb;
// float fc = dot(r, ec) / lec;
vec3 sp = p[0] + res; //res.x * mb + res.y * mc;
float v = (float) noise.octaveNoise0_1(sp.x * frequency * 4,
sp.y * frequency * 4, sp.z * frequency * 4, 8);
//
v = pow(v, 3);
// default color
float r = 0.12 + v * 0.72, g = 0.1 + 0.7 * v, b = 0.1
+ 0.7 * v;
diff[ix + iy * texture_size][0] = r * 255;
diff[ix + iy * texture_size][1] = g * 255;
diff[ix + iy * texture_size][2] = b * 255;
// diff[ix + iy * ntex] = v * 255;
// diff[ix + iy * ntex][0] = (32 * rx) % 255;
// diff[ix + iy * ntex][1] = (32 * ry) % 255;
// diff[ix + iy * ntex][2] = 0; //(0.5 + sp.z) * 255;
// float rd = 1.f; //0.7 + 0.3 * length(r) * rects;
// diff[ix + iy * ntex][0] = rd * (0.5 + sp.x) * 255;
// diff[ix + iy * ntex][1] = rd * (0.5 + sp.y) * 255;
// diff[ix + iy * ntex][2] = rd * (0.5 + sp.z) * 255;
// diff[ix + iy * ntex][0] = length(r) * rects * 255;
// diff[ix + iy * ntex][1] = length(r) * rects * 255;
// diff[ix + iy * ntex][2] = length(r) * rects * 255;
// diff[ix + iy * ntex][0] = r.x * rects * 200;
// diff[ix + iy * ntex][1] = -r.z * rects * 200;
// diff[ix + iy * ntex][2] = 0;
// diff[ix + iy * ntex][0] = 128 + (res.x - 0.5) * 200;
// diff[ix + iy * ntex][1] = 128 + (res.y - 0.5) * 200;
// diff[ix + iy * ntex][2] = 0; //res.z * 255;
}
//}
}
rx++;
if (rx >= rects) {
rx = 0;
ry++;
}
}
//
// for (int ix = 0; ix < ntex; ix++) {
// for (int iy = 0; iy < ntex; iy++) {
//
// float v = (float) noise.octaveNoise0_1(ix * texf * frequency,
// iy * texf * frequency, 0.5 * frequency, 4);
// diff[ix + (ntex - iy) * ntex] = 5 + v * 250;
// }
// }
stbi_write_bmp("diffuse.bmp", texture_size, texture_size, 3,
diff.data());
}
};
#endif /* SRC_TEXTUREMAPPER_H_ */