def findG(self, vertex, newVertex, face): c1 = newVertex.x c2 = newVertex.y c3 = newVertex.z u = face.V[0].Position.newVector(face.V[1].Position) u1 = u.x u2 = u.y u3 = u.z r = face.V[2].Position.newVector(face.V[1].Position) r1 = r.x r2 = r.y r3 = r.z s1 = face.V[0].Position.x s2 = face.V[0].Position.y s3 = face.V[0].Position.z g1 = vertex.Position.x - c1 g2 = vertex.Position.y - c2 g3 = vertex.Position.z - c3 #miluju matlab try: t = (-(c1*r2*u3 - c1*r3*u2 - c2*r1*u3 + c2*r3*u1 + c3*r1*u2 - c3*r2*u1 + r1*s2*u3 - r1*s3*u2 - r2*s1*u3 + r2*s3*u1 + r3*s1*u2 - r3*s2*u1)/ (g1*r2*u3 - g1*r3*u2 - g2*r1*u3 + g2*r3*u1 + g3*r1*u2 - g3*r2*u1)) except: t = 0 G = Vector(c1 + t*g1,c2 + t*g2,c3 + t*g3) #delky trojuhelniku a = face.V[0].Position.pointLen(face.V[1].Position) b = face.V[0].Position.pointLen(face.V[2].Position) c = face.V[1].Position.pointLen(face.V[2].Position) #bod nalezi trojuhelniku if (G.pointLen(face.V[0].Position) <= a and G.pointLen(face.V[0].Position) <= b and G.pointLen(face.V[0].Position) <= c and G.pointLen(face.V[1].Position) <= a and G.pointLen(face.V[1].Position) <= b and G.pointLen(face.V[1].Position) <= c and G.pointLen(face.V[2].Position) <= a and G.pointLen(face.V[2].Position) <= b and G.pointLen(face.V[2].Position) <= c): return G return None
class Mesh: def __init__(self, engine, x, y, z, faces): self.Position = Vector(x, y, z) self.Faces = faces self.mode = "faces" self.engine = engine self.showHitbox = True self.hitBox = [] self.updateFaces() def updateMesh(self, camera): self.distance = self.Position.pointLen(camera.Position) self.updateFaces() def updateFaces(self): for face in self.Faces: face.updateFace(self, self.engine.camera, self.engine.light) self.updateHitbox() #vykresli vsechny steny, pokud jejich vzdalenost od kamery je mensi #nez vzdalenost domaci Mesh od kamery #face.distance <= (face.distance - self.distance) + self.distance def drawFaces(self, screen, camera): for face in self.Faces: if (face.render and self.mode == "faces"): A = face.A.drawVertex(camera) B = face.B.drawVertex(camera) C = face.C.drawVertex(camera) self.drawFace(screen, face, A, B, C) if (self.mode == "mesh"): #vykresli oboji A = face.A.drawVertex(camera) B = face.B.drawVertex(camera) C = face.C.drawVertex(camera) self.drawFace(screen, face, A, B, C) #screen.draw([A,B,C], face.distance, (0,0,0), False) def drawFace(self, screen, face, A, B, C): if (face.actColor != None): screen.draw([A, B, C], face.distance + self.distance, face.actColor, True) #screen.draw([A,B,C], face.distance, face.actColor, False) def sortFaces(self): for i in range(0, len(self.Faces) - 1): j = i + 1 tmp = self.Faces[j] while (j > 0 and tmp.distance > self.Faces[j - 1].distance): self.Faces[j] = self.Faces[j - 1] j -= 1 self.Faces[j] = tmp def checkCollisions(self, parent, v): self.hitBox[0] = self.hitBox[0] + v.x self.hitBox[3] = self.hitBox[3] + v.x self.hitBox[1] = self.hitBox[1] + v.y self.hitBox[4] = self.hitBox[4] + v.y self.hitBox[2] = self.hitBox[2] + v.z self.hitBox[5] = self.hitBox[5] + v.z answer = self.engine.CollideHitBox(self) if (answer[0] and answer[1].solid): answer[1].addForce(Force(v.x, v.y, v.z)) newForce = self.createBounce(v, answer[1], 0.1) self.updateHitbox() i = 0 while (self.engine.CollideHitBox(self)[0] == False): i += 0.1 v = v.setVectorLeng(i) self.hitBox[0] = self.hitBox[0] + v.x self.hitBox[3] = self.hitBox[3] + v.x self.hitBox[1] = self.hitBox[1] + v.y self.hitBox[4] = self.hitBox[4] + v.y self.hitBox[2] = self.hitBox[2] + v.z self.hitBox[5] = self.hitBox[5] + v.z v = v.setVectorLeng(i - 0.1) return True, v, newForce if (answer[0]): #koliduje, ale nema zastavit objekt pass else: parent.Position = self.Position return False, v def createBounce(self, v, component, slow): deltaX = abs(component.Position.x - self.Position.x) deltaY = abs(component.Position.y - self.Position.y) deltaZ = abs(component.Position.z - self.Position.z) if (deltaX >= deltaY and deltaX >= deltaZ): return Force(v.x * -slow, v.y * slow, v.z * slow, slow) if (deltaY >= deltaX and deltaY >= deltaZ): return Force(v.x * slow, v.y * -slow, v.z * slow, slow) if (deltaZ >= deltaX and deltaZ >= deltaY): return Force(v.x * slow, v.y * slow, v.z * -slow, slow) def drawHitbox(self, screen): if (self.showHitbox): for edge in self.hitBoxEdges: edge.drawEdge(screen) def updateHitbox(self): try: maxmin = [ self.Position.x, self.Position.y, self.Position.z, self.Position.x, self.Position.y, self.Position.z ] #maxX,maxY,maxZ,minX,minY,minZ for face in self.Faces: for vertex in [face.A, face.B, face.C]: if (vertex.Position.x > maxmin[0]): #nejvetsi X maxmin[0] = vertex.Position.x if (vertex.Position.x < maxmin[3]): #nejmensi X maxmin[3] = vertex.Position.x if (vertex.Position.y > maxmin[1]): #nejvetsi Y maxmin[1] = vertex.Position.y if (vertex.Position.y < maxmin[4]): #nejmensi Y maxmin[4] = vertex.Position.y if (vertex.Position.z > maxmin[2]): #nejvetsi Z maxmin[2] = vertex.Position.z if (vertex.Position.z < maxmin[5]): #nejmensi Z maxmin[5] = vertex.Position.z self.hitBox = maxmin self.hitBoxEdges = [] self.hitBoxEdges.append( Edge(self.engine, Vertex(maxmin[0], maxmin[1], maxmin[2]), Vertex(maxmin[3], maxmin[1], maxmin[2]))) self.hitBoxEdges.append( Edge(self.engine, Vertex(maxmin[0], maxmin[1], maxmin[2]), Vertex(maxmin[0], maxmin[1], maxmin[5]))) self.hitBoxEdges.append( Edge(self.engine, Vertex(maxmin[3], maxmin[1], maxmin[5]), Vertex(maxmin[0], maxmin[1], maxmin[5]))) self.hitBoxEdges.append( Edge(self.engine, Vertex(maxmin[3], maxmin[1], maxmin[2]), Vertex(maxmin[3], maxmin[1], maxmin[5]))) #down self.hitBoxEdges.append( Edge(self.engine, Vertex(maxmin[0], maxmin[4], maxmin[2]), Vertex(maxmin[3], maxmin[4], maxmin[2]))) self.hitBoxEdges.append( Edge(self.engine, Vertex(maxmin[0], maxmin[4], maxmin[2]), Vertex(maxmin[0], maxmin[4], maxmin[5]))) self.hitBoxEdges.append( Edge(self.engine, Vertex(maxmin[3], maxmin[4], maxmin[5]), Vertex(maxmin[0], maxmin[4], maxmin[5]))) self.hitBoxEdges.append( Edge(self.engine, Vertex(maxmin[3], maxmin[4], maxmin[2]), Vertex(maxmin[3], maxmin[4], maxmin[5]))) #between self.hitBoxEdges.append( Edge(self.engine, Vertex(maxmin[0], maxmin[4], maxmin[2]), Vertex(maxmin[0], maxmin[1], maxmin[2]))) self.hitBoxEdges.append( Edge(self.engine, Vertex(maxmin[0], maxmin[4], maxmin[5]), Vertex(maxmin[0], maxmin[1], maxmin[5]))) self.hitBoxEdges.append( Edge(self.engine, Vertex(maxmin[3], maxmin[4], maxmin[2]), Vertex(maxmin[3], maxmin[1], maxmin[2]))) self.hitBoxEdges.append( Edge(self.engine, Vertex(maxmin[3], maxmin[4], maxmin[5]), Vertex(maxmin[3], maxmin[1], maxmin[5]))) return maxmin except: return None def changeColor(self, color): for face in self.Faces: face.color = color #metoda, ktera prenacte steny def setFaces(self, faces): self.Faces = faces
class Mesh: def __init__(self, engine, parent, x, y, z, faces): self.Position = Vector(x, y, z) self.Faces = faces self.mode = "faces" self.parent = parent self.engine = engine self.showHitbox = True self.updateFaces() self.updateRadius() self.collider = MeshCollider(self) def updateMesh(self, camera): self.distance = self.Position.pointLen(camera.Position) self.updateFaces() def updateFaces(self): for face in self.Faces: face.updateFace(self, self.engine.camera, self.engine.light) #vykresli vsechny steny, pokud jejich vzdalenost od kamery je mensi #nez vzdalenost domaci Mesh od kamery #face.distance <= (face.distance - self.distance) + self.distance def drawFaces(self, screen, camera): for face in self.Faces: if (face.render and self.mode == "faces"): vertices = [] for vert in face.V: vertices.append(vert.drawVertex(camera)) self.drawFace(screen, face, vertices) if (self.mode == "mesh"): #vykresli oboji A = face.A.drawVertex(camera) B = face.B.drawVertex(camera) C = face.C.drawVertex(camera) self.drawFace(screen, face, A, B, C) #screen.draw([A,B,C], face.distance, (0,0,0), False) #self.drawRadius(screen) def drawFace(self, screen, face, vertices): if (face.actColor != None): screen.draw(vertices, face.distance, face.actColor, True) #screen.draw(vertices, face.distance, face.actColor, False) def checkCollisions(self, parent, v): answer = self.engine.CollideRadius(self, self.radius, self.Position.addVectorReturn(v)) if (answer[0]): v, obj, collide = self.collider.collision(answer[1], v) if (collide): #v = Vector(v.Position.x, v.Position.y, v.Position.z) obj.addForce(Force(v.x/2, v.y/2, v.z/2)) newForce = self.createBounce(v, obj, 0.5) else: newForce = Force(0,0,0) return collide, v, newForce if (answer[0]): #koliduje, ale nema zastavit objekt pass else: return False, v def createBounce(self, v, component, slow): deltaX = abs(component.Position.x - self.Position.x) deltaY = abs(component.Position.y - self.Position.y) deltaZ = abs(component.Position.z - self.Position.z) if (deltaX >= deltaY and deltaX >= deltaZ): return Force(v.x*-slow, v.y*slow, v.z*slow, slow) if (deltaY >= deltaX and deltaY >= deltaZ): return Force(v.x*slow, v.y*-slow, v.z*slow, slow) if (deltaZ >= deltaX and deltaZ >= deltaY): return Force(v.x*slow, v.y*slow, v.z*-slow, slow) #najde nejvzdalensejsi bod meshe a spocte jeho vzdalenost od stredu #najde polomer hitBoxu def updateRadius(self): self.radius = 0 for face in self.Faces: for vector in face.v: newRadius = vector.length() if (newRadius > self.radius): self.radius = newRadius def changeColor(self, color): for face in self.Faces: face.color = color #metoda, ktera prenacte steny def setFaces(self, faces): self.Faces = faces def drawRadius(self, screen): step = 40 for i in range(0, 360, step): radian = i*math.pi/180 x1 = self.Position.x + self.radius*math.sin(radian) y1 = self.Position.y + self.radius*math.cos(radian) radian = (i+step)*math.pi/180 x2 = self.Position.x + self.radius*math.sin(radian) y2 = self.Position.y + self.radius*math.cos(radian) a1 = Vertex(x1,y1,self.Position.z) a2 = Vertex(x2,y2,self.Position.z) edge = Edge(self.engine, a1, a2).drawEdge(screen) for i in range(0, 360, step): radian = i*math.pi/180 z1 = self.Position.z + self.radius*math.sin(radian) y1 = self.Position.y + self.radius*math.cos(radian) radian = (i+step)*math.pi/180 z2 = self.Position.z + self.radius*math.sin(radian) y2 = self.Position.y + self.radius*math.cos(radian) a1 = Vertex(self.Position.x,y1,z1) a2 = Vertex(self.Position.x,y2,z2) edge = Edge(self.engine, a1, a2).drawEdge(screen) for i in range(0, 360, step): radian = i*math.pi/180 x1 = self.Position.x + self.radius*math.sin(radian) z1 = self.Position.z + self.radius*math.cos(radian) radian = (i+step)*math.pi/180 x2 = self.Position.x + self.radius*math.sin(radian) z2 = self.Position.z + self.radius*math.cos(radian) a1 = Vertex(x1,self.Position.y,z1) a2 = Vertex(x2,self.Position.y,z2) edge = Edge(self.engine, a1, a2).drawEdge(screen)