int main() { double y_vals[] = {-1.5, 2, -2.5}; double z_vals[] = {3, -2, 1}; Vec<double> zeroes(3); // Vec size 3 (entries initialize to zero) Vec<double> x = Vec<double>::constantVec(3, 2.5); // Vec size 3 with all entries set to 2.5 Vec<double> y = Vec<double>(y_vals, 3); Vec<double> z(3); z.setEntries(z_vals, 3); Vec<int> ix(x); cout << "zeroes = " << zeroes << endl; cout << "x = " << x << endl; cout << "y = " << y << endl; cout << "z = " << z << endl; cout << "ix = " << ix << endl; cout << "z[0] = " << z[0] << ", z[1] = " << z[1] << ", z[2] = " << z[2] << endl; cout << "3.5 * x = " << (3.5 * x) << endl; cout << "x / 3.5 = " << (x / 3.5) << endl; cout << "x + y = " << (x + y) << endl; cout << "x - y = " << (x - y) << endl; cout << "x.concatenate(y) = " << x.concatenate(y) << endl; cout << "x.dot(y) = " << x.dot(y) << endl; cout << "x.cross(y) = " << x.cross(y) << endl; cout << "x.norm() = " << x.norm() << endl; cout << "x.unit_vector() = " << x.unit_vector() << endl; cout << "ix.norm() = " << ix.norm() << endl; cout << "ix.norm<double>() = " << ix.norm<double>() << endl; cout << "ix.unit_vector<double>() = " << ix.unit_vector<double>() << endl; cout << "scalar_triple_product(x, y, z) = " << Vec<double>::scalar_triple_product(x, y, z) << endl; cout << "vector_triple_product(x, y, z) = " << Vec<double>::vector_triple_product(x, y, z) << endl; }
static int trimesh(lua_State *ls) { if (!lua_istable(ls, -1)) { luaL_error(ls, "trimesh: expected table"); } std::vector<Vec> vertices; lua_getfield(ls, -1, "vertices"); lua_pushnil(ls); while (lua_next(ls, -2) != 0) { double x, y, z; get_xyz(ls, x, y, z); vertices.push_back(Vec{x, y, z}); lua_pop(ls, 1); } lua_pop(ls, 1); std::vector<TriangleMesh::Face> faces; lua_getfield(ls, -1, "faces"); lua_pushnil(ls); while (lua_next(ls, -2) != 0) { size_t i, j, k; lua_getfield(ls, -1, "i"); i = static_cast<size_t>(luaL_checknumber(ls, -1)); lua_pop(ls, 1); lua_getfield(ls, -1, "j"); j = static_cast<size_t>(luaL_checknumber(ls, -1)); lua_pop(ls, 1); lua_getfield(ls, -1, "k"); k = static_cast<size_t>(luaL_checknumber(ls, -1)); lua_pop(ls, 1); Vec ab = vertices[j] - vertices[i]; Vec ac = vertices[k] - vertices[i]; Vec norm = ab.cross(ac); norm.normalize(); faces.push_back(TriangleMesh::Face{i, j, k, norm}); lua_pop(ls, 1); } lua_pop(ls, 1); lua_getfield(ls, -1, "material"); Material *mat = reinterpret_cast<Material *>(lua_touserdata(ls, -1)); lua_pop(ls, 1); TriangleMesh *tm = new TriangleMesh; tm->faces = std::move(faces); tm->vertices = std::move(vertices); tm->material.reset(mat); lua_pushlightuserdata(ls, tm); return 1; }
int main(int argc, char *argv[]) { int nworkers = omp_get_num_procs(); omp_set_num_threads(nworkers); rng.init(nworkers); int w = 480, h = 360, samps = argc==2 ? atoi(argv[1])/4 : 1; // # samples Vec cx = Vec(w*.5135/h), cy = (cx.cross(cam.d)).normalize()*.5135; std::vector<Vec> c(w*h); #pragma omp parallel for schedule(dynamic, 1) for ( int y = 0; y < h; y++ ) { for ( int x = 0; x < w; x++ ) { const int i = (h - y - 1)*w + x; for ( int sy = 0; sy < 2; ++sy ) { for ( int sx = 0; sx < 2; ++sx ) { Vec r; for ( int s = 0; s<samps; s++ ) { double r1 = 2*rng(), dx = r1<1 ? sqrt(r1)-1 : 1-sqrt(2-r1); double r2 = 2*rng(), dy = r2<1 ? sqrt(r2)-1 : 1-sqrt(2-r2); Vec d = cx*(((sx+.5 + dx)/2 + x)/w - .5) + cy*(((sy+.5 + dy)/2 + y)/h - .5) + cam.d; r = r + receivedRadiance(Ray(cam.o, d.normalize()), 1, true)*(1./samps); } c[i] = c[i] + Vec(clamp(r.x), clamp(r.y), clamp(r.z))*.25; } } } #pragma omp critical fprintf(stderr,"\rRendering (%d spp) %6.2f%%",samps*4,100.*y/(h-1)); } fprintf(stderr, "\n"); // Write resulting image to a PPM file FILE *f = fopen("image.ppm", "w"); fprintf(f, "P3\n%d %d\n%d\n", w, h, 255); for ( int i = 0; i<w*h; i++ ) fprintf(f, "%d %d %d ", toInt(c[i].x), toInt(c[i].y), toInt(c[i].z)); fclose(f); return 0; }
/** Texture mapping for spheres ** @param pt intersection point ** @param n normal at pt ** @param p pigment of the object ** @return the color of pt at texture coordinate **/ Vec sphereMapping(Vec pt, Vec n, Pigment p){ Vec vn = scene.up; // unit-length vector from the center to the north pole Vec tmp[3] = {Vec(1.0, 0.0, 0.0), Vec(0.0, 1.0, 0.0), Vec(0.0, 0.0, 1.0)}; Vec ve; // unit-length vector from the center to a point on the equator for (int i = 0; i<3; i++) { if (tmp[i].dot(vn) == 0) { ve = tmp[i]; break; } } Vec vp = n; // unit-length vector from the center to intersection point int s, t; float u, v, theta, phi; phi = acos(vn.dot(vp) * -1); v = phi / PI; theta = (acos(vp.dot(ve) / sin(phi))) / (2*PI); if ((vn.cross(ve)).dot(vp) > 0) u = theta; else u = 1 - theta; // find the color of pt at texture cooridnates s = (int)p.image.width * u; t = (int)p.image.height * v; if ((s < p.image.width && s >= 0) && (t < p.image.height && t >= 0)) return p.image.textures[s][t]; else return background; }
template<class Vec> void testCross() { Vec vec; for (unsigned int i = 0; i < vec.getDimension(); i++) vec[i] = numbers[i]; Vec vec2; for (unsigned int i = vec.getDimension(); i < vec2.getDimension(); i++) vec2[i] = numbers[i]; auto temp = vec.cross(vec2); ASSERT_EQ(temp.getDimension(), vec.getDimension()); for (unsigned int i = 0; i < temp.getDimension(); i++) { unsigned int i1 = i + 1; unsigned int i2 = i + 2; if (i2 >= temp.getDimension()) i2 -= temp.getDimension(); if (i1 >= temp.getDimension()) i1 -= temp.getDimension(); ASSERT(dbgl::isSimilar(temp[i], vec[i1] * vec2[i2] - vec[i2] * vec2[i1])); } }
int main(int argc, char *argv[]) { clock_t start = clock(); // MILO int width = 256, height = 256; std::string sceneName = "cornell"; std::string rendererName = "simple"; int nSamples = 25; // # samples option long_options[] = { {"help", no_argument, 0, 'h'}, {"viewport",required_argument, 0, 'v'}, {"input", required_argument, 0, 'i'}, {"samples", required_argument, 0, 's'}, {"renderer",required_argument, 0, 'r'}, {0, 0, 0, 0} }; int opt; int option_index = 0; while ((opt = getopt_long (argc, argv, "hv:i:s:r:", long_options, &option_index)) != -1) { switch (opt) { case 'h': { fprintf(stdout, "smallpt --renderer simple --viewport 256 --input cornell --samples 100\n\n"); IScene::printBuiltInSceneNames(); exit(0); } case 'v':{width = height = atoi(optarg); break;} case 'i':{sceneName = optarg; break;} case 's':{nSamples = atoi(optarg)/4; break;} case 'r':{rendererName = optarg; break;} default: exit(0); } } if (optind < argc) { printf ("non-option ARGV-elements: "); while (optind < argc) printf ("%s ", argv[optind++]); printf ("\n"); exit(0); } IRenderer* renderer = NULL; { if (rendererName == "forward") renderer = new ForwardRenderer(); else if (rendererName == "diffuse") renderer = new DiffuseOnlyRenderer(); else renderer = new SimpleRenderer(); } Ray cam(Vec(50,52,295.6), Vec(0,-0.042612,-1).norm()); // cam pos, dir Vec cx = Vec(width*.5135/height); Vec cy=(cx.cross(cam.dir)).norm()*.5135; Vec* colorBuf = new Vec[width*height]; Vec r; IScene* scene = new SimpleScene(); if (!IScene::createBuiltInScene(scene, sceneName)) { fprintf(stderr, "Invalid scene name: %s\n", sceneName.c_str()); IScene::printBuiltInSceneNames(); exit(1); } char imageName[100]; sprintf(imageName, "%s_%s_%dX%dX%d.ppm", sceneName.c_str(), rendererName.c_str(), width, height, nSamples*4); fprintf(stdout, "Rendering to %s\n", imageName); #pragma omp parallel for schedule(dynamic, 1) private(r) // OpenMP for (int y = 0; y < height; y++) { // Loop over image rows fprintf(stderr,"\rRendering (%d spp) %5.2f%%",nSamples*4,100.*y/(height - 1)); RandomLCG Xi(y*y*y); // MILO for (unsigned short x = 0; x < width; x++) { // Loop cols int loc = (height - y - 1) * width + x; for (int sy = 0; sy < 2; sy++) { // 2x2 subpixel rows for (int sx = 0; sx < 2; sx++, r = Vec()) { // 2x2 subpixel cols for (int s = 0; s < nSamples; s++) { double dx = tentFilterRandom(Xi); double dy = tentFilterRandom(Xi); #if 1 Vec d = cx*( ( (sx+.5 + dx)/2 + x)/width - .5) + cy*( ( (sy+.5 + dy)/2 + y)/height - .5) + cam.dir; #else Vec d = cx*(x/(double)width - .5 ) + cy*(y/(double)height - .5) + cam.dir; #endif r = r + renderer->radiance(*scene, Ray(cam.orig+d*140,d.norm()),0,Xi)*(1./nSamples); } // Camera rays are pushed ^^^^^ forward to start in interior colorBuf[loc] = colorBuf[loc] + Vec(clamp(r.x),clamp(r.y),clamp(r.z))*.25; } } } } delete renderer; delete scene; printf("\n%f sec\n", (float)(clock() - start)/CLOCKS_PER_SEC); // MILO { FILE *f = fopen(imageName, "w"); // Write image to PPM file. fprintf(f, "P3\n%d %d\n%d\n", width, height, 255); for (int i = 0; i < width*height; i++) fprintf(f,"%d %d %d ", toInt(colorBuf[i].x), toInt(colorBuf[i].y), toInt(colorBuf[i].z)); fclose(f); } }
void ONB:: initFromVW(const Vec& v, const Vec& w){ W = normalize(w); U = normalize(v.cross(W)); V = W.cross(U); }
void ONB:: initFromUW(const Vec& u, const Vec& w){ U = normalize(u); V = normalize(w.cross(U)); W = U.cross(V); }
inline void createLocalCoord(const Vec &n, Vec &u, Vec &v, Vec &w) { w = n; u = ((std::abs(w.x)>.1 ? Vec(0, 1) : Vec(1)).cross(w)).normalize(); v = w.cross(u); }