void PlanetographicGrid::render(Renderer* renderer, const Point3f& pos, float discSizeInPixels, double tdb) const { Quatd q = Quatd::yrotation(PI) * body.getEclipticToBodyFixed(tdb); Quatf qf((float) q.w, (float) q.x, (float) q.y, (float) q.z); // The grid can't be rendered exactly on the planet sphere, or // there will be z-fighting problems. Render it at a height above the // planet that will place it about one pixel away from the planet. float scale = (discSizeInPixels + 1) / discSizeInPixels; scale = max(scale, 1.001f); float offset = scale - 1.0f; Vec3f semiAxes = body.getSemiAxes(); Vec3d posd(pos.x, pos.y, pos.z); Vec3d viewRayOrigin = Vec3d(-pos.x, -pos.y, -pos.z) * (~q).toMatrix3(); // Calculate the view normal; this is used for placement of the long/lat // label text. Vec3f vn = Vec3f(0.0f, 0.0f, -1.0f) * renderer->getCameraOrientation().toMatrix3(); Vec3d viewNormal(vn.x, vn.y, vn.z); // Enable depth buffering glEnable(GL_DEPTH_TEST); glDepthMask(GL_TRUE); glDisable(GL_BLEND); glDisable(GL_TEXTURE_2D); glPushMatrix(); glRotate(~qf); glScale(scale * semiAxes); glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_FLOAT, 0, xzCircle); // Only show the coordinate labels if the body is sufficiently large on screen bool showCoordinateLabels = false; if (discSizeInPixels > 50) showCoordinateLabels = true; float latitudeStep = minLatitudeStep; float longitudeStep = minLongitudeStep; if (discSizeInPixels < 200) { latitudeStep = 30.0f; longitudeStep = 30.0f; } for (float latitude = -90.0f + latitudeStep; latitude < 90.0f; latitude += latitudeStep) { float phi = degToRad(latitude); float r = (float) cos(phi); if (latitude == 0.0f) { glColor(Renderer::PlanetEquatorColor); glLineWidth(2.0f); } else { glColor(Renderer::PlanetographicGridColor); } glPushMatrix(); glTranslatef(0.0f, (float) sin(phi), 0.0f); glScalef(r, r, r); glDrawArrays(GL_LINE_LOOP, 0, circleSubdivisions); glPopMatrix(); glLineWidth(1.0f); if (showCoordinateLabels) { if (latitude != 0.0f && abs(latitude) < 90.0f) { char buf[64]; char ns; if (latitude < 0.0f) ns = northDirection == NorthNormal ? 'S' : 'N'; else ns = northDirection == NorthNormal ? 'N' : 'S'; sprintf(buf, "%d%c", (int) fabs((double) latitude), ns); longLatLabel(buf, 0.0, latitude, viewRayOrigin, viewNormal, posd, q, semiAxes, offset, renderer); longLatLabel(buf, 180.0, latitude, viewRayOrigin, viewNormal, posd, q, semiAxes, offset, renderer); } } } glVertexPointer(3, GL_FLOAT, 0, xyCircle); for (float longitude = 0.0f; longitude <= 180.0f; longitude += longitudeStep) { glColor(Renderer::PlanetographicGridColor); glPushMatrix(); glRotatef(longitude, 0.0f, 1.0f, 0.0f); glDrawArrays(GL_LINE_LOOP, 0, circleSubdivisions); glPopMatrix(); if (showCoordinateLabels) { int showLongitude = 0; char ew = 'E'; switch (longitudeConvention) { case EastWest: ew = 'E'; showLongitude = (int) longitude; break; case Eastward: if (longitude > 0.0f) showLongitude = 360 - (int) longitude; ew = 'E'; break; case Westward: if (longitude > 0.0f) showLongitude = 360 - (int) longitude; ew = 'W'; break; } char buf[64]; sprintf(buf, "%d%c", (int) showLongitude, ew); longLatLabel(buf, longitude, 0.0, viewRayOrigin, viewNormal, posd, q, semiAxes, offset, renderer); if (longitude > 0.0f && longitude < 180.0f) { showLongitude = (int) longitude; switch (longitudeConvention) { case EastWest: ew = 'W'; showLongitude = (int) longitude; break; case Eastward: showLongitude = (int) longitude; ew = 'E'; break; case Westward: showLongitude = (int) longitude; ew = 'W'; break; } sprintf(buf, "%d%c", showLongitude, ew); longLatLabel(buf, -longitude, 0.0, viewRayOrigin, viewNormal, posd, q, semiAxes, offset, renderer); } } } glDisableClientState(GL_VERTEX_ARRAY); glPopMatrix(); glDisable(GL_LIGHTING); glDisable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE); }
CornellBox::CornellBox() { Ray c(Vec3<double>(50,52,295.6),Vec3<double>(0,-0.042612,-1).norm()); setCamera(c); std::mt19937 gen(RANDOM()); std::normal_distribution<> sized(sizecenter,5); std::normal_distribution<> posd(40,10); auto hsv2vec3 = [](float h, float s, float v) { float r,g,b; HSVtoRGB(&r,&g,&b,h,s,v); return Vec3<double>(r,g,b); }; auto clamp = [](float v) { if(v < 0) return 0.0f; if(v > 1) return 1.0f; return v; }; auto randColor = [&](){ const float rate = 2; std::exponential_distribution<> d(rate+1); std::uniform_real_distribution<float> h(0,360); return hsv2vec3( h(gen), clamp((rate-d(gen))/rate), clamp((rate-d(gen))/rate) ); }; // Set objects auto makeWall = [&](Vec3<double> p, Vec3<double> c) { auto s = new Sphere(1e5); s->position = p; s->color = c; s->material_type = M_DIFFUSE; addShape(s); }; auto makeLight = [&](Vec3<double> p, Vec3<double> c) { auto s = new Sphere(600); s->position = p; s->emission = c; s->material_type = M_DIFFUSE; addShape(s); }; auto makeGlass = [&](double size, Vec3<double> p) { if(size == -1) { size = sized(gen); if(size < 1) size = 1; p.y += size; if(p.x - size < 0) p.x = size; if(p.z - size < 0) p.z = size; if(p.x + size > 81.6) p.x = 81.6 - size; if(p.z + size > 81.6) p.z = 81.6 - size; } auto s = new Sphere(size); s->position = p; s->color = Vec3<double>(1,1,1)*.999; s->material_type = M_REFRACTION; addShape(s); }; auto makeMirror = [&](double size, Vec3<double> p) { if(size == -1) { size = sized(gen); if(size < 1) size = 1; p.y += size; if(p.x - size < 0) p.x = size; if(p.z - size < 0) p.z = size; if(p.x + size > 81.6) p.x = 81.6 - size; if(p.z + size > 81.6) p.z = 81.6 - size; } auto s = new Sphere(size); s->position = p; s->color = Vec3<double>(1,1,1)*.999; s->material_type = M_SPECULAR; addShape(s); }; makeWall(Vec3<double>(1e5+1,40.8,81.6), randColor()); // right makeWall(Vec3<double>(-1e5+99,40.8,81.6), randColor());// left makeWall(Vec3<double>(50,40.8, 1e5), Vec3<double>(.75,.75,.75)); // back makeWall(Vec3<double>(50, 1e5, 81.6),Vec3<double>(.75,.75,.75)); // top makeWall(Vec3<double>(50,-1e5+81.6,81.6),Vec3<double>(.75,.75,.75)); // bottom makeGlass(-1, Vec3<double>(posd(gen)+5,posd(gen),posd(gen)/2+40)); makeMirror(-1, Vec3<double>(posd(gen)-5,0,posd(gen))); makeLight(Vec3<double>(50,681.6-0.27,81.6),Vec3<double>(12,12,12)); enumerateLights(); }