// Given a point and a plane (defined by a coplanar point and a normal), compute the closest point // in the plane. (The plane is unbounded.) vec3f NearestPointInPlane(const vec3f &point, const vec3f &planePoint, const vec3f &planeNormal) { vec3f nearestPoint; vec3f pointDelta = point - planePoint; float delta = planeNormal.dot(pointDelta) / planeNormal.dot(planeNormal); nearestPoint = point - delta*planeNormal; return nearestPoint; }
bool Sphere::intersect(Ray ray, float* t, vec3f* intersectionPoint) const noexcept { const vec3f k{implementation->position - ray.position}; const float a = ray.direction.dot(k); const float D = a * a - (k.dot(k) - implementation->radius * implementation->radius); if (D < 0.0F) return false; const float sqrtD = std::sqrt(D); const float t1 = a - sqrtD; const float t2 = a + sqrtD; const float minT = std::min(t1, t2); const float maxT = std::max(t1, t2); const float fineT = minT >= 0.0F ? minT : maxT; if (fineT < 0.0F) return false; if (t) *t = fineT; if (intersectionPoint) *intersectionPoint = ray.position + ray.direction * fineT; return true; }
//****************************************************************** //FUNCTION: void COutdoorLightScattering::__getRaySphereIntersection(vec3f vRayOrigin, vec3f vRayDirection, vec3f vSphereCenter, float vSphereRadius, vec2f& voIntersection) { vRayOrigin -= vSphereCenter; float A = vRayDirection.dot(vRayDirection); float B = 2 * vRayOrigin.dot(vRayDirection); float C = vRayOrigin.dot(vRayOrigin) - vSphereRadius * vSphereRadius; float D = B * B - 4 * A * C; if (D < 0) { voIntersection = vec2f(-1); } else { D = sqrt(D); voIntersection = vec2f((-B - D) / 2 * A, (-B + D) / 2 * A); } }
/** * LookTowards * * Note 1: Function will exit if front_vec is (close to) parallel to the Y-axis; supply your own up_vec if this is the case. * Note 2: Not fully tested, use at own risk... * * Example: * Make camera look at 'my_node'. Note that world space positions are used. * camera->lookAt( my_node->getWorldPosition() - camera->getWorldPosition() ); */ void Transformable::lookTowards( vec3f front_vec, vec3f up_vec ) { vec3f right; vec3f up; vec3f prev_up; front_vec.normalize(); up_vec.normalize(); if (abs(up_vec.dot(front_vec)) > 0.99999f) { return; } if (parent && parent->is_transformable) { mat3f mat; R = ((Transformable *) parent)->getWorldMatrix().rotationMatrix(); R.inv(); prev_up = up_vec; right = front_vec.cross(prev_up); up = right.cross(front_vec); right.normalize(); up.normalize(); mat.setCol(0, right); mat.setCol(1, up); mat.setCol(2, -front_vec); R = R * mat; } else { prev_up = up_vec; right = front_vec.cross(prev_up); up = right.cross(front_vec); right.normalize(); up.normalize(); R.setCol(0, right); R.setCol(1, up); R.setCol(2, -front_vec); } }
/** * @brief Called in response to user interaction. */ void cylinder_sensor_node::do_activate(double timestamp, bool, bool active, const double (&p)[3]) { using openvrml::local::pi; using openvrml::local::pi_2; using openvrml::vec3f; using openvrml::make_vec3f; if (this->enabled_.sfbool::value()) { // Become active if (active && !this->is_active_.value()) { this->is_active_.value(active); // set activation point in local coords vec3f v = make_vec3f(static_cast<float>(p[0]), static_cast<float>(p[1]), static_cast<float>(p[2])); this->activationMatrix = this->modelview.inverse(); v *= this->activationMatrix; this->activationPoint = v; // Bearing vector in local coordinate system v.x(this->activationMatrix[2][0]); v.y(this->activationMatrix[2][1]); v.z(this->activationMatrix[2][2]); const vec3f bearing = v.normalize(); const vec3f up = make_vec3f(0.0, 1.0, 0.0); double ang = acos(bearing.dot(up)); if (ang > pi_2) { ang = pi - ang; } this->disk = (ang < this->disk_angle_.sffloat::value()); // send message node::emit_event(this->is_active_emitter_, timestamp); } // Become inactive else if (!active && this->is_active_.value()) { this->is_active_.value(active); node::emit_event(this->is_active_emitter_, timestamp); // save auto offset of rotation if (this->auto_offset_.sfbool::value()) { this->offset_.sffloat::value(rotation_val); node::emit_event(this->offset_, timestamp); } } // Tracking else if (active) { using openvrml::local::fequal; // get local coord for touch point vec3f Vec = make_vec3f(static_cast<float>(p[0]), static_cast<float>(p[1]), static_cast<float>(p[2])); Vec = Vec * this->activationMatrix; this->track_point_changed_.value(Vec); node::emit_event(this->track_point_changed_emitter_, timestamp); vec3f tempv; float rot, radius; vec3f dir1 = make_vec3f(Vec[0], 0, Vec[2]); radius = this->disk ? 1.0f : dir1.length(); dir1 = dir1.normalize(); vec3f dir2 = make_vec3f(this->activationPoint.x(), 0, this->activationPoint.z()); dir2 = dir2.normalize(); tempv = dir2 * dir1; vec3f cx(tempv); cx = cx.normalize(); if (cx.length() == 0.0) { return; } rot = radius * float(acos(dir2.dot(dir1))); if (fequal(cx.y(), -1.0f)) { rot = -rot; } if (this->auto_offset_.sfbool::value()) { rot = this->offset_.sffloat::value() + rot; } if (this->min_angle_.sffloat::value() < this->max_angle_.sffloat::value()) { if (rot < this->min_angle_.sffloat::value()) { rot = this->min_angle_.sffloat::value(); } else if (rot > this->max_angle_.sffloat::value()) { rot = this->max_angle_.sffloat::value(); } } this->rotation_val = rot; this->rotation_changed_.sfrotation::value( openvrml::make_rotation(0, 1, 0, rot)); node::emit_event(this->rotation_changed_emitter_, timestamp); } } }