#ifndef SRC_TEXTUREMAPPER_H_ #define SRC_TEXTUREMAPPER_H_ #include #include class TextureMapper { public: typedef std::vector texture3_t; typedef std::vector 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_ */