bool CollisionManager::checkLineOfSightInParentCell(SceneObject* object, Vector3& endPoint) { ManagedReference<SceneObject*> parent = object->getParent(); if (parent == NULL || !parent->isCellObject()) return true; CellObject* cell = cast<CellObject*>( parent.get()); SharedObjectTemplate* objectTemplate = parent->getRootParent().get()->getObjectTemplate(); PortalLayout* portalLayout = objectTemplate->getPortalLayout(); MeshAppearanceTemplate* appearanceMesh = NULL; if (portalLayout == NULL) return true; try { appearanceMesh = portalLayout->getMeshAppearanceTemplate(cell->getCellNumber()); } catch (Exception& e) { return true; } if (appearanceMesh == NULL) { //info("null appearance mesh "); return true; } AABBTree* aabbTree = appearanceMesh->getAABBTree(); if (aabbTree == NULL) return true; //switching Y<->Z, adding 0.1 to account floor Vector3 startPoint = object->getPosition(); startPoint.set(startPoint.getX(), startPoint.getY(), startPoint.getZ() + 0.1f); endPoint.set(endPoint.getX(), endPoint.getY(), endPoint.getZ() + 0.1f); Vector3 dir = endPoint - startPoint; dir.normalize(); float distance = endPoint.distanceTo(startPoint); float intersectionDistance; Ray ray(startPoint, dir); Triangle* triangle = NULL; //nothing in the middle if (aabbTree->intersects(ray, distance, intersectionDistance, triangle, true)) return false; Ray ray2(endPoint, Vector3(0, -1, 0)); //check if we are in the cell with dir (0, -1, 0) if (!aabbTree->intersects(ray2, 64000.f, intersectionDistance, triangle, true)) return false; return true; }
TEST(CubeTest, HasIntersection) { Cube cube; Ray ray1(Point3(0, 0, 2), Vector3(0, 0, -1)); EXPECT_TRUE(cube.HasIntersection(ray1, 2)); EXPECT_FALSE(cube.HasIntersection(ray1, 0.5)); Ray ray2(Point3(0, 0, 2), Vector3(0, 0, 1)); EXPECT_FALSE(cube.HasIntersection(ray2, 20)); }
void Ray2Tests::testBasics() { Ray2 ray1(Point2(2.0f, 0.0f), Vector2(2.0f, 0.0f)); Ray2 ray2(Point2(1.0f, 1.0f), Vector2(2.0f, 2.0f)); CPTAssert(ray1.origin() == Point2(2.0f, 0.0f)); CPTAssert(ray1.direction() == Point2(1.0f, 0.0f)); CPTAssert(ray2.origin() == Point2(1.0f, 1.0f)); CPTAssert(ray2.direction() == Point2(1.0f, 1.0f).unit()); }
TEST(RayTest, equality) { Geom::Point3D origin(0, 0, 0); Geom::Vector3D direction(1, 1, 1); Geom::Ray ray1(origin, direction); Geom::Ray ray2(origin, direction); EXPECT_EQ(ray1, ray2); Geom::Ray ray3(origin, Geom::Vector3D(2, 3, 2)); EXPECT_NE(ray1, ray3); }
void LPESimplify::drawHandleLine(Geom::Point p,Geom::Point p2) { Geom::Path path; path.start( p ); double diameter = radius_helper_nodes; if(helper_size > 0 && Geom::distance(p,p2) > (diameter * 0.35)) { Geom::Ray ray2(p, p2); p2 = p2 - Geom::Point::polar(ray2.angle(),(diameter * 0.35)); } path.appendNew<Geom::LineSegment>( p2 ); hp.push_back(path); }
void ocTriTree::intersect(const z3D::Core::Ray& ray, vector<int32_t>& tris) { IceMaths::Ray ray2(Point(&ray.origin().x), Point(&ray.direction().x)); _pimpl.get().ray_collider_dest.Reset(); bool okay = _pimpl.get().ray_collider.Collide(ray2, _pimpl.get().model); if(!okay) return; size_t count = (size_t)_pimpl.get().ray_collider_dest.GetNbFaces(); const Opcode::CollisionFace* face_iter = _pimpl.get().ray_collider_dest.GetFaces(); for(size_t i = 0; i < count; ++i, ++face_iter) tris.push_back(face_iter->mFaceID); }
void tst_QRay3D::compare() { Qt3DRender::RayCasting::QRay3D ray1(QVector3D(10, 20, 30), QVector3D(-3, -4, -5)); Qt3DRender::RayCasting::QRay3D ray2(QVector3D(10, 20, 30), QVector3D(1.5f, 2.0f, 2.5f)); Qt3DRender::RayCasting::QRay3D ray3(QVector3D(0, 20, 30), QVector3D(-3, -4, -5)); QVERIFY(ray1 == ray1); QVERIFY(!(ray1 != ray1)); QVERIFY(qFuzzyCompare(ray1, ray1)); QVERIFY(ray1 != ray2); QVERIFY(!(ray1 == ray2)); QVERIFY(!qFuzzyCompare(ray1, ray2)); QVERIFY(ray1 != ray3); QVERIFY(!(ray1 == ray3)); QVERIFY(!qFuzzyCompare(ray1, ray3)); }
int main(int argc, char *argv[]) { Vector orig(0,0,0); double radius = 1; Ray ray1(Vector(-2, 1, 0), Vector(1,0,0)); Ray ray2(Vector(-2, 1, 0), Vector(-1,0,0)); Ray ray3(Vector(0, 0.5f, 0), Vector(1,0,0)); Sphere sphere(orig, radius); ASSERT(sphere.intersect(ray1), true, "No intersection"); ASSERT(sphere.intersect(ray2), false, "Error in intersection"); ASSERT(sphere.intersect(ray3), false, "Origin is inside the Sphere"); REPORT(); return ERROR_COUNT; }
TEST(CubeTest, FindIntersection) { Cube cube; double t; Point3 point; Vector3 normal; Ray ray1(Point3(0, 0, 2), Vector3(0, 0, -1)); EXPECT_TRUE(cube.FindIntersection(ray1, &t, &point, &normal)); EXPECT_EQ(1, t); EXPECT_EQ(0, point[0]); EXPECT_EQ(0, point[1]); EXPECT_EQ(1, point[2]); EXPECT_EQ(0, normal[0]); EXPECT_EQ(0, normal[1]); EXPECT_EQ(1, normal[2]); Ray ray2(Point3(0, 0, 2), Vector3(0, 0, 1)); EXPECT_FALSE(cube.FindIntersection(ray2, &t, &point, &normal)); }
TEST(TestRaycast, TestPlaneIntersection) { FTRaycast ray(glm::vec3(0, 2, 0), glm::vec3(1, 3, 1)); // Test Standard glm::vec3 intersection; EXPECT_TRUE(ray.intersectsPlane(glm::vec3(2,1,-4), glm::vec3(3,2,1), intersection)); EXPECT_EQ(intersection, glm::vec3(2, 8, 2)); // Test parrallel no intersection intersection = glm::vec3(23, 5, 78); FTRaycast ray2(glm::vec3(1, 4, 0), glm::vec3(1, 2, 1)); EXPECT_FALSE(ray2.intersectsPlane(glm::vec3(2, 1, -4), glm::vec3(3, 2, 1), intersection)); EXPECT_EQ(intersection, glm::vec3(23, 5, 78)); // Test parallel with intersection FTRaycast ray3(glm::vec3(2, 8, 2), glm::vec3(1, 2, 1)); EXPECT_TRUE(ray3.intersectsPlane(glm::vec3(2, 1, -4), glm::vec3(3, 2, 1), intersection)); EXPECT_EQ(intersection, glm::vec3(3,2,1)); }
//--------------------------------------------------------------------- Vec3 Scene::ComputeFirstBounceIllumination(const Ray& ray, KdTreeStats& kdTreeStats, ShadingStats& shadingStats) const { const int nSamples = 128; const Object* obj = m_kdtree.Intersect(ray, kdTreeStats); if (!obj) { return Vec3(0.f); } Vec3 p = ray(ray.tmax); Vec3 n = (p - obj->center).GetNormalized(); Vec3 t1, t2; BuildCoordSystem(n, t1, t2); Vec3 radiance = Vec3(0.f); for (int i = 0; i < nSamples; i++) { float u1 = genrand_float(); float u2 = genrand_float(); Vec3 localDir = CosineSampleHemisphere(u1, u2); Vec3 wi = localDir.x * t1 + localDir.y * t2 + localDir.z * n; Ray ray2(p, wi); radiance += ComputeDirectIllumination(ray2, kdTreeStats, shadingStats); } radiance *= obj->albedo / nSamples; return radiance; }
void tst_QRay3D::transform() { QFETCH(QVector3D, point); QFETCH(QVector3D, direction); QMatrix4x4 m; m.translate(-1.0f, 2.5f, 5.0f); m.rotate(45.0f, 1.0f, 1.0f, 1.0f); m.scale(23.5f); Qt3DRender::RayCasting::QRay3D ray1(point, direction); Qt3DRender::RayCasting::QRay3D ray2(ray1); Qt3DRender::RayCasting::QRay3D ray3; ray1.transform(m); ray3 = ray2.transformed(m); QVERIFY(fuzzyCompare(ray1.origin(), ray3.origin())); QVERIFY(fuzzyCompare(ray1.direction(), ray3.direction())); QVERIFY(fuzzyCompare(ray1.origin(), m * point)); QVERIFY(fuzzyCompare(ray1.direction(), m.mapVector(direction))); }
void tst_QRay3D::transform() { QFETCH(QVector3D, point); QFETCH(QVector3D, direction); QMatrix4x4 m; m.translate(-1.0f, 2.5f, 5.0f); m.rotate(45.0f, 1.0f, 1.0f, 1.0f); m.scale(23.5f); QRay3D ray1(point, direction); QRay3D ray2(ray1); QRay3D ray3; ray1.transform(m); ray3 = ray2.transformed(m); QCOMPARE(ray1.origin(), ray3.origin()); QCOMPARE(ray1.direction(), ray3.direction()); QCOMPARE(ray1.origin(), m * point); QCOMPARE(ray1.direction(), m.mapVector(direction)); }
Vec3f RayTracer::traceRay(Ray &ray, float tmin, int bounces, float weight, float indexOfRefraction, Hit &hit) const { //printf("当前已有光线:\n"); //RayTree::Print(); Vec3f canswer; if (bounces > max_bounces) return Vec3f(0.0f, 0.0f, 0.0f); Camera *camera = sceneParser->getCamera(); Group *group = sceneParser->getGroup(); int num_lights = sceneParser->getNumLights(); Vec3f cambient = sceneParser->getAmbientLight(); //原来最后是这里出了问题,一旦碰到有转换的物体,那么hit带出来的值是 //转换后的视线看到的值,而非本来视线看到的值 //所以解决方案是:距离不变,根据距离重新计算焦点 if (group->intersect(ray, hit, tmin))//撞到了 { if (is_view_ray) { RayTree::SetMainSegment(ray, 0, hit.getT()); is_view_ray = false; } Vec3f cobject = hit.getMaterial()->getDiffuseColor(); Vec3f hitPoint = hit.getIntersectionPoint(); //环境光部分 canswer = cambient * cobject; Vec3f clight;//光的颜色 Vec3f light_dir;//指向光的方向 Vec3f normal_dir = hit.getNormal();//交点法线向量 float distolight;//距离光源的距离 for (int i = 0; i < num_lights; i++) { Light *light = sceneParser->getLight(i); //light_dir : the direction to the light // 该方法用于获得指向光的方向,光的颜色,和到达光的距离 // 第一个参数传递的是焦点信息 light->getIllumination(hitPoint, light_dir, clight, distolight); Ray ray2(hitPoint, light_dir); Vec3f init_normal(0, 0, 0); Hit hit2(distolight, NULL, init_normal); //阴影检测 if (shadow) { if (group->intersect(ray2, hit2, tmin)){ RayTree::AddShadowSegment(ray2, 0, hit2.getT()); continue; } RayTree::AddShadowSegment(ray2, 0, hit2.getT()); } //cpixel = cambient * cobject + SUMi [ clamped(Li . N) * clighti * cobject ] //返回局部光 canswer = canswer + hit.getMaterial()->Shade(ray, hit, light_dir, clight); } //printf("当前已有光线:\n"); //RayTree::Print(); //反射光 Material *material = hit.getMaterial(); Vec3f rc = material->getReflectiveColor(); if (rc.r() > 0 && rc.g() > 0 && rc.b() > 0) { Vec3f mirrorDir; Vec3f incoming = ray.getDirection(); mirrorDir = mirrorDirection(normal_dir, incoming); // The ray weight is simply multiplied by the magnitude of the reflected color Ray ray3(hitPoint, mirrorDir); Vec3f init_normal(0, 0, 0); Hit hit3(distolight, NULL, init_normal); //忘记乘以本身的反射光系数%………… canswer += traceRay(ray3, tmin, bounces + 1, weight*rc.Length(), indexOfRefraction, hit3)*rc; if (bounces + 1 < max_bounces) RayTree::AddReflectedSegment(ray3, 0, hit3.getT()); } //printf("当前已有光线:\n"); //RayTree::Print(); //从这里开始还都存在问题!!!!! //折射光 Vec3f transmitted; Vec3f tc = material->getTransparentColor(); float index = material->getIndexOfRefraction(); if (tc.r() > 0 && tc.g() > 0 && tc.b() > 0) { Vec3f init_normal(0, 0, 0); Hit hit4(distolight, NULL, init_normal); //在判断折射光的存在之后,要考虑光线的位置:物体内还是物体外 //这里根据normal和incoming的点积来判断 Vec3f incoming = ray.getDirection(); float judge = normal_dir.Dot3(incoming); if (judge < 0)//光线在外 { if (transmittedDirection(normal_dir, incoming, 1, index, transmitted)) { Ray ray4(hitPoint, transmitted); canswer += traceRay(ray4, tmin, bounces+1, weight*rc.Length(), index, hit4)*tc; RayTree::AddTransmittedSegment(ray4, 0, hit4.getT()); } } else//光线在内 { normal_dir.Negate(); if (transmittedDirection(normal_dir, incoming, index, 1, transmitted)) { Ray ray4(hitPoint, transmitted); canswer += traceRay(ray4, tmin, bounces+1, weight*rc.Length(), 1, hit4)*tc; RayTree::AddTransmittedSegment(ray4, 0, hit4.getT()); } } } //printf("当前已有光线:\n"); //RayTree::Print(); } else canswer = sceneParser->getBackgroundColor(); canswer.Clamp(); return canswer; }
bool smooth_curve(const BVH *bvh, const VectorXu &E2E, std::vector<CurvePoint> &curve, bool watertight) { const MatrixXu &F = *bvh->F(); const MatrixXf &V = *bvh->V(), &N = *bvh->N(); cout << endl; std::vector<CurvePoint> curve_new; std::vector<Float> weight; std::vector<uint32_t> path; cout << "Input: " << curve.size() << " vertices" << endl; for (int it=0;; ++it) { if (curve.size() < 2) return false; for (uint32_t it2=0; it2<curve.size(); ++it2) { curve_new.clear(); curve_new.push_back(curve[0]); for (uint32_t i=1; i<curve.size()-1; ++i) { Vector3f p_new = 0.5f * (curve[i-1].p + curve[i+1].p); Vector3f n_new = (curve[i-1].n + curve[i+1].n).normalized(); Float maxlength = (curve[i-1].p - curve[i+1].p).norm()*2; Ray ray1(p_new, n_new, 0, maxlength); Ray ray2(p_new, -n_new, 0, maxlength); uint32_t idx1 = 0, idx2 = 0; Float t1 = 0, t2 = 0; Vector2f uv1, uv2; bool hit1 = bvh->rayIntersect(ray1, idx1, t1, &uv1); bool hit2 = bvh->rayIntersect(ray2, idx2, t2, &uv2); if (!hit1 && !hit2) continue; CurvePoint pt; if (t1 < t2) { pt.p = ray1(t1); pt.f = idx1; pt.n = ((1 - uv1.sum()) * N.col(F(0, idx1)) + uv1.x() * N.col(F(1, idx1)) + uv1.y() * N.col(F(2, idx1))).normalized(); } else { pt.p = ray2(t2); pt.f = idx2; pt.n = ((1 - uv2.sum()) * N.col(F(0, idx2)) + uv2.x() * N.col(F(1, idx2)) + uv2.y() * N.col(F(2, idx2))).normalized(); } curve_new.push_back(pt); } curve_new.push_back(curve[curve.size()-1]); curve.swap(curve_new); } if (!watertight && it == 1) break; curve_new.clear(); curve_new.push_back(curve[0]); for (uint32_t i=1; i<curve.size(); ++i) { if (!astar(F, E2E, V, curve[i-1].f, curve[i].f, path)) return false; auto closest = [](const Vector3f &p0, const Vector3f &p1, const Vector3f &target) -> Vector3f { Vector3f d = (p1-p0).normalized(); return p0 + d * std::min(std::max((target-p0).dot(d), 0.0f), (p0-p1).norm()); }; if (path.size() > 2) { uint32_t base = curve_new.size() - 1; for (uint32_t j=1; j<path.size()-1; ++j) { uint32_t f = path[j]; Vector3f p0 = V.col(F(0, f)), p1 = V.col(F(1, f)), p2 = V.col(F(2, f)); CurvePoint pt2; pt2.f = f; pt2.n = (p1-p0).cross(p2-p0).normalized(); pt2.p = (p0+p1+p2) * (1.0f / 3.0f); curve_new.push_back(pt2); } curve_new.push_back(curve[i]); for (uint32_t q=1; q<path.size()-1; ++q) { for (uint32_t j=1; j<path.size()-1; ++j) { Float bestDist1 = std::numeric_limits<Float>::infinity(); Float bestDist2 = std::numeric_limits<Float>::infinity(); Vector3f bestPt1 = Vector3f::Zero(), bestPt2 = Vector3f::Zero(); uint32_t f = path[j]; for (uint32_t k=0; k<3; ++k) { Vector3f closest1 = closest(V.col(F(k, f)), V.col(F((k + 1) % 3, f)), curve_new[base+j-1].p); Vector3f closest2 = closest(V.col(F(k, f)), V.col(F((k + 1) % 3, f)), curve_new[base+j+1].p); Float dist1 = (closest1 - curve_new[base+j-1].p).norm(); Float dist2 = (closest2 - curve_new[base+j+1].p).norm(); if (dist1 < bestDist1) { bestDist1 = dist1; bestPt1 = closest1; } if (dist2 < bestDist2) { bestDist2 = dist2; bestPt2 = closest2; } } curve_new[base+j].p = (bestPt1 + bestPt2) * 0.5f; } } } else { curve_new.push_back(curve[i]); } } curve.swap(curve_new); curve_new.clear(); curve_new.push_back(curve[0]); weight.clear(); weight.push_back(1.0f); for (uint32_t i=0; i<curve.size(); ++i) { auto &cur = curve_new[curve_new.size()-1]; auto &cur_weight = weight[weight.size()-1]; if (cur.f == curve[i].f) { cur.p += curve[i].p; cur.n += curve[i].n; cur_weight += 1; } else { curve_new.push_back(curve[i]); weight.push_back(1.f); } } for (uint32_t i=0; i<curve_new.size(); ++i) { curve_new[i].p /= weight[i]; curve_new[i].n.normalize(); } curve_new[0] = curve[0]; curve_new[curve_new.size()-1] = curve[curve.size()-1]; if (curve_new.size() < 2 || curve_new[0].f == curve_new[curve_new.size()-1].f) return false; curve_new.swap(curve); if (it > 2) break; } cout << "Smoothed curve: " << curve.size() << " vertices" << endl; return true; }
void LPESimplify::generateHelperPathAndSmooth(Geom::PathVector &result) { if(steps < 1) { return; } Geom::PathVector tmp_path; Geom::CubicBezier const *cubic = NULL; for (Geom::PathVector::iterator path_it = result.begin(); path_it != result.end(); ++path_it) { if (path_it->empty()) { continue; } Geom::Path::iterator curve_it1 = path_it->begin(); // incoming curve Geom::Path::iterator curve_it2 = ++(path_it->begin());// outgoing curve Geom::Path::iterator curve_endit = path_it->end_default(); // this determines when the loop has to stop SPCurve *nCurve = new SPCurve(); if (path_it->closed()) { // if the path is closed, maybe we have to stop a bit earlier because the // closing line segment has zerolength. const Geom::Curve &closingline = path_it->back_closed(); // the closing line segment is always of type // Geom::LineSegment. if (are_near(closingline.initialPoint(), closingline.finalPoint())) { // closingline.isDegenerate() did not work, because it only checks for // *exact* zero length, which goes wrong for relative coordinates and // rounding errors... // the closing line segment has zero-length. So stop before that one! curve_endit = path_it->end_open(); } } if(helper_size > 0) { drawNode(curve_it1->initialPoint()); } nCurve->moveto(curve_it1->initialPoint()); Geom::Point start = Geom::Point(0,0); while (curve_it1 != curve_endit) { cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1); Geom::Point point_at1 = curve_it1->initialPoint(); Geom::Point point_at2 = curve_it1->finalPoint(); Geom::Point point_at3 = curve_it1->finalPoint(); Geom::Point point_at4 = curve_it1->finalPoint(); if(start == Geom::Point(0,0)) { start = point_at1; } if (cubic) { point_at1 = (*cubic)[1]; point_at2 = (*cubic)[2]; } if(path_it->closed() && curve_it2 == curve_endit) { point_at4 = start; } if(curve_it2 != curve_endit) { cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it2); if (cubic) { point_at4 = (*cubic)[1]; } } Geom::Ray ray1(point_at2, point_at3); Geom::Ray ray2(point_at3, point_at4); double angle1 = Geom::deg_from_rad(ray1.angle()); double angle2 = Geom::deg_from_rad(ray2.angle()); if((smooth_angles >= std::abs(angle2 - angle1)) && !are_near(point_at4,point_at3) && !are_near(point_at2,point_at3)) { double dist = Geom::distance(point_at2,point_at3); Geom::Angle angleFixed = ray2.angle(); angleFixed -= Geom::Angle::from_degrees(180.0); point_at2 = Geom::Point::polar(angleFixed, dist) + point_at3; } nCurve->curveto(point_at1, point_at2, curve_it1->finalPoint()); cubic = dynamic_cast<Geom::CubicBezier const *>(nCurve->last_segment()); if (cubic) { point_at1 = (*cubic)[1]; point_at2 = (*cubic)[2]; if(helper_size > 0) { if(!are_near((*cubic)[0],(*cubic)[1])) { drawHandle((*cubic)[1]); drawHandleLine((*cubic)[0],(*cubic)[1]); } if(!are_near((*cubic)[3],(*cubic)[2])) { drawHandle((*cubic)[2]); drawHandleLine((*cubic)[3],(*cubic)[2]); } } } if(helper_size > 0) { drawNode(curve_it1->finalPoint()); } ++curve_it1; ++curve_it2; } if (path_it->closed()) { nCurve->closepath_current(); } tmp_path.push_back(nCurve->get_pathvector()[0]); nCurve->reset(); delete nCurve; } result = tmp_path; }