Beispiel #1
0
 def find_connect_point(self, iInfo, ray_proj, triangle_dic):
     """
         find vector on intersection point, called in connect()
     """
     #set small number for floating point problem
     small_num = 0.000001
     ###find connecting point
     t = -1
     triangle = self.model.triangles[iInfo.triangleID]
     rays=[euclid.Ray3(triangle.vertices[0],triangle.vertices[1]),\
           euclid.Ray3(triangle.vertices[1],triangle.vertices[2]),\
           euclid.Ray3(triangle.vertices[2],triangle.vertices[0])]
     #iterate edges in triangle to find closest intersection for ray_proj
     #and update iInfo
     ray_id = 0
     for i, ray in enumerate(rays):
         print("ray" + str(i) + ":")
         (t_temp, iInfo_temp) = self.line_intersect(ray_proj, ray)
         if (t_temp < t or t < 0) and t_temp > small_num:
             print(t_temp)
             t = t_temp
             iInfo.icoordinate = iInfo_temp.icoordinate
             ray_id = i
     #iterate self.model.triangles to find next triangleID
     for i, tri_temp in enumerate(self.model.triangles):
         #find triangle that consists of two vertice to build ray
         #and find triangle whose ID is not yet in triangle_dic
         if triangle.vertex_indices[
                 ray_id] in tri_temp.vertex_indices and triangle.vertex_indices[
                     (ray_id + 1) %
                     3] in tri_temp.vertex_indices and i not in triangle_dic:
             iInfo.triangleID = i
             break
     return (t, ray_id)
Beispiel #2
0
 def intersect_on_new_model(self):
     for prev_iInfo in self.prev_iInfos:
         ray = euclid.Ray3(prev_iInfo.icoordinate,
                           -prev_iInfo.cutting_vector)
         iInfo = IntersectionInfo()
         mx = -1
         iInfo_temp = IntersectionInfo()
         #            ###find nearest intersection
         #            for i,triangle in enumerate(self.model.triangles):
         #                (isIntersect,iInfo_temp)=triangle.intersect(ray);
         #                if isIntersect:
         #                    #print("intersection_temp in outer loop")
         #                    #print(iInfo_temp)
         #                    d=(iInfo_temp.icoordinate-ray.p).magnitude_squared();
         #                    if mx==-1 or d<mx:
         #                        iInfo=iInfo_temp;
         #                        iInfo.triangleID=i;
         #                        mx=d;
         ###find farest intersection
         for i, triangle in enumerate(self.model.triangles):
             (isIntersect, iInfo_temp) = triangle.intersect(ray)
             if isIntersect:
                 #print("intersection_temp in outer loop")
                 #print(iInfo_temp)
                 d = (iInfo_temp.icoordinate - ray.p).magnitude_squared()
                 if d > mx:
                     iInfo = iInfo_temp
                     iInfo.triangleID = i
                     mx = d
         if mx > -1:
             if len(self.iInfos) > 0:
                 self.connect(self.iInfos[-1], iInfo)
             self.iInfos.append(iInfo)
             self.points.extend((iInfo.icoordinate[0], iInfo.icoordinate[1],
                                 iInfo.icoordinate[2]))
Beispiel #3
0
 def build_ray(self, mouse_x, mouse_y, button, w, h):
     """
         build ray: from mouse position to a 3D ray (in world coordinate) starting from camera eye position
     """
     #viewport coordinates to normalized device coordinates
     x = 2 * mouse_x / w - 1
     y = 2 * mouse_y / h - 1
     #call projection matrix and model view matrix
     M_proj = (gl.GLfloat * 16)()
     M_modelview = (gl.GLfloat * 16)()
     gl.glGetFloatv(gl.GL_PROJECTION_MATRIX, M_proj)
     gl.glGetFloatv(gl.GL_MODELVIEW_MATRIX, M_modelview)
     M_proj = euclid.Matrix4.new(*(list(M_proj)))
     M_modelview = euclid.Matrix4.new(*(list(M_modelview)))
     M_proj_inversed = M_proj.inverse()
     M_modelview_inversed = M_modelview.inverse()
     #homogeneous clip coordinates
     vector_clip = euclid.Vector3(x, y, -1)
     #eye coordinates
     vector_eye = M_proj_inversed * vector_clip
     vector_eye = euclid.Vector3(vector_eye[0], vector_eye[1], -1)
     #world coordinates
     vector_world = M_modelview_inversed * vector_eye
     vector_world.normalize()
     #        print(vector_world);
     #        print(M_modelview_inversed);
     #build ray, starting point is camera eye position
     ray = euclid.Ray3(
         euclid.Point3(M_modelview_inversed[12], M_modelview_inversed[13],
                       M_modelview_inversed[14]), vector_world)
     return ray
Beispiel #4
0
 def getColor(self, intersect, obj, intensity):
     # DEBUG: no shadows
     #return RayColor(intensity, obj.getColor(intersect))
     # get a ray from the intersect to the source of light
     vectorToLight = self.light - intersect
     rayToLight = euclid.Ray3(intersect, vectorToLight)
     for o in self.objects:
         i = o.intersect(rayToLight)
         if obj == o:
             if type(i) == euclid.Point3:
                 # often means intercept with self
                 continue
             elif not i:  # is None
                 continue  # no intercept
             # otherwise find penetration
             lenI = abs(i)
             distances.append(lenI)
             if lenI < 0.2:
                 continue
         if i:  # intersect, so is in shadow
             return RayColor(intensity, (0, 0, 0))
     # otherwise not in shadow
     # find intensity depending on angle to light.
     if type(obj) == RaycastingPlane:
         normal = obj.shape.n
     elif type(obj) == RaycastingSphere:
         normal = (intersect - obj.shape.c).normalize()
     strength = abs(vectorToLight.normalized().dot(normal))
     return RayColor(intensity * strength, obj.getColor(intersect))
Beispiel #5
0
def reflect(point, obj, ray):
    if type(obj) == RaycastingSphere:
        n = (point - obj.c).normalized()
        v = -ray.v.normalized()
    elif type(obj) == RaycastingPlane:
        n = obj.shape.n
        v = -ray.v.normalized()
    else:
        raise TypeError("Unknown shape")
    return euclid.Ray3(point, 2 * n.dot(v) * n - v)
Beispiel #6
0
    def selection_ray(self, x, y):
        self.setup()
        model_view = (GLdouble * 16)()
        glGetDoublev(GL_MODELVIEW_MATRIX, model_view)
        projection = (GLdouble * 16)()
        glGetDoublev(GL_PROJECTION_MATRIX, projection)
        viewport = (GLint * 4)()
        glGetIntegerv(GL_VIEWPORT, viewport)

        x1, y1, z1 = GLdouble(), GLdouble(), GLdouble()
        x2, y2, z2 = GLdouble(), GLdouble(), GLdouble()
        gluUnProject(x, y, 0, model_view, projection, viewport, x1, y1, z1)
        gluUnProject(x, y, 1, model_view, projection, viewport, x2, y2, z2)
        ray = euclid.Ray3(euclid.Point3(x1.value, y1.value, z1.value),
                          euclid.Point3(x2.value, y2.value, z2.value))
        ray.v.normalize()
        self.reset()
        return ray
Beispiel #7
0
    def generateRays(self, startline=0, endline=None):
        """ 
            generate all the rays for the pixels in the screen.
            each ray starts from the camera's position and goes through the screen.

            The camera is originally at 0,0,0; and the screen originally is at
            A(f, .5w, .5h);
            B(f, .5w, -.5h);
            C(f, -.5w, -.5h);
            D(f, -.5w, .5h);

            Apply the transformation matrix for rotation to easily get the 
            actual screen position! don't do complex math if somebody already 
            did it for you
        """
        if not endline:
            endline = self.imageh
        A = Point3(self.focallength, 0.5 * self.screenw, 0.5 * self.screenh)
        B = Point3(self.focallength, 0.5 * self.screenw, -0.5 * self.screenh)
        # C = Point3(self.focallength, -0.5*self.screenw, -0.5*self.screenh)
        D = Point3(self.focallength, -0.5 * self.screenw, 0.5 * self.screenh)

        # rotate & translate the ABCD vectors
        A = self.rotation * A
        B = self.rotation * B
        D = self.rotation * D
        A += self.translation
        B += self.translation
        D += self.translation

        # unit vector for screen width, nx, is A to D divided by image width
        nx = D - A
        nx /= self.imagew
        # unit vector for screen height, ny, is A to B divided by image height
        ny = B - A
        ny /= self.imageh

        OA = A - self.translation  # the first ray. will be modified to find the various rays
        for x in range(self.imagew):
            for y in range(startline, endline):
                # This is the initial ray for searching for collisions.
                vector = OA + (0.5 + x) * nx + (0.5 + y) * ny
                ray = euclid.Ray3(self.translation, vector)
                yield ray, x, y
Beispiel #8
0
def main():
    T = int(raw_input())
    for case in xrange(T):
        N = int(raw_input())
        position = euclid.Vector3()
        velocity = euclid.Vector3()
        for _ in xrange(N):
            x, y, z, vx, vy, vz = map(float, raw_input().split())
            position += euclid.Vector3(x, y, z)
            velocity += euclid.Vector3(vx, vy, vz)
        position /= N
        velocity /= N
        if velocity == euclid.Vector3():
            d_min = abs(position - euclid.Point3())
            t_min = 0.
        else:
            position = euclid.Point3(position.x, position.y, position.z)
            ray = euclid.Ray3(position, velocity)
            connection = ray.connect(euclid.Point3())
            d_min = abs(connection)
            t_min = abs(connection.p1 - position) / abs(velocity)
        print 'Case #%d: %1.8f %1.8f' % (case + 1, d_min, t_min)
#        elif data[0] == 'f':
#            vi_1, vi_2, vi_3 = data[1:4]
#            faces.extend((vi_1,vi_2,vi_3))
#point1=[0,0];
#point2=[0,1];
#point3=[1,1];
#point4=[1,0];
#
#x=np.arange(4);
#y=np.array([point1,point2,point3,point4]);
#cs=interpolate.CubicSpline(x,y);
#plt.plot(y[:,0],y[:,1]);
#plt.plot(cs(xs)[:,0],cs(xs)[:,1])
#plt.show()

ray1 = euclid.Ray3(euclid.Point3(0, 0, 0), euclid.Point3(1, 1, 1))
ray2 = euclid.Ray3(euclid.Point3(1, 1, 0), euclid.Point3(1, 1, -0.5))


def line_intersect(ray1, ray2):
    """
        find intersection point between two lines
    """
    small_num = 0.000001
    den = ray2.v.cross(ray1.v)
    d = den.magnitude()
    t = -1
    #if not paralleled
    if d > small_num:
        g = ray2.p - ray1.p
        num = ray2.v.cross(g)
Beispiel #10
0
    def findLightedColor(self, obj, point):
        truecolor = obj.getColor(point)

        # these two for highlights
        angles = []
        spectralAngles = []
        # this for brightness
        distances = []
        # this for intersection tests
        intersected = []

        # normal vector
        Vn = obj.normal(point).normalize()
        # line to viewer
        Vv = (point - self.camera.translation).normalize()

        # Try to draw a line to a light source
        for light in self.lights:
            ray = euclid.Ray3(point, light.position - point)
            canDoLight = True
            for thing in self.objects:
                inter = thing.intersect(ray)
                # if it's an intersection, no light!
                if isinstance(inter, euclid.Point3):
                    if inter:
                        if thing != obj:
                            canDoLight = False
                            intersected.append(True)
                else:
                    if inter and inter.length > 0.05:
                        if thing.getTransparency() > 0.0:
                            continue
                        else:
                            canDoLight = False
                            intersected.append(True)
                            break
            # spectral reflection stuff
            if canDoLight:
                intersected.append(False)

                N = obj.normal(point)
                N.normalize()
                dot = N.dot(ray.v.normalized())
                angles.append(dot)

                # find reflection vector & viewer vector angle
                Vl = (light.position - point)
                distances.append(len(Vl))
                Vl.normalize()
                # must rotate L around axis N x L, equal to angle.
                N_L_angle = math.acos(Vl.dot(N))
                axis = Vl.cross(N)
                rot = euclid.Quaternion.new_rotate_axis(N_L_angle * 2, axis)
                Reflection = rot * Vl
                # get angle between viewer and reflection
                spectralAngles.append(Reflection.dot(Vv))

        shadowed = True
        for tf in intersected:
            shadowed &= tf

        if shadowed:
            return (0, 0, 0)

        angle = max(angles)  # The greatest angle wins
        distance = min(distances)  # smallest distance
        # but wait, there's more! Find the spectral lighting angle
        spectral = max(spectralAngles)
        # lighted color
        lightedcolor = truecolor  #lerp((0,0,0), truecolor, 7 / distance**2)

        # If the material is more reflective, the highlight is smaller & more intense
        # but for now, if the angle is above a threshold make it white
        if spectral < -0.985:
            return lerp(lightedcolor, (255, 255, 255),
                        abs((spectral + 0.985) * 100)**3)
        return lerp((0, 0, 0), lightedcolor, angle)
Beispiel #11
0
    def connect(self, iInfo_start, iInfo_end):
        """
            find connecting points along surface
        """
        #dictionay to keep track of triangle gone through
        triangle_dic = {}
        print("=========================")
        print("start ID is")
        print(iInfo_start.triangleID)
        print("end ID is")
        print(iInfo_end.triangleID)

        iInfo = iInfo_start.copy()
        iInfo_prev = iInfo.copy()
        counter = 0

        while (iInfo.triangleID != iInfo_end.triangleID):

            triangle_dic[iInfo.triangleID] = counter
            print("triangle Info:")
            print("triangleID is " + str(iInfo.triangleID))
            print("vertices:")
            print(self.model.triangles[iInfo.triangleID].vertex_indices)
            print(self.model.triangles[iInfo.triangleID].vertices)

            counter += 1
            #check if triangle normal is too close to previous triangle normal
            #we want to continue the vector direction if the two normals are similar
            if iInfo_prev.normal.dot(
                    iInfo.normal) / iInfo.normal.magnitude_squared() > 0.9:
                v = iInfo_end.icoordinate - iInfo_prev.icoordinate
            else:
                v = iInfo_end.icoordinate - iInfo.icoordinate
            #get projected vector of v on triangle
            v_proj = v - v.dot(iInfo.normal) / iInfo.normal.magnitude_squared(
            ) * (iInfo.normal)
            v_proj.normalize()
            #build ray with projected vector
            ray_proj = euclid.Ray3(iInfo.icoordinate, v_proj)
            print("ray_proj is:")
            print(ray_proj)
            #keep track of previous iInfo
            iInfo_prev = iInfo.copy()
            #find intersection with t and ray_id, iInfo passed by reference
            t, ray_id = self.find_connect_point(iInfo, ray_proj, triangle_dic)
            print('t is:')
            print(t)
            #check if t < 0, which is intersection in wrong direction
            if (t < 0):
                print("error: connecting point in wrong direction")
                break
#            #check if intersection is inside triangle
#            if not self.model.triangles[iInfo.triangleID].inside_check(iInfo.icoordinate):
#                print("error: connecting point is not in triangle")
#                print("wrong connecting point:")
#                print(iInfo.icoordinate)
#                break;
#check if triangle found is correct
            if iInfo.triangleID in triangle_dic:
                print("error: wrong triangle found")
                break
            #update iInfo.normal
            iInfo.normal = self.model.triangles[iInfo.triangleID].plane.n

            print('connecting point' + str(counter) + " inside triangle" +
                  str(iInfo.triangleID))
            print(iInfo.icoordinate)

            iInfoTemp = iInfo.copy()
            self.iInfos.append(iInfoTemp)
            self.points.extend((iInfo.icoordinate[0], iInfo.icoordinate[1],
                                iInfo.icoordinate[2]))
Beispiel #12
0
 scene.objects.append(RaycastingSphere(euclid.Point3(-50, 0, 0), 2.0))
 scene.objects[-1].reflectionIndex = 0.2
 scene.objects.append(RaycastingSphere(euclid.Point3(-55, 2, 0), 1.0))
 scene.objects[-1].reflectionIndex = 0.2
 scene.objects.append(RaycastingSphere(euclid.Point3(-55, 8, -2), 3.0))
 scene.objects[-1].reflectionIndex = 0.1
 scene.objects.append(RaycastingSphere(euclid.Point3(-55, 2, -5), 2.0))
 scene.objects[-1].color = (255, 0, 0)
 """scene.objects.append(RaycastingPlane((0,0,0), 
     euclid.Point3(0, 0, 5)))
 scene.objects[-1].reflectionIndex = 0.2"""
 im = Image.new("RGB", (imgW, imgH), (0, 0, 255))
 pixels = im.load()
 for x, y, point in scene.camera.getPixelCoords(imgW, imgH):
     color = scene.trace(
         euclid.Ray3(scene.camera.focus, point - scene.camera.focus), 1.0,
         5)
     if color.__class__.__name__ == "RayColor":
         pixels[x, y] = color.toRGB()
     elif type(color) == tuple:
         pixels[x, y] = color
     else:
         raise TypeError("unknown color type: " + str(type(color)) +
                         " containing:\n" + repr(color))
 if not len(distances) < 2:
     print "average:" + str(
         reduce(lambda x, y: x + y, distances) / float(len(distances)))
     print "min:" + str(reduce(lambda x, y: x if x < y else y, distances))
     distances.insert(0, 0.0)
     print "number of 0.0s:" + str(
         reduce(lambda x, y: x + 1 if y == 0.0 else x, distances))