def enemy_wing_shape(r, g, b): # r,g,b - Red, green and blue values of the wing color # Defining locations and colors for each vertex of the shape vertices = [ # positions colors 0.0, -0.5, 0.0, r, g, b, 0.5, 0.5, 0.0, r, g, b, 0.0, 1.25, 0.0, r, g, b ] # Defining connections among vertices # We have a triangle every 3 indices specified indices = [0, 1, 2] return bs.Shape(vertices, indices)
def createArrowMap(): # Defining the location and colors of each vertex of the shape vertices = [] # This shape is meant to be drawn with GL_LINES indices = [] for i in range(shapeSol[0]): for j in range(shapeSol[1]): k = j + i * shapeSol[0] color = [0, 0, 0] # Getting the gradient gradient, magnitude = calculateGradient(i, j) vertex = np.array([i * PRECISION, j * PRECISION, 0.05]) end_point = vertex + 0.07 * magnitude * gradient middle = (vertex + end_point) / 2 # Creating the arrowhead perpendicular = np.cross(end_point - vertex, [0, 0, 1]) perpendicular /= np.linalg.norm(perpendicular) # Adding the arrow vertices += list(vertex) + color + list(end_point) + color vertices += list(middle + 0.02 * magnitude * perpendicular) + color vertices += list(middle - 0.02 * magnitude * perpendicular) + color indices += [ 4 * k, 4 * k + 1, 4 * k + 1, 4 * k + 2, 4 * k + 1, 4 * k + 3 ] return bs.Shape(vertices, indices)
def createColorTrapeze(r, g, b): vertices = [ # positions colors -0.5, -0.5, 0.0, r, g, b, 0.5, -0.5, 0.0, r, g, b, -0.3, 0.5, 0.0, r, g, b, 0.3, 0.5, 0.0, r, g, b ] # Connections among vertices indices = [0, 1, 3, 3, 2, 0] return bs.Shape(vertices, indices)
def player_body_shape(r, g, b): # r,g,b - Red, green and blue values of the body color # Defining locations and colors for each vertex of the shape vertices = [ # positions colors -0.45, -0.525, 0.0, r, g, b, 0.45, -0.525, 0.0, r, g, b, 0.0, 0.75, 0.0, r, g, b ] # Defining connections among vertices # We have a triangle every 3 indices specified indices = [0, 1, 2] return bs.Shape(vertices, indices)
def createTextureQuad(image_filename, x, y, nx=1, ny=1): # Defining locations and texture coordinates for each vertex of the shape vertices = [ # positions texture 0.0, 0.0, 0.0, 0, ny, x, 0.0, 0.0, nx, ny, x, y, 0.0, nx, 0, 0.0, y, 0.0, 0, 0 ] # Defining connections among vertices # We have a triangle every 3 indices specified indices = [0, 1, 2, 2, 3, 0] textureFileName = image_filename return bs.Shape(vertices, indices, textureFileName)
def createColorTriangle(r, g, b): vertices = [ # positions colors -0.5, -0.5, 0.0, r, g, b, 0.5, -0.5, 0.0, r, g, b, 0.0, 0.5, 0.0, r, g, b ] # Connections among vertices indices = [0, 1, 2] return bs.Shape(vertices, indices)
def create_explosion(): # Ship explosion model r, g, b = (0.95, 0.4, 0.0) # Defining locations and colors for each vertex of the shape vertices = [ # positions colors -0.5, -0.5, 0.0, r, g, b, 0.5, -0.5, 0.0, r, g, b, 0.0, 0.5, 0.0, r, g, b, 0.0, -0.75, 0.0, r, g, b, 0.5, 0.25, 0.0, r, g, b, -0.5, 0.25, 0.0, r, g, b ] # Defining connections among vertices # We have a triangle every 3 indices specified indices = [0, 1, 2, 3, 4, 5] gpuExplosion = es.toGPUShape(bs.Shape(vertices, indices)) explosion = sg.SceneGraphNode("explosionModel") explosion.transform = tr.matmul( [tr.translate(0.0, 0.02, 0.0), tr.uniformScale(0.15)]) explosion.childs = [gpuExplosion] return explosion
def readOBJ(filename, color): vertices = [] normals = [] textCoords = [] faces = [] with open(filename, 'r') as file: for line in file.readlines(): aux = line.strip().split(' ') if aux[0] == 'v': vertices += [[float(coord) for coord in aux[1:]]] elif aux[0] == 'vn': normals += [[float(coord) for coord in aux[1:]]] elif aux[0] == 'vt': assert len( aux[1:] ) == 2, "Texture coordinates with different than 2 dimensions are not supported" textCoords += [[float(coord) for coord in aux[1:]]] elif aux[0] == 'f': N = len(aux) faces += [[ readFaceVertex(faceVertex) for faceVertex in aux[1:4] ]] for i in range(3, N - 1): faces += [[ readFaceVertex(faceVertex) for faceVertex in [aux[i], aux[i + 1], aux[1]] ]] vertexData = [] indices = [] index = 0 # Per previous construction, each face is a triangle for face in faces: # Checking each of the triangle vertices for i in range(0, 3): vertex = vertices[face[i][0] - 1] normal = normals[face[i][2] - 1] vertexData += [ vertex[0], vertex[1], vertex[2], color[0], color[1], color[2], normal[0], normal[1], normal[2] ] # Connecting the 3 vertices to create a triangle indices += [index, index + 1, index + 2] index += 3 return bs.Shape(vertexData, indices)
def createColorCube2(i, j, k, X, Y, Z, r, g, b): l_x = X[i, j, k] r_x = l_x + 1 b_y = Y[i, j, k] f_y = b_y + 1 b_z = Z[i, j, k] t_z = b_z + 1 # positions colors vertices = [ # Z+: number 1 l_x, b_y, t_z, r, g, b, r_x, b_y, t_z, r, g, b, r_x, f_y, t_z, r, g, b, l_x, f_y, t_z, r, g, b, # Z-: number 6 l_x, b_y, b_z, r, g, b, r_x, b_y, b_z, r, g, b, r_x, f_y, b_z, r, g, b, l_x, f_y, b_z, r, g, b, # X+: number 5 r_x, b_y, b_z, r, g, b, r_x, f_y, b_z, r, g, b, r_x, f_y, t_z, r, g, b, r_x, b_y, t_z, r, g, b, # X-: number 2 l_x, b_y, b_z, r, g, b, l_x, f_y, b_z, r, g, b, l_x, f_y, t_z, r, g, b, l_x, b_y, t_z, r, g, b, # Y+: number 4 l_x, f_y, b_z, r, g, b, r_x, f_y, b_z, r, g, b, r_x, f_y, t_z, r, g, b, l_x, f_y, t_z, r, g, b, # Y-: number 3 l_x, b_y, b_z, r, g, b, r_x, b_y, b_z, r, g, b, r_x, b_y, t_z, r, g, b, l_x, b_y, t_z, r, g, b, ] # Defining connections among vertices # We have a triangle every 3 indices specified indices = [ 0, 1, 2, 2, 3, 0, 4, 5, 6, 6, 7, 4, 4, 5, 1, 1, 0, 4, 6, 7, 3, 3, 2, 6, 5, 6, 2, 2, 1, 5, 7, 4, 0, 0, 3, 7] return bs.Shape(vertices, indices)
def createRoof(): # Defining the location and colors of each vertex of the shape vertices = [] pts = keyPoints() for vertex in [pts[0], pts[3], pts[24], pts[33]]: vertices += vertex + [0.75, 0.75, 0.75] + [0, 0, -1] # Defining connections among vertices indices = [2, 0, 1, 2, 1, 3] return bs.Shape(vertices, indices)
def fish_body(lenght, height, r, g, b): # Function to create a fish body shape # lenght - Lenght of the body # height - Height of the body # r,g,b - Color of the body # return - Fish body Shape vertices = [ -lenght / 2, 0.0, 0.0, r, g, b, -lenght / 6, 0.0, -height / 2, r, g, b, lenght / 2, 0.0, 0.0, r, g, b, -lenght / 6, 0.0, height / 2, r, g, b ] indices = [0, 1, 3, 1, 2, 3] return bs.Shape(vertices, indices)
def fish_fin(lenght, height, r, g, b): # Function to create a fish fin shape # lenght - Lenght of the fin # height - Height of the fin # r,g,b - Color of the fin # return - Fish fin Shape vertices = [ 0.0, 0.0, 0.0, r, g, b, lenght, 0.0, -height / 2, r, g, b, lenght, 0.0, height / 2, r, g, b ] indices = [0, 1, 2] return bs.Shape(vertices, indices)
def createBranch(length=1.0, ratio=0.1, sides=5): radius = length * ratio angle = 360 / sides colorCoffee = [0.67, 0.33, 0.0] vertices = [] indices = [] # Creating vertices that will become the center of two polygons # The normals of all vertices were set up considering each branch as # a component of a tree, so some simplifications were be made vertices += [0, 0, length] + colorCoffee + [0, 0, 1] vertices += [0, 0, 0] + colorCoffee + [0, 0, -1] # Creating a prism made up of two connected polygons for i in range(sides): sub_angle = angle * i * np.pi / 180 x = radius * np.cos(sub_angle) y = radius * np.sin(sub_angle) vertices += [x, y, length] + colorCoffee + [x, y, 0] vertices += [x, y, 0] + colorCoffee + [x, y, 0] if i > 0: j = (i + 1) * 2 # Creating the lower and upper base of the prism indices += [0, j - 2, j] indices += [1, j - 1, j + 1] # Creating the vertical faces of the prism indices += [j + 1, j - 1, j - 2] indices += [j - 2, j, j + 1] lastIdx = sides * 2 # Closing the lower and upper base indices += [0, 2, lastIdx] indices += [1, 3, lastIdx + 1] # Closing the vertical faces indices += [lastIdx + 1, 3, 2] indices += [lastIdx, lastIdx + 1, 2] return bs.Shape(vertices, indices)
def createLifeBar(green=True): channel = int(green) vertices = [ # positions colors -0.5, -0.5, 0.0, 1 - channel, channel, 0, 0.5, -0.5, 0.0, 1 - channel, channel, 0, 0.5, 0.5, 0.0, 1, 1, 1, -0.5, 0.5, 0.0, 1 - channel, channel, 0 ] # Defining connections among vertices indices = [0, 1, 2, 2, 3, 0] gpuShape = es.toGPUShape(bs.Shape(vertices, indices)) # Creating an elongated bar scaledBar = sg.SceneGraphNode("scaledBar") scaledBar.transform = tr.scale(0.1, 0.03, 1) scaledBar.childs += [gpuShape] bar = sg.SceneGraphNode("bar") bar.childs += [scaledBar] return bar
def createCurve(curve, level): z = (level - minval) / (maxval - minval) color = list((np.array(colorAux(level)) + np.array([1, 1, 1])) * 0.5) # Defining the location and colors of each vertex of the shape vertices = [] # This shape is meant to be drawn with GL_LINES indices = [] for i, pos in enumerate(curve): vertices += [pos[0] * PRECISION, pos[1] * PRECISION, z] + color indices += [i, i + 1] indices.pop() return bs.Shape(vertices, indices)
def createCircleHitbox(radio, sides, r, g, b): vertices = [0, 0, 0, r, g, b] indices = [] xt = np.array([radio, 0, 0, 1]) vertices += [xt[0], xt[1], xt[2], r, g, b] indices += [0, 1, 2] for i in range(1, sides + 1): xtp = np.matmul(tr.rotationZ((2 / sides) * i * np.pi), xt) xtr = np.array([xtp[0], xtp[1], xtp[2]]) / xtp[3] vertices += [xtr[0], xtr[1], xtr[2], r, g, b] if i == (sides): indices += [0, i + 1, 1] else: indices += [0, i + 1, i + 2] return bs.Shape(vertices, indices)
def generateCylinder(latitudes, color, R=1.0, z_bottom=0.0, z_top=1.0): vertices = [] indices = [] dtheta = 2 * np.pi / latitudes theta = 0 start_index = 0 for i in range(latitudes): a = [np.cos(theta) * R, np.sin(theta) * R, z_bottom] b = [np.cos(theta + dtheta) * R, np.sin(theta + dtheta) * R, z_bottom] d = [np.cos(theta) * R, np.sin(theta) * R, z_top] c = [np.cos(theta + dtheta) * R, np.sin(theta + dtheta) * R, z_top] rectangulo, indice = createColorQuadIndexation(start_index, a, b, c, d, color) vertices += rectangulo indices += indice theta += dtheta start_index += 4 return bs.Shape(vertices, indices)
def createFloor(): global data # Generate a terrain with many samples between the limits of the map xs = np.ogrid[0:5 * data["L"] + 4 * data["W"]:np.complex(shapeSol[0], 1)] ys = np.ogrid[0:data["P"] + data["W"] + data["D"]:np.complex(shapeSol[1], 1)] xSize = len(xs) ySize = len(ys) # Defining the location and colors of each vertex of the shape vertices = [] indices = [] # Generating a vertex for each sample x, y, and assigning a color for i in range(xSize): for j in range(ySize): x = xs[i] y = ys[j] vertices += [x, y, 0] + colorMap(x, y) # The previous loops generates full columns j-y and then move to # the next i-x. Hence, the index for each vertex i,j can be computed as index = lambda i, j: i * len(ys) + j # We generate quads for each cell connecting 4 neighbor vertices for i in range(len(xs) - 1): for j in range(len(ys) - 1): # Getting indices for all vertices in this quad isw = index(i, j) ise = index(i + 1, j) ine = index(i + 1, j + 1) inw = index(i, j + 1) # Adding this cell's quad as 2 triangles indices += [isw, ise, ine, ine, inw, isw] return bs.Shape(vertices, indices)
def flame_shape(): # Ship flame model r1, g1, b1 = (0.95, 0.3, 0.0) r2, g2, b2 = (0.95, 0.6, 0.0) # Defining locations and colors for each vertex of the shape vertices = [ # positions colors -0.25, 0.0, 0.0, r1, g1, b1, 0.0, -0.75, 0.0, r1, g1, b1, 0.25, 0.0, 0.0, r1, g1, b1, 0.0, -0.4, 0.0, r2, g2, b2 ] # Defining connections among vertices # We have a triangle every 3 indices specified indices = [0, 1, 2, 0, 3, 2] flame = bs.Shape(vertices, indices) return flame
def hitboxShape(self, image_filename): r = 1.0 g = 0.0 b = 0.0 # Defining locations and colors for each vertex of the shape vertices = [ # positions colors 0.0, 0.0, 0.0, 0.0, 1.0, self.width, 0.0, 0.0, 1.0, 1.0, self.width, self.height, 0.0, 1.0, 0.0, 0.0, self.height, 0.0, 0.0, 0.0 ] # Defining connections among vertices # We have a triangle every 3 indices specified indices = [0, 1, 2, 2, 3, 0] textureFileName = image_filename return bs.Shape(vertices, indices, textureFileName)
def generateTerrain(xs, ys, s): verticesList = [] vertices = [] indices = [] xSize = len(xs) ySize = len(ys) zs = np.zeros((xSize, ySize)) muList = [] sigmaList = [] signList = [] # Each gaussian function is randomized for i in range(GAUSSIAN): np.random.seed(RANDOM + i) random = 2 * np.random.uniform(0, 1.0, 2) - 1.0 random[0] *= MAP_X_SIZE random[1] *= MAP_Y_SIZE muList += [np.copy(random)] sigmaList += [max(1, s - np.random.uniform())] signList += [1] if np.random.uniform() > 0.3 else [-1] # Generating a vertex for each sample x, y, z, using a # number of gaussian functions defined as a parameter for i in range(xSize): for j in range(ySize): x = xs[i] y = ys[j] z = 0 for sigma, mu, sign in zip(sigmaList, muList, signList): z += gaussianFunction(x, y, s, sigma, mu) * sign zs[i, j] = z verticesList += [[x, y, z] + list(altitudeColor(z))] # Generating the normal vertices for i in range(xSize): for j in range(ySize): normal = terrainNormal(xSize, ySize, zs, i, j) verticesList[i * xSize + j] += normal vertices += verticesList[i * xSize + j] # The previous loops generates full columns j-y and then move to # the next i-x. Hence, the index for each vertex i,j can be computed as index = lambda i, j: i * len(ys) + j # We generate quads for each cell connecting 4 neighbor vertices for i in range(len(xs) - 1): for j in range(len(ys) - 1): # Getting indices for all vertices in this quad isw = index(i, j) ise = index(i + 1, j) ine = index(i + 1, j + 1) inw = index(i, j + 1) # Adding this cell's quad as 2 triangles indices += [isw, ise, ine, ine, inw, isw] return bs.Shape(vertices, indices), zs
def createAquarium(width, lenght, height, r, g, b): # Function to create the aquarium bounding box as lines # width - Width of the aquarium # lenght - Lenght of the aquarium # height - Height of the aquarium # r,g,b - Color of the lines # return - Aquarium Shape w2 = width / 2 l2 = lenght / 2 h2 = height / 2 # Defining the location and colors of each vertex of the shape vertices = [ # positions colors # Z- -w2, -l2, -h2, r, g, b, w2, -l2, -h2, r, g, b, w2, l2, -h2, r, g, b, -w2, l2, -h2, r, g, b, # Z+ -w2, -l2, h2, r, g, b, w2, -l2, h2, r, g, b, w2, l2, h2, r, g, b, -w2, l2, h2, r, g, b, ] # This shape is meant to be drawn with GL_LINES, # i.e. every 2 indices, we have 1 line. indices = [ # Z- 0, 1, 1, 2, 2, 3, 3, 0, # Z+ 4, 5, 5, 6, 6, 7, 7, 4, # sides 0, 4, 1, 5, 2, 6, 3, 7 ] return bs.Shape(vertices, indices)
def to_shape(self): # Method to return volume as Shape # return - Shape of the voxel volume return bs.Shape(self.vertices, self.indices)
def createWalls(): global data # Defining the location and colors of each vertex of the shape vertices = [] color = [0.75, 0.75, 0.75] # Points to use pts = keyPoints() hpts = list(map(lambda x: [x[0], x[1], 1], pts.copy())) # Drawing the walls # Drawing the bottom walls for i in range(0, 4): vertices += pts[i] + color + [0, 1, 0] + hpts[i] + color + [0, 1, 0] # Unorganized group of walls vertices += pts[0] + color + [1, 0, 0] + hpts[0] + color + [1, 0, 0] vertices += pts[4] + color + [1, 0, 0] + hpts[4] + color + [1, 0, 0] vertices += pts[3] + color + [-1, 0, 0] + hpts[3] + color + [-1, 0, 0] vertices += pts[33] + color + [-1, 0, 0] + hpts[33] + color + [-1, 0, 0] vertices += pts[14] + color + [1, 0, 0] + hpts[14] + color + [1, 0, 0] vertices += pts[24] + color + [1, 0, 0] + hpts[24] + color + [1, 0, 0] # Drawing the walls perpendicual to the heater (big) for i in range(6, 14, 2): vertices += pts[i] + color + [-1, 0, 0] + hpts[i] + color + [-1, 0, 0] vertices += pts[i + 19] + color + [-1, 0, 0] + hpts[i + 19] + color + [ -1, 0, 0 ] for i in range(16, 24, 2): vertices += pts[i] + color + [1, 0, 0] + hpts[i] + color + [1, 0, 0] vertices += pts[i + 10] + color + [1, 0, 0] + hpts[i + 10] + color + [ 1, 0, 0 ] # Drawing the walls parallel to the heater for i in range(4, 14): vertices += pts[i] + color + [0, -1, 0] + hpts[i] + color + [0, -1, 0] for i in range(14, 24): vertices += pts[i] + color + [0, 1, 0] + hpts[i] + color + [0, 1, 0] # Drawing the walls perpendicual to the heater (small) for i in range(5, 15, 2): vertices += pts[i] + color + [1, 0, 0] + hpts[i] + color + [1, 0, 0] vertices += pts[i + 10] + color + [1, 0, 0] + hpts[i + 10] + color + [ 1, 0, 0 ] # Drawing the heater for i in range(1, 3): vertices += pts[i] + [1, 0, 0] + [0, 1, 0] + hpts[i] + [1, 0, 0 ] + [0, 1, 0] # Drawing the bottom of the windows for i in range(24, 34): vertices += pts[i] + color + [0, -1, 0] + hpts[i][:2] + [ 0.3 ] + color + [0, -1, 0] # Drawing the open or closed windows windows = data["windows"] glass_colors = [[0.5, 0.5, 1], [1, 1, 0]] for i, j in enumerate(range(24, 34)): glass = glass_colors[windows[i // 2]] vertices += pts[j][:2] + [0.3] + glass + [ 0, 1, 0 ] + hpts[j] + glass + [0, 1, 0] # Defining connections among vertices indices = [] for i in range(0, 156, 4): indices += [i + 1, i, i + 2, i + 1, i + 2, i + 3] return bs.Shape(vertices, indices)
def createLeaf(g=0.4): # The golden ratio and its inverse gRa = (1 + np.sqrt(5)) / 2 iRa = 1 / gRa # Defining the location and colors of each vertex of the shape vertices = [ # positions colors normals iRa, gRa, 0.0, 0.0, g, 0.0, iRa, gRa, 0.0, gRa, 0.0, iRa, 0.0, g, 0.0, gRa, 0.0, iRa, 1.0, 1.0, 1.0, 0.0, g, 0.0, 1.0, 1.0, 1.0, gRa, 0.0, -iRa, 0.0, g, 0.0, gRa, 0.0, -iRa, 1.0, 1.0, -1.0, 0.0, g, 0.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 0.0, g, 0.0, 1.0, -1.0, 1.0, iRa, -gRa, 0.0, 0.0, g, 0.0, iRa, -gRa, 0.0, 1.0, -1.0, -1.0, 0.0, g, 0.0, 1.0, -1.0, -1.0, 0.0, -iRa, -gRa, 0.0, g, 0.0, 0.0, -iRa, -gRa, 0.0, iRa, -gRa, 0.0, g, 0.0, 0.0, iRa, -gRa, -1.0, -1.0, -1.0, 0.0, g, 0.0, -1.0, -1.0, -1.0, -iRa, -gRa, 0.0, 0.0, g, 0.0, -iRa, -gRa, 0.0, -1.0, 1.0, -1.0, 0.0, g, 0.0, -1.0, 1.0, -1.0, -gRa, 0.0, -iRa, 0.0, g, 0.0, -gRa, 0.0, -iRa, -iRa, gRa, 0.0, 0.0, g, 0.0, -iRa, gRa, 0.0, 0.0, iRa, gRa, 0.0, g, 0.0, 0.0, iRa, gRa, -1.0, 1.0, 1.0, 0.0, g, 0.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 0.0, g, 0.0, -1.0, -1.0, 1.0, -gRa, 0.0, iRa, 0.0, g, 0.0, -gRa, 0.0, iRa, 0.0, -iRa, gRa, 0.0, g, 0.0, 0.0, -iRa, gRa ] # Defining connections among vertices # We have a triangle every 3 indices specified indices = [ 0, 1, 2, 0, 3, 1, 0, 4, 3, 9, 3, 4, 9, 7, 3, 9, 8, 7, 11, 7, 6, 11, 8, 7, 11, 10, 8, 6, 1, 5, 6, 3, 1, 6, 7, 3, 12, 0, 14, 12, 4, 0, 12, 9, 4, 10, 12, 13, 10, 9, 12, 10, 8, 9, 17, 13, 18, 17, 10, 13, 17, 11, 10, 16, 2, 15, 16, 0, 2, 16, 14, 0, 18, 14, 16, 18, 12, 14, 18, 13, 12, 19, 2, 15, 19, 1, 2, 19, 5, 1, 17, 5, 19, 17, 6, 5, 17, 11, 6, 18, 15, 16, 18, 19, 15, 18, 17, 19 ] return bs.Shape(vertices, indices)
glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) # Load temperatures and grid load_voxels = np.load(FILENAME) X = np.arange(0, load_voxels.shape[0], 1, dtype=int) Y = np.arange(0, load_voxels.shape[1], 1, dtype=int) Z = np.arange(0, load_voxels.shape[2], 1, dtype=int) X, Y, Z = np.meshgrid(Y, X, Z) voxelsA = fast_marching_cube(X, Y, Z, load_voxels, T_A) voxelsB = fast_marching_cube(X, Y, Z, load_voxels, T_B) voxelsC = fast_marching_cube(X, Y, Z, load_voxels, T_C) # Creating shapes on GPU memory isosurfaceA = bs.Shape([], []) pointsA = [] for i in range(X.shape[0] - 1): for j in range(X.shape[1] - 1): for k in range(X.shape[2] - 1): if voxelsA[i, j, k]: pointsA.append((i, j, k)) temp_shape = createColorCube2(i, j, k, X, Y, Z, 0.0, 0.5, 0.0) merge(isosurfaceA, 6, temp_shape) copyPointsA = pointsA.copy() isosurfaceB = bs.Shape([], []) pointsB = [] for i in range(X.shape[0] - 1): for j in range(X.shape[1] - 1): for k in range(X.shape[2] - 1):