def intersect(self, ray, t0=0, t1=10000):
     """ Given a ray p(t) = e + td and an implicit surface f(p) = 0.
         We can represent a sphere in vector form:
         (p−c)·(p−c)−R2 = 0.
         Any point p that satisfies this equation is on the sphere.
         plug in p(t) in previous equation yields:
         (e+td−c)·(e+td−c)−R2 = 0
         which can be rearranged as :
         (d·d)t2 +2d·(e−c)t+(e−c)·(e−c)−R2 =0.
         giving us a quadratic equation, for which we can solve for t
         :param ray:  a Ray to p(t) = e + td
         :return:
             False if the discriminant is negative
             True if discriminant is positive and there are two solution
     """
     ec = ray.e - self.c
     A = QVector3D.dotProduct(ray.d, ray.d)
     B = QVector3D.dotProduct(2 * ray.d, ec)
     C = QVector3D.dotProduct(ec, ec) - self.r * self.r
     discriminant = B * B - 4 * A * C
     if discriminant < EPSILON:
         return -1.0
     localt0 = (-B + math.sqrt(discriminant)) / 2 * A
     localt1 = (-B - math.sqrt(discriminant)) / 2 * A
     t = min(localt0, localt1)
     return min(t, t1)
Beispiel #2
0
 def project(self, point, depth=0.0):
     """Returns intersection if any"""
     ray = self.ray(point)
     tMin = -math.inf
     tMax = math.inf
     obb_xform = QMatrix4x4()
     obb_center = QVector3D(0.0, 0.0, depth)
     point = obb_center - ray.origin()
     plane_size = [100.0, 100.0, 1E-6]
     for i in range(3):
         axis = QVector3D(obb_xform[0, i], obb_xform[1, i],
                          obb_xform[2, i]).normalized()
         half_length = plane_size[i]
         e = QVector3D.dotProduct(axis, point)
         f = QVector3D.dotProduct(axis, ray.direction())
         if abs(f) > 10E-6:
             t1 = (e + half_length) / f
             t2 = (e - half_length) / f
             if t1 > t2:
                 w = t1
                 t1 = t2
                 t2 = w
             if t1 > tMin:
                 tMin = t1
             if t2 < tMax:
                 tMax = t2
             if tMin > tMax:
                 return QVector3D(0, 0, 0)
             if tMax < 0:
                 return QVector3D(0, 0, 0)
         elif -e - half_length > 0.0 or -e + half_length < 0.0:
             return QVector3D(0, 0, 0)
     if tMin > 0:
         return ray.origin() + tMin * ray.direction()
     return ray.origin() + tMax * ray.direction()
Beispiel #3
0
 def intersect(self, ray):
     """Returns intersection if any"""
     tMin = -math.inf
     tMax = math.inf
     obb_xform = self.transform()
     obb_center = QVector3D(obb_xform[0, 3], obb_xform[1, 3], obb_xform[2,
                                                                        3])
     point = obb_center - ray.origin()
     for i in range(3):
         axis = QVector3D(obb_xform[0, i], obb_xform[1, i],
                          obb_xform[2, i]).normalized()
         half_length = QVector3D(obb_xform[i, 0], obb_xform[i, 1],
                                 obb_xform[i, 2]).length() / 2.0
         e = QVector3D.dotProduct(axis, point)
         f = QVector3D.dotProduct(axis, ray.direction())
         if abs(f) > 10E-6:
             t1 = (e + half_length * self._pickFactor) / f
             t2 = (e - half_length * self._pickFactor) / f
             if t1 > t2:
                 w = t1
                 t1 = t2
                 t2 = w
             if t1 > tMin:
                 tMin = t1
             if t2 < tMax:
                 tMax = t2
             if tMin > tMax:
                 return (False, math.inf)
             if tMax < 0:
                 return (False, math.inf)
         elif -e - half_length > 0.0 or -e + half_length < 0.0:
             return (False, math.inf)
     if tMin > 0:
         return (True, tMin)
     return (True, tMax)
 def intersect(self, ray):
     p1 = self.vertices[0]
     denom = QVector3D.dotProduct(ray.d, self._normal)
     t = QVector3D.dotProduct(p1 - ray.e, self._normal) / denom
     if abs(denom) < EPSILON:  # the  polygon is parallel to the ray
         return False
     p = ray.e + t * ray.d
     return True
Beispiel #5
0
 def move(self, x, y, width, height):
     self.currentPos = self.mapToSphere(x, y, width, height)
     self._axis = QVector3D.crossProduct(self.lastPos, self.currentPos)
     length = math.sqrt(QVector3D.dotProduct(self.axis, self.axis))
     self.angle = QVector3D.dotProduct(self.lastPos, self.currentPos)
     self.lastPos = self.currentPos
     if length > EPSILON:
         return QQuaternion.fromAxisAndAngle(self._axis, self.angle)
     return QQuaternion.fromAxisAndAngle(0, 0, 0, 0)
 def intersect(self, ray, t0=0, t1=10000):
     """ A point P is on the plane if Ndot(P-Q) = 0 , where Q is a point in the plane
     :param ray:
     :return:
     """
     if QVector3D.dotProduct(self.normal, ray.d) == 0:
         return False
     t = QVector3D.dotProduct(
         self.normal,
         (self.point - self.distance) - ray.e) / QVector3D.dotProduct(
             self.normal, ray.d)
     if t < 0:
         return False
     return t
Beispiel #7
0
    def ray_pick_test(self, origin, direction):
        """Check whether the given ray intersects this object.

        :param QVector3D origin: the camera position
        :param QVector3D direction: the direction vector. This MUST be normalized.
        :returns: the distance to the closest point of this object along the ray. Negative values if no intersection
        """
        L = origin - QVector3D(*self.offset)
        t0, t1 = solve_quadratic(1, 2 * QVector3D.dotProduct(direction, L),
                                 QVector3D.dotProduct(L, L) - self.scale**2)
        if t0 is None or (t0 <= 0 and t1 <= 0):
            return -1
        elif t0 > 0 and t0 < t1:
            return t0
        else:
            return t1
Beispiel #8
0
def angleBetweenTwoVectors(A=None, B=None):
    ABoverABmag = QVector3D.dotProduct(A, B) / (A.length() * B.length())
    if ABoverABmag > 0.999999:
        ABoverABmag = 1.0
    elif ABoverABmag < -0.99999:
        ABoverABmag = -1.0
    return math.degrees(math.acos(ABoverABmag))
Beispiel #9
0
    def moveGrabber(self, dx, dy):
        if self.currentEdgePair is None or self.selectedGrabber is None:
            return

        cPos = self.cameraPosition()        
        cVec = self.opts['center'] - cPos
        dist = cVec.length()
        xDist = dist * 2. * np.tan(0.5 * self.opts['fov'] * np.pi / 180.)  ## approx. width of view at distance of center point
        xScale = xDist / self.width()

        translationVector = QVector3D(dx, dy, 0) * xScale * 100
        if translationVector.length() is not 0:
            self.selectedGrabber.showDirectionArrow(3)
        else:
            self.selectedGrabber.showDirectionArrow(0)

        transformation, res = self.projectionMatrix().inverted()
        translationVector = transformation * translationVector

        orientation = self.currentEdgePair.getOrientation()
        xAxis = QVector3D(orientation[0][0], orientation[0][1], orientation[0][2])
        translationMag = QVector3D.dotProduct(translationVector, xAxis)/ xAxis.length()
        translationMag = translationMag * xScale * 200
        grabberTransform = self.grabberElement.transform()
        grabberTransform.translate(translationMag, 0, 0)
        grabberPos = grabberTransform.column(3).toVector3D()

        max = 0
        for i in range(2):
            edge = self.currentEdgePair[i]
            startPos = edge.getStartPos3D()
            startPos = QVector3D(startPos[0], startPos[1], startPos[2])
            endPos = edge.getEndPos3D()
            endPos = QVector3D(endPos[0], endPos[1], endPos[2])
            distV = endPos - startPos
            if distV.length() > max:
                max = distV.length()
        max = max/2
        edgePairCenter = self.currentEdgePair.getCenterPoint3D()
        edgePairCenter = QVector3D(edgePairCenter[0], edgePairCenter[1], edgePairCenter[2])

        difference = grabberPos - edgePairCenter
        if max < difference.length():
            col = edgePairCenter.toVector4D()
            col.setW(1)
            grabberTransform.setColumn(3, col)
            if translationMag > 0:
                self.selectedGrabber.showDirectionArrow(1)
            else:
                max = -max
                self.selectedGrabber.showDirectionArrow(2)                

            grabberTransform.translate(max, 0, 0)
            self.grabberElement.setTransform(grabberTransform)
        else:
            self.grabberElement.translate(translationMag, 0, 0, local=True)
        self.grabberElement.update()
        self.paintGL()
Beispiel #10
0
    def move(self, point, quat):
        """Move trackball"""
        if not self._pressed:
            return

        currentTime = QTime.currentTime()
        msecs = self._lastTime.msecsTo(currentTime)
        if msecs <= 20:
            return

        if self._mode == self.TrackballMode.Planar:

            delta = QLineF(self._lastPos, point)
            self._angularVelocity = 180.0 * delta.length() / (math.pi * msecs)
            self._axis = QVector3D(-delta.dy(), delta.dx(), 0.0).normalized()
            self._axis = quat.rotatedVector(self._axis)
            self._rotation = QQuaternion.fromAxisAndAngle(self._axis, 180.0 / math.pi * delta.length()) * self._rotation

        elif self._mode == self.TrackballMode.Spherical:

            lastPos3D = QVector3D(self._lastPos.x(), self._lastPos.y(), 0.0)
            sqrZ = 1.0 - QVector3D.dotProduct(lastPos3D, lastPos3D)
            if sqrZ > 0:
                lastPos3D.setZ(math.sqrt(sqrZ))
            else:
                lastPos3D.normalize()

            currentPos3D = QVector3D(point.x(), point.y(), 0.0)
            sqrZ = 1.0 - QVector3D.dotProduct(currentPos3D, currentPos3D)
            if sqrZ > 0:
                currentPos3D.setZ(math.sqrt(sqrZ))
            else:
                currentPos3D.normalize()

            self._axis = QVector3D.crossProduct(lastPos3D, currentPos3D)
            angle = 180.0 / math.pi * math.asin(math.sqrt(QVector3D.dotProduct(self._axis, self._axis)))

            self._angularVelocity = angle / msecs
            self._axis.normalize()
            self._axis = quat.rotatedVector(self._axis)
            self._rotation = QQuaternion.fromAxisAndAngle(self._axis, angle) * self._rotation

        self._lastPos = point
        self._lastTime = currentTime
Beispiel #11
0
 def mapToSphere(self, x, y, width, height):
     x, y, z = Camera.devicePortCoordinates(x, y, width, height)
     length = QVector3D.dotProduct(QVector3D(x, y, 0), QVector3D(x, y, 0))
     z = 0
     if length <= 1.0:
         z = math.sqrt(1.0 - length)  # 1.0 is the radius of the ball
         pos = QVector3D(-x, y, z)
     else:
         pos = QVector3D(-x, y, z).normalized()
     return pos
Beispiel #12
0
 def angle_between(v1, v2):
     """
     Returns angle in radians between vector v1 and vector v2.
     
     @param v1
     Vector 1 of class QVector3D
     
     @param v2
     Vector 2 of class QVector3D
     """
     return math.acos(QVector3D.dotProduct(v1, v2) / (v1.length() * v2.length()))
Beispiel #13
0
def reflect(I, N):
    """ Calculates reflection direction using:
        I - 2.0 * dot(N, I) * N.
    :param I:  QVector3D incident vector
    :param N:  QVector3D normal vector
    :return:
            QVector3D vector reflection direction
    """
    Nnorm = N.normalize()
    R = I - 2.0 * QVector3D.dotProduct(I, N) * N
    return R.normalized()
Beispiel #14
0
 def dielectric(self, obj_hit, ray, t):
     p = ray.e + ray.d * t
     n = obj_hit.material.n
     normal = obj_hit.normal_at(p)
     reflection_refraction_ray_direction = reflect(ray.d, normal)
     if QVector3D.dotProduct(ray.d, normal) < 0:
         refraction_ray_dir = refract(ray.d, normal, n)[1]
         cos_theta = QVector3D.dotProduct(-ray.d, normal)
         kr = kg = kb = 255
     else:
         a = 1.57
         kr = math.exp(-math.log(a) * t)
         kg = math.exp(-math.log(a) * t)
         kb = math.exp(-math.log(a) * t)
         is_ray_refracted, refraction_ray_dir = refract(
             ray.d, -normal, n / 0.5)
         if is_ray_refracted:
             cos_theta = QVector3D.dotProduct(refraction_ray_dir, normal)
         else:
             reflection_color = QVector3D(kr, kg, kb)
             color = self.hit(Ray(p, reflection_refraction_ray_direction),
                              10000)[1]
             return reflection_color * color.color
     R0 = ((n - 1) * (n - 1)) / ((n + 1) * (n + 1))
     R = R0 + (1 - R0) * (1 - cos_theta)**5
     reflection_object = self.hit(
         Ray(p, reflection_refraction_ray_direction), 10000)[1]
     reflection_object2 = self.hit(Ray(p, refraction_ray_dir), 10000)[1]
     if reflection_object and reflection_object2:
         return R * reflection_object.shader.color + (
             1 - R) * reflection_object2.shader.color + obj_hit.shader.color
     if reflection_object and not reflection_object2:
         return R * reflection_object.shader.color + obj_hit.shader.color
     if reflection_object2 and not reflection_object:
         return (1 -
                 R) * reflection_object2.shader.color + obj_hit.shader.color
Beispiel #15
0
 def compute(self, point, object, light, camera):
     """ Compute light for matte shader
                   :param point:  QVector3D point at point t
                   :param object:  Primitive object that got hit
                   :param light:  Light
                   :param camera: Camera
                   :return:
                       QVector3D with calculated value for lambert
            """
     diffuse_Color = QVector3D(0.5, 0.5, 0.5)
     diffuse_coefficient = 0.9
     light_dir = light.direction(point)  # L
     normal = object.normal_at(point)  # N
     NdotL = QVector3D.dotProduct(light_dir, normal)
     lambert = diffuse_coefficient * diffuse_Color * light.color * max(NdotL, 0.0)
     return lambert
Beispiel #16
0
 def compute(self, point, object, light, camera):
     """ Compute light for matte shader
                   :param point:  QVector3D point at point t
                   :param object:  Primitive object that got hit
                   :param light:  Light
                   :param camera: Camera
                   :return:
                       QVector3D with calculated value for lambert
            """
     specular_color = QVector3D(1.0, 1.0, 1.0)
     light_dir = light.direction(point)  # L
     normal = object.normal_at(point)  # N
     eye_dir = (camera.position - point).normalized()  # V
     half_vector = (eye_dir + light_dir).normalized()
     NdotH = QVector3D.dotProduct(normal, half_vector)
     specular = light.color * specular_color * pow(max(NdotH, 0.0), light.shininess)
     return specular
Beispiel #17
0
 def compute(self, point, object, light, camera):
     """ Compute light for Blinn-Phong shader
            :param point:  QVector3D point at point t
            :param object:  Primitive object that got hit
            :param light:  Light
            :param camera: Camera
            :return:
                QVector3D with calculated value for lambert + specular
     """
     specular_color = QVector3D(1.0, 1.0, 1.0)
     ambient_color = QVector3D(0.2,0.2,0.2)
     light_dir = light.direction(point)  # L
     normal = object.normal_at(point)  # N
     eye_dir = (camera.position - point).normalized()  # V
     R = reflect(light_dir, normal)  # R
     NdotR = QVector3D.dotProduct(-R, normal)
     specular = light.color * specular_color * pow(max(NdotR, 0.0), light.shininess)
     return Matte(self.color).compute(point, object, light, camera) + specular
Beispiel #18
0
def refract(d, n, new_index_of_refraction):
    """
    :param d: eye dir
    :param n: normal
    :param new_index_of_refraction:
    :return:
    """
    original_index_of_refraction = 1.0  # air
    refractive_index = original_index_of_refraction / new_index_of_refraction
    DdotN = QVector3D.dotProduct(d, n)
    inside_phi = 1 - (refractive_index * refractive_index * (1 -
                                                             (DdotN * DdotN)))
    t = None
    is_ray_refracted = False
    # if negative there's no ray, all of the energy is reflected. known as total internal reflection
    if inside_phi > 0.0:
        cos_phi = math.sqrt(inside_phi)
        t = refractive_index * (d - n * DdotN) - n * cos_phi
        is_ray_refracted = True
    return is_ray_refracted, t
    def __init__(self):

        self.center = QVector3D(0.5, 0.5, 0.5)
        self.eye = QVector3D(0, 0, 3)

        lookDirection = (self.center - self.eye).normalized()
        self.up = QVector3D(0, 0, 1)
        self.up = (self.up - lookDirection * QVector3D.dotProduct(lookDirection, self.up)).normalized()

        self.clearColor = [0.3, 0.25, 0.35, 1.0]
        self.selectedLandscapeCell = (float("inf"), float("inf"))

        self.lightSourcePosition = QVector3D(1.5, 1.5, 2.7)
        self.lastMousePosition = QPoint()

        try:
            self.n, self.m, self.landscapeHeightsMatrix = self.loadLandscapeHeightsMatrix()
        except:
            self.n, self.m = 10, 10
            self.landscapeHeightsMatrix = self.generateLandscapeHeightsMatrix()
        self.generateWaterHeightsMatrix()
Beispiel #20
0
def _ortho_look_at_custom(eye_x: float, eye_y: float, eye_z: float,
                          center_x: float, center_y: float, center_z: float,
                          up_x: float, up_y: float, up_z: float):
    """
    Return the ortho projection matrix

    :param eye_x:
    :param eye_y:
    :param eye_z:
    :param center_x:
    :param center_y:
    :param center_z:
    :param up_x:
    :param up_y:
    :param up_z:
    :return: the matrix
    """
    eye_base = QVector3D(eye_x, eye_y, eye_z)
    up = QVector3D(up_x, up_y, up_z)
    center = QVector3D(center_x, center_y, center_y)
    eye = eye_base - center
    right = QVector3D.crossProduct(up, eye)
    up = QVector3D.crossProduct(eye, right)
    z_axis = QVector3D(0, 0, 1)

    r, theta, phi = cart2spher(eye_x, eye_y, eye_z)
    angle = math.pi / 2 - theta
    angle2 = phi + math.pi
    base_up = QVector3D(*spher2cart(r, angle, angle2))
    # print("up", up)
    # print("base_up",base_up)
    dot_up_base_up = QVector3D.dotProduct(up, base_up)
    if math.isclose(dot_up_base_up, 0):
        angle_up_base_up = 0
    else:
        cos_up_base_up = round(dot_up_base_up / base_up.length() / up.length(),
                               5)
        # print("cos_up_base_up",cos_up_base_up)
        cross_up_base_up = QVector3D.crossProduct(up, base_up)
        if QVector3D.dotProduct(cross_up_base_up, eye) < 0:
            angle_up_base_up = math.acos(cos_up_base_up)
        else:
            angle_up_base_up = math.pi * 2 - math.acos(cos_up_base_up)
    cos_x = math.cos(angle_up_base_up)
    sin_x = math.sin(angle_up_base_up)
    m_x = QMatrix4x4(1, 0, 0, 0, 0, cos_x, -sin_x, 0, 0, sin_x, cos_x, 0, 0, 0,
                     0, 1)
    # print("angle",math.degrees(angle_up_base_up))
    # print(m_x)

    # 求视线矢量到z轴的投影
    eye_project_z_factor = QVector3D.dotProduct(
        eye, z_axis) / z_axis.lengthSquared()
    eye_project_z = z_axis * eye_project_z_factor
    # 视线矢量在xy平面上的投影
    eye_project_xy = eye - eye_project_z
    # 求视线矢量与xy平面的夹角
    cos_eye_and_xy = QVector3D.dotProduct(
        eye, eye_project_xy) / eye_project_xy.length() / eye.length()
    angle_eye_and_xy = math.acos(cos_eye_and_xy)
    if eye.z() < 0:
        angle_eye_and_xy = -angle_eye_and_xy

    # 求 视线矢量在xy平面上的投影 与 x轴夹角
    # x_axis = QVector3D(1, 0, 0)
    # cos_project_xy_and_x = QVector3D.dotProduct(x_axis, eye_project_xy) / x_axis.length() / eye_project_xy.length()
    # angle_project_xy_and_x = math.acos(cos_project_xy_and_x)
    # if eye_project_xy.y() < 0:
    #     angle_project_xy_and_x = 2 * math.pi - angle_project_xy_and_x
    angle_project_xy_and_x = phi

    # print("eye", eye)
    # print("eye_project_z", eye_project_z)
    # print("eye_project_xy", eye_project_xy)
    # print(angle_eye_and_xy)
    # print(angle_project_xy_and_x)

    # 绕y轴逆时针旋转 angle_eye_and_xy 度
    cos_1 = math.cos(angle_eye_and_xy)
    sin_1 = math.sin(angle_eye_and_xy)
    m_y = QMatrix4x4(cos_1, 0, sin_1, 0, 0, 1, 0, 0, sin_1, 0, cos_1, 0, 0, 0,
                     0, 1)
    # 绕z轴顺时针转 angle_project_xy_and_x 度
    cos_2 = math.cos(-angle_project_xy_and_x)
    sin_2 = math.sin(-angle_project_xy_and_x)
    m_z = QMatrix4x4(-cos_2, sin_2, 0, 0, sin_2, cos_2, 0, 0, 0, 0, 1, 0, 0, 0,
                     0, 1)

    m_ortho = QMatrix4x4(0, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 1)

    return m_ortho * m_x.transposed() * m_y.transposed() * m_z.transposed()