Ejemplo n.º 1
0
    def _gen_texture(self, address, resolution=None):
        texture_name = None

        # If the a texture for the address has already been generated
        if address in self._generated_textures:
            texture_name = self._generated_textures[address]

        # Otherwise generate a new texture
        else:

            face = CubeSphereMap.get_address_face(address)
            level = len(address)

            name = "planet_texture"
            size = self._increments #256

            if not resolution is None:
                size = resolution

            data = None
            format_size = 4
            pitch = size * format_size
            format = "RGBA"

            #b = datetime.now()

            # Generate the data for the texture
            
            #perlin = Perlin(12345)

            # Generate sphere coordinates for the address
            # verts = []
            # for x in range(size):
            #     o = ""
            #     x /= float(size)

            #     for y in range(size):
            #         y /= float(size)
            #         # verts.append( Vector3(x, y, 0.5) )
            #         coord = CubeSphereMap.get_sphere_vector(x, y, face) * self._radius
            #         # #print coord
            #         verts.append( coord )

            #         o += " (%1.2f, %1.2f)" % (x, y)
            #verts = self._gen_verts(address)
            # mesh = self._generated_meshes[address]
            # verts = mesh.vertices
                
                #print o

            #ignoring faces
            #print verts
            # as image data is loaded from bottom-left to top-right vertex data
            # needs to be transformed as it is generated top-left to bottom-right

            # t_data = []
            # for x in xrange(size-1, -1, -1):
            #     row_start = x * size
            #     row_end = row_start + size
            #     t_data += verts[row_start:row_end]

            # for x in range(size):
            #     row_start = x * size
            #     row_end = row_start + size

                # o = ""
                # for v in verts[row_start:row_end]:
                #     o += " (%1.2f, %1.2f, %1.2f)" % (v.x, v.y, v.z)

            # Generate noise
            #data = [self._noise.ridged_multi_fractal3(v[0], v[1], v[2], 0, 1.0) for v in t_data]
            #data = [self._noise.ridged_multi_fractal3(v[0], v[1], v[2], 0, 1.0) for v in t_data]
            
            # data = [perlin.noise3(v.x, v.x, v.x) * 255.0 for v in verts]

            # first_scale = 8 * self._octaves

            #second_scale = 0.5 * self._octaves
            
            # data = []

            noise = self._generated_noise[address]

            # t_data = []
            # for x in xrange(size-1, -1, -1):
            #     row_start = x * size
            #     row_end = row_start + size
            #     t_data += noise[row_start:row_end]

            # for x in range(size):
            #     row_start = x * size
            #     row_end = row_start + size

            # noise = t_data

            colour_data = []

            #for v in verts:
            # for n in noise:
            for y in range(self._increments):#,-1,-1):
                nv = []
                for x in range(self._increments):#,-1,-1):

                    n = noise[x][y]
                    # # convert the height to a colour value
                    # #height = ( (v.magnitude() - self._radius) / self._max_height ) * 255.0

                    #nv.append(n)

                    # if n > 1.0:
                    #     print "n: %3.2f x: %d y: %d" % ( n, x, y)

                    height = (n * 128.0) + 128.0

                    # #height = 150.0
                    # #print height

                    colour = Preset.white

                    if 200 >= height >= 150:
                        colour = Preset.green
                    elif 150 > height > 100:
                        colour = Preset.yellow
                    elif 100 >= height:
                        colour = Preset.blue
                    
                    # if 50 > height:
                    #     colour = Preset.blue
                    # else:
                    #     colour = Preset.red

                    # if x == 0 or x == self._increments-1:
                    #     colour = Preset.yellow

                    # if y == 0 or y == self._increments-1:
                    #     colour = Preset.green
                    
                    # colour = Preset.red

                    # colour = colour.tinted(Preset.green, (y/float(size)))
                    # colour = colour.tinted(Preset.blue, (x/float(size)))

                    colour_data += [colour.r * 255.0, colour.g * 255.0, colour.b * 255.0, colour.a * 255.0]
                # s = ""
                # for n in noise[x]:
                #     s += "\t%0.3f," % n
                # print s

            #e = datetime.now() - b

            #print "%s Tex Colours Gen time: %3.5f" % (address, e.total_seconds())#(e.seconds +  (e.microseconds / 1000000.0) ) )

            # colour_data = []
            # for n in noise:
            
            #     nv.append(n)

            #     height = (n * 128.0) + 128.0

            #     if 100 > height:
            #         colour = Preset.blue
            #     else:
            #         colour = Preset.red

            #     colour_data += [colour.r * 255.0, colour.g * 255.0, colour.b * 255.0, colour.a * 255.0]

            #b = datetime.now()

            # Transform noise to colour data
            array_data = numpy.array(colour_data, 'f')

            # array_data = numpy.random.random_integers(low=0,
            #                                           high=255,
            #                                           size = (size * size, format_size))

            #array_data *= 255
            # array_data[:,3] = 255
            array_data.shape = -1
            tex_data = (GLubyte * array_data.size)(*array_data.astype('u1'))

            #test_plane = SceneManager.get_instance().current_scene.root.transform.get_child_with_name("test_plane")

            texture_name = "planet_texture_%s" % address
            
            new_planet_texture = GeneratedTexture(name=texture_name, width=size, height=size)
            new_planet_texture.wrapped = False
            new_planet_texture.smoothed = True

            new_planet_texture.set_data(format, pitch, tex_data)

            TextureManager.get_instance().add_texture(new_planet_texture)
            
            #test_plane.node.renderer.material.texture = "planet_texture"
            
            #e = datetime.now() - b

            #print "%s Tex Gen Vid card copy time: %3.5f" % (address, e.total_seconds())#(e.seconds +  (e.microseconds / 1000000.0) ) )

            #new_planet_texture.image.save(texture_name+'.png')

            self._generated_textures[address] = texture_name

        return texture_name
Ejemplo n.º 2
0
    def _gen_verts(self, address):
        bound_min_x, bound_min_z, bound_max_x, bound_max_z, face = CubeSphereMap.get_address_bounds(address)

        verts = []
        noise_x = []

        h_height = self._max_height / 2.0

        for i in xrange(self._increments + 1):
            #c = i * (1.0 / self._increments)
            c = (i * ( (bound_max_x - bound_min_x) / float(self._increments) ) ) + bound_min_x
            nv = []

            noise_y = []
            for j in xrange(self._increments + 1):
                #r = j * ( 1.0 / self._increments )
                r = (j * ( (bound_max_z - bound_min_z) / float(self._increments) ) ) + bound_min_z
                
                p = CubeSphereMap.get_sphere_vector(c, r, face) * self._radius
                
                n = Vector3()#c, r, -1) * self._radius
                if True:
                
                    u = c
                    v = r
                    u = (u * 2.0) - 1.0
                    v = (v * 2.0) - 1.0
                    if face == CubeSphereMap.BACK:
                        n = Vector3(-u, -v, -1) * self._radius
                    elif face == CubeSphereMap.LEFT:
                        n = Vector3(-1, -v, u) * self._radius
                    elif face == CubeSphereMap.RIGHT:
                        n = Vector3(1, -v, -u) * self._radius
                    elif face == CubeSphereMap.TOP:
                        n = Vector3(u, 1, v) * self._radius
                    elif face == CubeSphereMap.BOTTOM:
                        n = Vector3(u, -1, -v) * self._radius
                    elif face == CubeSphereMap.FRONT:
                        n = Vector3(u, -v, 1) * self._radius
                else:
                # Adjust the surface level using noise
                    n = p.copy()

                # if face == CubeSphereMap.RIGHT:
                #     n.x = self._radius
                # elif face == CubeSphereMap.LEFT:
                #     n.x = -self._radius
                # elif face == CubeSphereMap.TOP:
                #     n.y = self._radius
                # elif face == CubeSphereMap.BOTTOM:
                #     n.y = -self._radius
                # elif face == CubeSphereMap.FRONT:
                #     n.z = self._radius
                # elif face == CubeSphereMap.BACK:
                #     n.z = -self._radius

                frac = self._get_noise(n)
                
                # if i == 0 and j == 0:
                #     frac = 5.0
                # if i == self._increments and j == self._increments:
                #     frac = 10.0

                # if j in [4, 6, 8, 20, 25, 30]:
                #     frac = 1
                # else:
                #     frac = -1

                # if i in [5,6,20,21]:
                #     frac = 1

                #noise.append(frac)
                noise_y.append(frac)

                nv.append(frac)
                #h = noise * self._max_height
                h = (frac * h_height ) + h_height
                
                # Increase the surface vector by the noise value
                n = p.normalized()
                n *= h

                p += n

                verts.append((p.x, p.y, p.z))
            # s = ""
            # for n in nv:
            #     s += "\t%0.3f," % n
            # print s
            noise_x.append(noise_y)
        return verts, noise_x
Ejemplo n.º 3
0
    def gen_mesh(self, address):
        mesh = None

        if address in self._generated_meshes:
            mesh = self._generated_meshes[address]

        else:

            #b = datetime.now()

            bound_min_x, bound_min_z, bound_max_x, bound_max_z, face = CubeSphereMap.get_address_bounds(address)

            verts, noise = self._gen_verts(address)
                    
            faces = []
            v = 0
            for c in xrange(self._increments):
                for r in xrange(self._increments):
                    bl = v + c + r
                    tl = bl + 1
                    tr = tl + self._increments + 1
                    br = tr - 1
                    
                    faces.append((bl, tl, tr))
                    faces.append((bl, tr, br))
                v = v + self._increments
            
            tex_coords = []
            
            bound_width = bound_max_x - bound_min_x
            bound_height = bound_max_z - bound_min_z

            for i in xrange(self._increments + 1):
                # Generate 0.0 - 1.0 local uv coords
                c = i * (1.0 / (self._increments))

                # generate global uv coords i.e. 0.2 - 0.3
                #c = (i * (bound_width / float(self._increments) ) ) + bound_min_x
                tc = []

                for j in xrange(self._increments + 1):
                    # local
                    r = j * ( 1.0 / (self._increments))
                    
                    # global
                    #r = (j * ( bound_height / float(self._increments) ) )+ bound_min_z
                    
                    #y = j/self._increments
                    p = [c,r] 
                    tex_coords.append(p)
                    tc.append(p)

                # s = ""
                # for n in tc:
                #     s += "\t(%0.3f,%0.3f)," % (n[0], n[1])
                # print s
            #print "%s Vertex gen time: %3.5f" % (address, (datetime.now() - b).total_seconds())

            b = datetime.now()

            # Build a mesh
            mesh = Mesh(verts, faces, Preset.green, tex_coords=tex_coords)
            self._generated_meshes[address] = mesh
            self._generated_noise[address] = noise

            #print "%s Mesh obj Gen time: %3.5f" % (address, (datetime.now() - b).total_seconds())
        
        return mesh
Ejemplo n.º 4
0
    def update_sphere(self):
        
#        start = datetime.now()
        
        if (datetime.now() - self._last_time).total_seconds() > 0.1:
        
            if self._ui.track_camera:
            
                if self._camera is None:
                    self._camera = SceneManager.get_instance().current_scene.active_camera

                # Store the camera pos for access by the quad children
                self._camera_pos = self._camera.node_parent.transform.position - self.transform.position

                self._camera_pos_sc = CubeSphereMap.get_cube_coord(self._camera_pos.x, self._camera_pos.y, self._camera_pos.z) 
                
                self._line.line_to(self._camera_pos)


                if self._ui.planet_camera:
                    # Check if the camera has intersected the planet.
                    if self._camera_pos.magnitude() < (self._radius + self._max_height):
                        u = self._camera_pos_sc.x
                        v = self._camera_pos_sc.y
                        face = self._camera_pos_sc.face
                        self._camera.node_parent.transform.position = CubeSphereMap.get_sphere_position(u, v, face, (self._radius + self._max_height))

                
                # Reset the number of splits
                self._num_splits = 0
                #print "Resetting splits"
                
                # If the camera has moved a sufficient distance to warrant an update
    #            if self._last_camera_pos is None:
    #                self._last_camera_pos = self._camera_pos
    #            dist = self._last_camera_pos - self._camera_pos 
    #            if dist.magnitude() > 1.0:
                    
                # Calc the horizon
                altitude = self._camera_pos.magnitude()
                horizon_altitude = max([altitude-self.radius, self.max_height])
                self._horizon = math.sqrt(horizon_altitude * horizon_altitude + 2.0 * horizon_altitude * self._radius)
                
                if True:
                    # Update all of the sides of the cube/sphere
                    for child in self.transform.children:
                        if isinstance(child.node, SphereQuad):
                            child.node.update_surface()
                        
                self._last_camera_pos = self._camera_pos
                        
                self._last_time = datetime.now()
                
                # Update the UI with the camera pos
    #            self._ui.rel_camera_pos = self._camera_pos
    #            self._ui.camera_pos = self._camera_pos_sc

                if not self._camera_pos_sc is None:
                    pos = CubeSphereMap.get_sphere_vector(self._camera_pos_sc.x, self._camera_pos_sc.y, self._camera_pos_sc.face)
                    pos.normalize()
                    pos *= (self._radius / 1.9)
                    self._camera_gizmo.transform.position = pos
Ejemplo n.º 5
0
    def update_surface(self):
        
        pos = self._sphere_parent.camera.node_parent.transform.position
        
        # Get the distances of the camera from the quads
        # This needs to be updated in future to handle transform applied to the planet
        # i.e. rotation and position
        distances = [pos.distance(self._child_pos[QuadName.TL]),
                     pos.distance(self._child_pos[QuadName.TR]),
                     pos.distance(self._child_pos[QuadName.BR]),
                     pos.distance(self._child_pos[QuadName.BL]),
                    ]
        
        # Sort the quads by distance from the camera for updating and rendering.
        # Not using actual distances to avoid precision errors
        coord = CubeSphereMap.get_cube_coord(*pos)
        self._sorted_quads = []
        
        if coord.x < self._centre_coords[0]:
            # In top left
            if coord.y < self._centre_coords[1]:
                #print "TL"
                self._sorted_quads.append(0)
                self._sorted_quads.append(1)
                self._sorted_quads.append(2)
                self._sorted_quads.append(3)
            
            # In bottom left
            else:
                #print "BL"
                self._sorted_quads.append(2)
                self._sorted_quads.append(0)
                self._sorted_quads.append(3)
                self._sorted_quads.append(1)
                
        else:
            # In top right
            if coord.y < self._centre_coords[1]:
                #print "TR"
                self._sorted_quads.append(1)
                self._sorted_quads.append(0)
                self._sorted_quads.append(3)
                self._sorted_quads.append(2)
            
            # In bottom right
            else:
                #print "BR"
                self._sorted_quads.append(2)
                self._sorted_quads.append(3)
                self._sorted_quads.append(0)
                self._sorted_quads.append(1)
        
        # Calculate the quadrant size using the length of the diagonal across the quadrant
        #TODO: Maybe this is used to adjust the frustrum on the fly when the camera gets close to the planet??
        quad_size = self._child_pos[QuadName.TL] - self._child_pos[QuadName.BR] * 1.0 #( radius / frustrum radius)....
        
        radius = self._sphere_parent.radius
        
        # Calculate split priority
        # Adjust the quadrant size because the quadrants become distorted near the corners of the cube
        # resulting in incorrect splitting/merging of quads.
        
        quad_size = (self._corners[2] - self._corners[0]) * radius
        priority = 0.0
        if quad_size > (self._sphere_parent.max_height * 0.001):
            priority = self._sphere_parent.split_factor * math.pow(quad_size, self._sphere_parent.split_power )
            
        for quad_inc in self._sorted_quads:
            
            # Check to see if the camera is within this quadrant
            if not self.hit_test(self._sphere_parent.camera_pos_sc, quad_inc):
                    
                # Check the quadrant against the horizon distance
                if self._sphere_parent.horizon > 0.0 and \
                   (distances[quad_inc] - radius) > self._sphere_parent.horizon:
                    if not self._get_quad(quad_inc) is None:
                        self._get_quad(quad_inc)._merge()
                        #print "Horizon"
                    continue
               
                # Check the quadrant against the view frustrum
                if not self._get_quad(quad_inc) is None and not self._get_quad(quad_inc)._is_split:
                    child_quad_size = quad_size / 2.0
                    inside = self._sphere_parent.camera.sphere_inside(self._child_pos[quad_inc], child_quad_size) 
                    if inside == 1:
                        quad = self._get_quad(quad_inc)
                        #Logger.Log("Culling Quad: sz: %f name: %s pos: %s" % ( child_quad_size, quad.name, str(child_pos[quad_inc]) ) )
                        quad._merge()
                        continue
            
            if distances[quad_inc] > priority:
                if not self._get_quad(quad_inc) is None:
                    #print "merging due to distance: " + QuadName.quad_string(quad_inc)
                    self._get_quad(quad_inc)._merge()
                    
#                if self._level == self._planet_root._max_depth:
#                    print "merging split level: %d" % self._level
#                    print priority
#                    print distances
                    
                #print "Distance"
                continue

            # If the quad is futher away than its size then dont split it
            if distances[quad_inc] > quad_size:
                continue

#             if self._level <= self._planet_root._max_depth:
# #                print priority
# #                print distances
# #                print "Split level: %d" % self._levelx 
#                 Logger.Log("Splitting Quad: name: %s" % ( self.name) )
#                 self._split(quad_inc)
                
                
            if self._is_split:
                self._get_quad(quad_inc).update_surface()
            elif self._level <= self._planet_root._max_depth:
                #Logger.Log("Splitting Quad: name: %s" % ( self.name) )
                self._split(quad_inc) 
Ejemplo n.º 6
0
 def _get_centre_position(self):
     return CubeSphereMap.get_sphere_position(self._centre_coords[0], 
                                              self._centre_coords[1], 
                                              self._face,
                                              self._sphere_parent.radius)
Ejemplo n.º 7
0
    def _calc_corners(self):
        # Calculate the Cubic coordinates of this quad
        x0, y0, x1, y1, face = CubeSphereMap.get_address_bounds(self._name)

        self._corners = [x0, y0, x1, y1]
        self._centre_coords = CubeSphereMap.get_address_centre(self._name)
        self._quad_centres = [
                                CubeSphereMap.get_address_centre(self._name+'A'),
                                CubeSphereMap.get_address_centre(self._name+'B'),
                                CubeSphereMap.get_address_centre(self._name+'D'),
                                CubeSphereMap.get_address_centre(self._name+'C')
                             ]

        # if self._root:
        #     self._corners.append(0.0) #tl x
        #     self._corners.append(0.0) #tl y
        #     self._corners.append(1.0) #br x
        #     self._corners.append(1.0) #br y
        # else:
        #     parent_corners = self.transform.parent.node.corners
            
        #     if self._quad == QuadName.TL:
        #         self._corners.append(parent_corners[0])
        #         self._corners.append(parent_corners[1])
        #         self._corners.append(parent_corners[0] + (parent_corners[2] - parent_corners[0]) * 0.5 )
        #         self._corners.append(parent_corners[1] + (parent_corners[3] - parent_corners[1]) * 0.5 )
                
        #     elif self._quad == QuadName.TR:
        #         self._corners.append(parent_corners[0] + (parent_corners[2] - parent_corners[0]) * 0.5)
        #         self._corners.append(parent_corners[1])
        #         self._corners.append(parent_corners[2])
        #         self._corners.append(parent_corners[1] + (parent_corners[3] - parent_corners[1]) * 0.5 )
                
        #     elif self._quad == QuadName.BL:
        #         self._corners.append(parent_corners[0])
        #         self._corners.append(parent_corners[1] + (parent_corners[3] - parent_corners[1]) * 0.5)
        #         self._corners.append(parent_corners[0] + (parent_corners[2] - parent_corners[0]) * 0.5)
        #         self._corners.append(parent_corners[3])
                
            
        #     elif self._quad == QuadName.BR:
        #         self._corners.append(parent_corners[0] + (parent_corners[2] - parent_corners[0]) * 0.5)
        #         self._corners.append(parent_corners[1] + (parent_corners[3] - parent_corners[1]) * 0.5)
        #         self._corners.append(parent_corners[2])
        #         self._corners.append(parent_corners[3])
                
                
        # mid_x = (self._corners[2] - self._corners[0]) / 2
        # mid_y = (self._corners[3] - self._corners[1]) / 2
        
        # self._centre_coords = [(self._corners[0] + mid_x), (self._corners[1] + mid_y)]
        
        # self._quad_centres = [ [self._corners[0] + (mid_x/2), self._corners[1] + (mid_y/2)], #TL
        #                        [self._corners[2] - (mid_x/2), self._corners[1] + (mid_y/2)], #TR
        #                        [self._corners[2] - (mid_x/2), self._corners[3] - (mid_y/2)], #BR
        #                        [self._corners[0] + (mid_x/2), self._corners[3] - (mid_y/2)]  #BL
        #                      ]
        
        # Get world positions for centres of child quads
        self._child_pos = [CubeSphereMap.get_sphere_position(self._quad_centres[QuadName.TL][0],
                                                               self._quad_centres[QuadName.TL][1],
                                                               self._face,
                                                               self._sphere_parent.radius),
                             CubeSphereMap.get_sphere_position(self._quad_centres[QuadName.TR][0],
                                                               self._quad_centres[QuadName.TR][1],
                                                               self._face,
                                                               self._sphere_parent.radius),
                             CubeSphereMap.get_sphere_position(self._quad_centres[QuadName.BR][0],
                                                               self._quad_centres[QuadName.BR][1],
                                                               self._face,
                                                               self._sphere_parent.radius),
                             CubeSphereMap.get_sphere_position(self._quad_centres[QuadName.BL][0],
                                                               self._quad_centres[QuadName.BL][1],
                                                               self._face,
                                                               self._sphere_parent.radius),
                             ]