#include "TextureMapper.h" #include #include "stb_image_write.h" #include TextureMapper::TextureMapper(Density &density, size_t textureSize) : density(density), textureSize(textureSize), albedo( textureSize * textureSize), normal(textureSize * textureSize), roughness( textureSize * textureSize), darkestColor(0.3, 0.25, 0.2, 1.0), brightestColor( 0.9, 0.85, 0.8, 1.0) { } void TextureMapper::setTextureSize(size_t size) { textureSize = size; albedo.resize(textureSize * textureSize); normal.resize(textureSize * textureSize); roughness.resize(textureSize * textureSize); } size_t TextureMapper::getTextureSize() { return textureSize; } void TextureMapper::map(const vec3v_t &inVertices, const vec3v_t &inNormals, const uvec3v_t &inIndices) { float texf = 1. / textureSize; vertices.clear(); vertices.reserve(inIndices.size() * 3); normals.clear(); normals.reserve(inIndices.size() * 3); texcoords.clear(); texcoords.reserve(inIndices.size() * 3); // 2 px margin size_t marginPixels = 2; float margin = marginPixels * texf; std::fill(albedo.begin(), albedo.end(), 255.f * brightestColor); std::fill(normal.begin(), normal.end(), ucvec4_t(255, 255, 255, 255)); std::fill(roughness.begin(), roughness.end(), 255); int rects = ceil(sqrt(inIndices.size())), rx = 0, ry = 0; float rectSizePixel = floor(((float)textureSize - (rects + 1) * marginPixels) / rects); float rectSize = rectSizePixel / textureSize; printf("Rects: %d, Size: %f", rects, rectSize); for (size_t i = 0; i < inIndices.size(); i++) { glm::vec3 p[3], n[3]; glm::uvec3 idx = inIndices[i]; indices.push_back( glm::uvec3(vertices.size(), vertices.size() + 1, vertices.size() + 2)); for (size_t j = 0; j < 3; j++) { p[j] = inVertices[idx[j]]; vertices.push_back(p[j]); n[j] = inNormals[idx[j]]; normals.push_back(n[j]); } glm::vec3 ex = glm::normalize(p[1] - p[0]); glm::vec3 ey = glm::normalize(glm::cross(ex, p[2] - p[0])); glm::vec3 ez = glm::normalize(glm::cross(ex, ey)); glm::mat3 base = glm::mat3(ex, ey, ez); glm::vec3 t[3] = { p[0] * base, p[1] * base, p[2] * base }; glm::vec3 lower = min(min(t[0], t[1]), t[2]); glm::vec3 upper = max(max(t[0], t[1]), t[2]); t[0] -= lower; t[1] -= lower; t[2] -= lower; glm::vec3 extent = upper - lower; float s = std::max(std::max(extent.x, extent.y), extent.z); t[0] *= 0.9 * rectSize / s; t[1] *= rectSize / s; t[2] *= rectSize / s; glm::vec3 off(margin + rx * (rectSize + margin), 0, margin + ry * (rectSize + margin)); t[0] += off; t[1] += off; t[2] += off; texcoords.push_back(glm::vec2(t[0].x, t[0].z)); texcoords.push_back(glm::vec2(t[1].x, t[1].z)); texcoords.push_back(glm::vec2(t[2].x, t[2].z)); #if 0 //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 * textureSize); glm::vec3 eb = t[1] - t[0]; float leb = glm::length(eb); glm::vec3 ec = t[2] - t[0]; float lec = glm::length(ec); // mat2 textureBase = mat2(vec2(eb.x, eb.z), vec2(ec.x, ec.z)); // mat2 itextureBase = inverse(textureBase); glm::mat3 textureBase = glm::mat3(eb, glm::cross(eb, ec), ec); glm::mat3 itextureBase = glm::inverse(textureBase); // eb = normalize(eb); // ec = normalize(ec); glm::vec3 db = p[1] - p[0]; glm::vec3 dc = p[2] - p[0]; glm::vec3 mb = glm::normalize(p[1] - p[0]); glm::vec3 mc = glm::normalize(p[2] - p[0]); // mat2 faceBase = mat2(vec2(mb.x, mb.z), vec2(mc.x, mc.z)); // mat2 ifaceBase = inverse(faceBase); glm::mat3 faceBase = glm::mat3(db, glm::cross(db, dc), dc); glm::mat3 ifaceBase = glm::inverse(faceBase); glm::vec3 tmin = min(min(t[0], t[1]), t[2]); tmin = tmin * glm::vec3((float) textureSize); tmin = floor(tmin) - glm::vec3(2.0f); //tmin = tmin - glm::vec3(1.0f); tmin = max(tmin, glm::vec3(0.1)); // glm::vec3 tmax = min( // ceil( // max(max(t[0], t[1]), t[2]) // * glm::vec3((float) textureSize)) // + glm::vec3(1.0f), glm::vec3(textureSize - 1)); glm::vec3 tmax = max(max(t[0], t[1]), t[2]); tmax = tmax * glm::vec3((float) textureSize); tmax = ceil(tmax) + glm::vec3(2.0f); tmax = min(tmax, glm::vec3(textureSize)); // TODO: borders! for (int ix = tmin.x; ix < tmax.x; ix++) { for (int iy = (textureSize - tmax.z); iy < (textureSize - tmin.z); iy++) { // https://stackoverflow.com/questions/2049582/how-to-determine-if-a-point-is-in-a-2d-triangle#2049593 // for (int iy = tmin.z; iy < tmax.z; iy++) { // cout << "pix " << ix << " " << iy << endl; // cout << "uv " << float(ix) * texf << " " << 1.f - float(iy) * texf << endl; // pixel to uv space glm::vec3 res = glm::vec3(float(ix) * texf, 0.f, 1.f - float(iy) * texf) - t[0]; // cout << "r = " << r.x << " " << r.y << endl; glm::vec3 local = 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; glm::vec3 sp = p[0] + local; //res.x * mb + res.y * mc; float v = (float) density(sp, false); // //v = pow(v, 3); // default color // float r = 0.8 + v * 0.2, g = 0.75 + 0.2 * v, b = 0.7 // + 0.2 * v; glm::vec3 rgb = glm::vec3(255) * glm::mix(darkestColor, brightestColor, v); albedo[ix + (textureSize - iy) * textureSize][0] = rgb.x; albedo[ix + (textureSize - iy) * textureSize][1] = rgb.y; albedo[ix + (textureSize - iy) * textureSize][2] = rgb.z; // 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; // albedo[ix + (textureSize - iy) * textureSize][0] = rd * (sp.x) * 255; // albedo[ix + (textureSize - iy) * textureSize][1] = rd * (sp.y) * 255; // albedo[ix + (textureSize - iy) * textureSize][2] = rd * (sp.z) * 255; // albedo[ix + iy * textureSize][0] = length(res) * rects * 255; // albedo[ix + iy * textureSize][1] = length(res) * rects * 255; // albedo[ix + iy * textureSize][2] = length(res) * 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++; } #endif } // // 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_png("albedo.png", textureSize, textureSize, 3, albedo.data(), 0); }