bool inFace(int faceId, dvec3 v) { dvec3 o1 = v; dvec3 r1 = dvec3(1, 0, 0); bool pos = false, neg = false; for (int edge : faces[faceId].edgeIDs) { dvec3 o2 = creases[edge].p0; dvec3 r2 = creases[edge].p1 - creases[edge].p0; double det = 1 / (-r1.x * r2.y + r2.x * r1.y); double b11 = o2.x - o1.x; double b21 = o2.y - o1.y; double t1 = det * (-r2.y * b11 + r2.x * b21); double t2 = det * (-r1.y * b11 + r1.x * b21); if (t2 < 0 || 1 < t2) continue; if (t1 == 0) pos = neg = true; if (t1 < 0) neg = true; if (0 < t1) pos = true; } return (pos && neg); }
void RayTracer::drawScene(unsigned int samples, unsigned int bounces){ dvec3 eyePos = scene.getEyePos(); int c = 0; double gc = 1/2.2; #pragma omp parallel for schedule(dynamic, 1) for(size_t i = 0; i < viewY; i++){ for(size_t j = 0; j < viewX; j++){ dvec3 outColor; double x = (j + 0.5) / (viewX / 2.0) - 1.0; double y = -(i + 0.5) / (viewY / (2.0 * viewY/viewX)) + 1.0*viewY/viewX; dvec3 screenPos = dvec3(x,y,0); dvec3 eyeRay = glm::normalize(screenPos - eyePos); for(size_t k = 0; k < samples; k++){ outColor += scene.processRay(eyeRay, screenPos, -1, bounces) * (1.0/samples); } outColor = glm::clamp(outColor, 0.0, 1.0); int pc = (i*viewX + j)*bytesPerPixel; screenBuffer[pc + 0] = glm::pow(outColor[0],gc)*255; screenBuffer[pc + 1] = glm::pow(outColor[1],gc)*255; screenBuffer[pc + 2] = glm::pow(outColor[2],gc)*255; } #pragma omp atomic c++; std::cout << i*100.0/viewY << "%" << '\r'; std::cout.flush(); } return; }
void draw(float t) { glViewport(0, 0, windowW, windowH); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); //glRotatef(-90, 0, 0, 1); glTranslated(0, -0.2, -1.5); glColor4d(1, 1, 1, 1.0 / 3); glBegin(GL_POINTS); { double delta = 0.02; for (double x = -1; x <= 1; x += delta) { for (double y = -1; y <= 1; y += delta) { dvec3 v = fold(dvec3(x, y, 0)); dvec3 diff = v - dvec3(x, y, 0); glVertex3d(v.x, v.y, 0); } } } glEnd(); glBegin(GL_LINES); { for (int i = 0; i < creases.size(); ++i) { foldSegment& fs = creases[i]; if (i == errored) glColor3f(1, 1, 1); else if (fs.type == MOUNTAIN) glColor3d(0.3, 0.3, 1); else if (fs.type == VALLEY) glColor3d(1, 0.3, 0.3); else glColor3d(0.3, 0.8, 0.3); glVertex3d(fs.p0.x, fs.p0.y, 0); glVertex3d(fs.p1.x, fs.p1.y, 0); } } glEnd(); }
vector<double> anglesAroundVertex(dvec3 pt) { vector<double> ret; for (foldSegment& seg : creases) { dvec3 ptToAdd = dvec3(-2, -2, 0); if (closeEnough(seg.p0, pt)) ptToAdd = seg.p1 - seg.p0; else if (closeEnough(seg.p1, pt)) ptToAdd = seg.p0 - seg.p1; if (ptToAdd.x < -1) continue; double angleToAdd = atan2(ptToAdd.y, ptToAdd.x); if (angleToAdd < 0) angleToAdd += 2 * PI; ret.push_back(angleToAdd); } std::sort(ret.begin(), ret.begin() + ret.size()); return ret; }
void setup() { glMatrixMode(GL_PROJECTION); float n = 0.1f; float hx = tan(PI / 4) * n; glFrustum(-hx, hx, -hx, hx, n, 10); glMatrixMode(GL_MODELVIEW); // the edges of paper { foldSegment c; c.p0 = dvec3(-1, 1, 0); c.p1 = dvec3(1, 1, 0); c.type = EDGE; creases.push_back(c); } { foldSegment c; c.p0 = dvec3(1, -1, 0); c.p1 = dvec3(-1, -1, 0); c.type = EDGE; creases.push_back(c); } { foldSegment c; c.p0 = dvec3(1, 1, 0); c.p1 = dvec3(1, -1, 0); c.type = EDGE; creases.push_back(c); } { foldSegment c; c.p0 = dvec3(-1, -1, 0); c.p1 = dvec3(-1, 1, 0); c.type = EDGE; creases.push_back(c); } // diaganols { foldSegment c; c.p0 = dvec3(1, 1, 0); c.p1 = dvec3(0, 0, 0); c.type = VALLEY; creases.push_back(c); } { foldSegment c; c.p0 = dvec3(-1, -1, 0); c.p1 = dvec3(0, 0, 0); c.type = VALLEY; creases.push_back(c); } // pieces coming out of center { foldSegment c; c.p0 = dvec3(0, 0, 0); c.p1 = dvec3(0, -1 + tan(PI / 8), 0); c.type = MOUNTAIN; creases.push_back(c); } { foldSegment c; c.p0 = dvec3(0, 0, 0); c.p1 = dvec3(1 - tan(PI / 8), 0, 0); c.type = MOUNTAIN; creases.push_back(c); } { foldSegment c; c.p0 = dvec3(0, 0, 0); c.p1 = dvec3(0, 1 - tan(PI / 8), 0); c.type = MOUNTAIN; creases.push_back(c); } { foldSegment c; c.p0 = dvec3(0, 0, 0); c.p1 = dvec3(-1 + tan(PI / 8), 0, 0); c.type = MOUNTAIN; creases.push_back(c); } // connecting to left and right wings { foldSegment c; c.p0 = dvec3(-1, -1, 0); c.p1 = dvec3(0, -1 + tan(PI / 8), 0); c.type = MOUNTAIN; creases.push_back(c); } { foldSegment c; c.p0 = dvec3(1, 1, 0); c.p1 = dvec3(1 - tan(PI / 8), 0, 0); c.type = MOUNTAIN; creases.push_back(c); } { foldSegment c; c.p0 = dvec3(1, 1, 0); c.p1 = dvec3(0, 1 - tan(PI / 8), 0); c.type = MOUNTAIN; creases.push_back(c); } { foldSegment c; c.p0 = dvec3(-1, -1, 0); c.p1 = dvec3(-1 + tan(PI / 8), 0, 0); c.type = MOUNTAIN; creases.push_back(c); } // the other edge connection { foldSegment c; c.p0 = dvec3(1, -1, 0); c.p1 = dvec3(0, -1 + tan(PI / 8), 0); c.type = MOUNTAIN; creases.push_back(c); } { foldSegment c; c.p0 = dvec3(1, -1, 0); c.p1 = dvec3(1 - tan(PI / 8), 0, 0); c.type = MOUNTAIN; creases.push_back(c); } { foldSegment c; c.p0 = dvec3(-1, 1, 0); c.p1 = dvec3(0, 1 - tan(PI / 8), 0); c.type = MOUNTAIN; creases.push_back(c); } { foldSegment c; c.p0 = dvec3(-1, 1, 0); c.p1 = dvec3(-1 + tan(PI / 8), 0, 0); c.type = MOUNTAIN; creases.push_back(c); } // center line { foldSegment c; c.p0 = dvec3(0, -1 + tan(PI / 8), 0); c.p1 = dvec3(1 - tan(PI / 8), 0, 0); c.type = VALLEY; creases.push_back(c); } { foldSegment c; c.p0 = dvec3(-1 + tan(PI / 8), 0, 0); c.p1 = dvec3(0, 1 - tan(PI / 8), 0); c.type = VALLEY; creases.push_back(c); } creaseWithFirstChoice(dvec3(1, 1, 0), 3 * PI / 2 - PI / 16, VALLEY); creaseWithFirstChoice(dvec3(1, 1, 0), PI + PI / 16, VALLEY); creaseWithFirstChoice(dvec3(1, 0.6, 0), PI / 2 + PI / 4 + PI / 16, VALLEY); creaseWithFirstChoice(dvec3(1, 0, 0), PI / 2 + PI / 4 + PI / 16, VALLEY); creaseWithFirstChoice(dvec3(-1, -1, 0), 3 * PI / 16, MOUNTAIN); creaseWithFirstChoice(dvec3(-1, -1, 0), PI / 2 - PI / 16, VALLEY); creaseWithFirstChoice(dvec3(0, -1, 0), PI / 2 + PI / 4 - PI / 16, VALLEY); errored = buildFaces(); buildFaceTree(); for (face& f : faces) { f.color = dvec3(nrand(), nrand(), nrand()); } printf("# fold segments: %d", creases.size()); }
void creaseWithFirstChoice(dvec3 pt, double angle, foldSegmentType t) { dvec3 o = pt; dvec3 dir = dvec3(cos(angle), sin(angle), 0); dvec3 ptOther = dir * raycast(o, dir) + o; insertAndSegment(o, ptOther, t); bool foundSomethingToFix = true; //for (int q = 0; q < 3; ++q) while (1) { foundSomethingToFix = false; vector<dvec3> verts = getInternalVerts(); for (dvec3 v : verts) { int n = numEdgesAroundVertex(v); if (n % 2 == 0) continue; foundSomethingToFix = true; // insert a crease in the first available correct configuration clockwise vector<double> angles = anglesAroundVertex(v); double total = 0; for (int i = 0; i < angles.size(); ++i) { total = 0; for (int j = i; j < i + angles.size(); ++j) { total = angles[j % angles.size()] - total; } total -= PI; if (total < 0) total += 2 * PI; double targetWidth = angles[(i - 1 + angles.size()) % angles.size()] - angles[i]; if (targetWidth > 0) targetWidth -= 2 * PI; printf("testing %f in between %f and %f: ", total, angles[i] + targetWidth, angles[i]); if (angles[i] + targetWidth + epsilon < total && total < angles[i] - epsilon) { printf("accept\n"); break; } if (angles[(i - 1 + angles.size()) % angles.size()] + epsilon < total && total < angles[(i - 1 + angles.size()) % angles.size()] - targetWidth - epsilon) { printf("accept\n"); break; } printf("reject\n"); } printf("%f, %f: %f \n", v.x, v.y, total); o = v; dir = dvec3(cos(total), sin(total), 0); ptOther = dir * raycast(o, dir) + o; // ballance out mountain/valley folds foldSegmentType typeToUse = VALLEY; int diff = diffBetweenMountainValley(v); if (diff - 1 == -2) typeToUse = VALLEY; else if (diff + 1 == 2) typeToUse = MOUNTAIN; insertAndSegment(o, ptOther, typeToUse); break; } if (!foundSomethingToFix) break; } }
int buildFaces() { // set the face counters approapriately for (foldSegment& f : creases) { f.faceRight = false; if (f.type == EDGE) f.faceLeft = true; else f.faceLeft = false; } // find any fold segment that doesn't have both faces accounted for, then // trace it around crease by crease until it loops back //for (int i = 0; i < 20; ++i) while (1) { int curEdge = 0; dvec3 startPt = dvec3(); dvec3 prevPt = dvec3(); dvec3 curPt = dvec3(); dvec3 nextPt = dvec3(); dvec3 refPt = dvec3(); face newFace; // find the first fold segment bool found = false; for (int i = 0; i < creases.size(); ++i) { curEdge = i; startPt = prevPt = creases[i].p0; curPt = creases[i].p1; if (creases[i].faceRight == false) { dvec3 dir = curPt - prevPt; dvec3 ndir = normalize(dir); refPt = prevPt + dir / 2.0 + dvec3(ndir.y, -ndir.x, 0) / 10.0; found = true; creases[i].faceRight = true; break; } if (creases[i].faceLeft == false) { dvec3 dir = curPt - prevPt; dvec3 ndir = normalize(dir); refPt = prevPt + dir / 2.0 - dvec3(ndir.y, -ndir.x, 0) / 10.0; found = true; creases[i].faceLeft = true; break; } } if (!found) break; //printf("%d: %d %d\n", curEdge, creases[curEdge].faceLeft, creases[curEdge].faceRight); newFace.edgeIDs.push_back(curEdge); // now start looping while (!closeEnough(curPt, startPt)) { // find next curEdge int nextEdge = 0; float bestCosine = -1; bool left = false; for (int i = 0; i < creases.size(); ++i) { if (i == curEdge) continue; dvec3 p0, p1; bool trigger = false; if (closeEnough(curPt, creases[i].p0)) { p0 = creases[i].p0; p1 = creases[i].p1; } else if (closeEnough(curPt, creases[i].p1)) { p0 = creases[i].p1; p1 = creases[i].p0; trigger = true; } else continue; { dvec3 r1 = prevPt - curPt; dvec3 r2 = p1 - curPt; dvec3 r2_reference = refPt - curPt; double cross1 = cross(r1, r2).z; double crossRef = cross(r1, r2_reference).z; if (((cross1 > 0) != (crossRef > 0)) && (cross1 != 0) && (crossRef != 0)) continue; double testCosine = dot(normalize(r1), normalize(r2)); if (testCosine >= bestCosine) { nextPt = p1; nextEdge = i; bestCosine = testCosine; if (crossRef < 0) left = true; else left = false; if (trigger) left = !left; } } } newFace.edgeIDs.push_back(nextEdge); if (left) { if (creases[nextEdge].faceLeft == true) { printf("something is wrong with edge: %d\n", nextEdge); return nextEdge; } creases[nextEdge].faceLeft = true; } else { if (creases[nextEdge].faceRight == true) { printf("something is wrong with edge: %d\n", nextEdge); return nextEdge; } creases[nextEdge].faceRight = true; } printf("%d: %d %d\n", nextEdge, creases[nextEdge].faceLeft, creases[nextEdge].faceRight); curEdge = nextEdge; prevPt = curPt; curPt = nextPt; } faces.push_back(newFace); printf("\n"); } return -1; }