예제 #1
0
                // 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;
                }
예제 #2
0
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);
	}
}
예제 #4
0
/**
* 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);
	}
}
예제 #5
0
    /**
     * @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);
            }
        }
    }