Color Texture::fileColorAt(unsigned int x, unsigned int y) const { if (x >= width || y >= height) { throw RenderException("Invalid color location: (" + to_string(x) + ", " + to_string(y) + ")"); } unsigned int i = x * 3 + y * width * 3; return Color(image[i]/NORM, image[i+1]/NORM, image[i+2]/NORM); }
Template::Template(std::string templateName) { try { m_template = FileOpener::readAll("templates/" + templateName + ".html"); } catch (const std::exception& e) { throw RenderException(e.what()); } }
Texture* Texture::fromFile(const string& filename) { vector<unsigned char> image; unsigned int width; unsigned int height; unsigned int error = lodepng::decode(image, width, height, filename, LodePNGColorType::LCT_RGB, BITDEPTH); if (error) { throw RenderException("Error reading png file: \"" + filename + "\" - error code " + to_string(error)); } return new Texture(image, width, height); }
/** u,v ranges from [0,1], origin at bottom left of image. Uses bilinear interpolation * http://supercomputingblog.com/graphics/coding-bilinear-interpolation/ */ Color Texture::colorAt(double u, double v) const { if (u > (1.0 + EPSILON) || u < -EPSILON) { throw RenderException("invalid u = " + to_string(u)); } if (v > (1.0 + EPSILON) || v < -EPSILON) { throw RenderException("invalid v = " + to_string(v)); } // orient x,y to upper left of texture double x = bound(u) * (width-1); double y = bound(1.0-v) * (height-1); unsigned int x1 = x; unsigned int y1 = y; unsigned int x2 = ceil(x); unsigned int y2 = ceil(y); if (x1 == x2 && y1 == y2) { return fileColorAt(x, y); } Color c11 = fileColorAt(x1, y1); Color c12 = fileColorAt(x1, y2); Color c21 = fileColorAt(x2, y1); Color c22 = fileColorAt(x2, y2); if (y1 == y2) { double w1 = (x2 - x) / (x2 - x1); double w2 = (x - x1) / (x2 - x1); return (c11 * w1) + (c21 * w2); } else if (x1 == x2) { double w1 = (y2 - y) / (y2 - y1); double w2 = (y - y1) / (y2 - y1); return (c11 * w1) + (c12 * w2); } else { double w1 = (x2 - x) / (x2 - x1); double w2 = (x - x1) / (x2 - x1); Color c1 = (c11 * w1) + (c21 * w2); Color c2 = (c12 * w1) + (c22 * w2); return c1 * (y2 - y) / (y2 - y1) + c2 * (y - y1) / (y2 - y1); } }
StringList Shader::loadSource(const IO::Path& path) { std::fstream stream(path.asString().c_str(), std::ios::in); if (!stream.is_open()) throw RenderException("Cannot load shader source from " + path.asString()); String line; StringList lines; while (!stream.eof()) { std::getline(stream, line); lines.push_back(line + '\n'); } return lines; }
Shader::Shader(const IO::Path& path, const GLenum type) : m_name(path.lastComponent().asString()), m_type(type), m_shaderId(0) { assert(m_type == GL_VERTEX_SHADER || m_type == GL_FRAGMENT_SHADER); glAssert(m_shaderId = glCreateShader(m_type)); if (m_shaderId == 0) throw RenderException("Cannot create shader " + m_name); const StringList source = loadSource(path); const char** linePtrs = new const char*[source.size()]; for (size_t i = 0; i < source.size(); i++) linePtrs[i] = source[i].c_str(); glAssert(glShaderSource(m_shaderId, static_cast<GLsizei>(source.size()), linePtrs, NULL)); delete[] linePtrs; glAssert(glCompileShader(m_shaderId)); GLint compileStatus; glAssert(glGetShaderiv(m_shaderId, GL_COMPILE_STATUS, &compileStatus)); if (compileStatus == 0) { RenderException ex; ex << "Cannot compile shader " << m_name << ": "; GLint infoLogLength; glAssert(glGetShaderiv(m_shaderId, GL_INFO_LOG_LENGTH, &infoLogLength)); if (infoLogLength > 0) { char* infoLog = new char[infoLogLength]; glGetShaderInfoLog(m_shaderId, infoLogLength, &infoLogLength, infoLog); infoLog[infoLogLength-1] = 0; ex << infoLog; delete [] infoLog; } else { ex << "Unknown error"; } throw ex; } }
/* Determines the PA = LU decomposition of this matrix (A). * Writes into lu, where L is lu[i][j] for i > j * and U is lu[i][j] for i <= j * Writes into perm, representing the row-index permutations * from the decomposistion (analogous to the P permutation matrix) */ void Matrix4::decomposeLUP(double lu[4][4], int perm[4]) const { // copy this matrix into lu memcpy(lu, elem, sizeof(double)*16); // initial identity permutation for (int i = 0; i < 4; i++) { perm[i] = i; } // move down/in the row/columns of the matrix A to calc PA = LU for (int k = 0; k < 4; k++) { // find largest pivot and its index double pivot = 0.0; int k_prime = -1; for (int i = k; i < 4; i++) { double next = fabs(lu[i][k]); if (next > pivot) { pivot = next; k_prime = i; } } if (pivot < EPSILON || k_prime < 0) { throw RenderException("Unable to calculate inverse of singular matrix"); } // adjust perm bookkeeping and matrix for new pivot-row swap(perm[k], perm[k_prime]); for (int i = 0; i < 4; i++) { swap(lu[k][i], lu[k_prime][i]); } // with pivot-row in place, do LU decomposition for (int i = k+1; i < 4; i++) { // U[k][i] = lu[k][i], so just need to calculate L[i][k] lu[i][k] = lu[i][k] / lu[k][k]; } // and calculate Schur complement of submatrix for (int i = k+1; i < 4; i++) { for (int j = k+1; j < 4; j++) { lu[i][j] = lu[i][j] - lu[i][k] * lu[k][j]; } } } }