bool VisObj::select_vertex(const CGLA::Vec2i& pos) { float d; if(depth_pick(pos[0], pos[1], d)) { Vec3d c; float r; bsphere(mani, c, r); VertexID closest = InvalidVertexID; double min_dist = DBL_MAX; for(auto vid : mani.vertices()) { Vec3d wp = world2screen(mani.pos(vid)); if(sqr_length(Vec2d(wp[0],wp[1])-Vec2d(pos))<100) { double dist = sqr_length(screen2world(pos[0], pos[1], d)-mani.pos(vid)); if(dist < min_dist) { min_dist = dist; closest = vid; } } } if(closest != InvalidVertexID) { vertex_selection.resize(mani.allocated_vertices(),0); vertex_selection[closest] = !vertex_selection[closest]; active_selection = true; post_create_display_list(); return true; } } return false; }
void VisObj::refit() { bsphere(mani, bsphere_center, bsphere_radius); view_ctrl.set_centre(Vec3f(bsphere_center)); view_ctrl.set_eye_dist(2*bsphere_radius); }
void VPLShaderManager::setVPL(const VPL &vpl) { const size_t sampleCount = 250; /* Estimate good near and far plane locations by tracing some rays */ m_nearClip = std::numeric_limits<Float>::infinity(); m_farClip = -std::numeric_limits<Float>::infinity(); /* Update animations */ for (size_t i=0; i<m_animatedGeometry.size(); ++i) { const AnimatedGeometryRecord &agRec = m_animatedGeometry[i]; const Matrix4x4 &matrix = agRec.trafo->eval(vpl.its.time).getMatrix(); if (agRec.geometryIndex >= 0) m_geometry[agRec.geometryIndex].second = matrix; if (agRec.opaqueGeometryIndex >= 0) m_opaqueGeometry[agRec.opaqueGeometryIndex].second = matrix; } if (vpl.type != EDirectionalEmitterVPL) { /* Trace a few rays from the VPL to estimate a suitable depth range */ for (size_t i=0; i<sampleCount; ++i) { Point2 sample = sample02(i); Ray ray; if (vpl.type == ESurfaceVPL || (vpl.type == EPointEmitterVPL && vpl.emitter->getType() & Emitter::EOnSurface)) { ray = Ray(vpl.its.p, vpl.its.shFrame.toWorld( warp::squareToCosineHemisphere(sample)), 0); #if defined(MTS_VPL_USE_PARABOLOID_MAPS) m_shadowMapType = ShadowMapGenerator::EParaboloid; #elif defined(MTS_VPL_USE_SINGLE_PASS) m_shadowMapType = ShadowMapGenerator::EHemicubeSinglePass; #else m_shadowMapType = ShadowMapGenerator::EHemicube; #endif } else if (vpl.type == EPointEmitterVPL) { ray = Ray(vpl.its.p, warp::squareToUniformSphere(sample), 0); #if defined(MTS_VPL_USE_SINGLE_PASS) m_shadowMapType = ShadowMapGenerator::ECubeSinglePass; #else m_shadowMapType = ShadowMapGenerator::ECube; #endif } else { Log(EError, "Unsupported VPL type!"); } ConstShapePtr shape; Normal n; Point2 uv; /* unused */ Float t, accum = 0; bool hit = false; for (int it=0; it<5; ++it) { if (!m_scene->rayIntersect(ray, t, shape, n, uv)) break; accum += t; if (!(shape->getBSDF()->getType() & BSDF::ETransmission)) { hit = true; break; } ray.o = ray(t); } if (hit && accum > 0) { m_nearClip = std::min(m_nearClip, accum); m_farClip = std::max(m_farClip, accum); } } if (m_nearClip >= m_farClip) { BSphere bsphere(m_scene->getKDTree()->getAABB().getBSphere()); Float minDist = 0; if ((vpl.type == ESurfaceVPL || vpl.type == EPointEmitterVPL) && !bsphere.contains(vpl.its.p)) minDist = (bsphere.center - vpl.its.p).length() - bsphere.radius; /* If everything fails, use really conservative bounds */ m_farClip = minDist + bsphere.radius * 2.25f; m_nearClip = std::max(minDist - 0.25f * bsphere.radius, m_farClip * 1e-5f); } else { m_nearClip = std::max(m_nearClip / 1.5f, m_farClip * 1e-5f); m_farClip *= 1.5f; } m_shadowMapTransform = (Transform::translate(Vector(vpl.its.p)) * Transform::fromFrame(vpl.its.shFrame)).inverse(); } else { m_shadowMapType = ShadowMapGenerator::EDirectional; m_shadowMapTransform = m_shadowGen->directionalFindGoodFrame( m_scene->getKDTree()->getAABB(), vpl.its.shFrame.n); } bool is2D = m_shadowMapType == ShadowMapGenerator::EParaboloid || m_shadowMapType == ShadowMapGenerator::EDirectional; if (is2D) { if (!m_shadowMap2D || m_shadowMap2D->getSize().x != m_shadowMapResolution) { if (m_shadowMap2D) m_shadowMap2D->cleanup(); m_shadowMap2D = m_shadowGen->allocate(m_renderer, m_shadowMapType, m_shadowMapResolution); } m_shadowMap = m_shadowMap2D; } else { if (!m_shadowMapCube || m_shadowMapCube->getSize().x != m_shadowMapResolution) { if (m_shadowMapCube) m_shadowMapCube->cleanup(); m_shadowMapCube = m_shadowGen->allocate(m_renderer, m_shadowMapType, m_shadowMapResolution); } m_shadowMap = m_shadowMapCube; } Float sample = sampleTEAFloat(m_vplIndex++, 0x12345); m_shadowGen->render(m_renderer, m_shadowMap, m_shadowMapType, m_shadowMapTransform, m_nearClip, m_farClip, sample > 0.3 ? m_opaqueGeometry : m_geometry); /* Convert between the Mitsuba and OpenGL matrix conventions */ m_shadowMapTransform = Transform::scale( Vector(-1.0f, 1.0f, -1.0f)) * m_shadowMapTransform; }