def RayToPlaneIntersection(P, d, Q, n): denom = geo2.Vec3Dot(n, d) if abs(denom) < 1e-05: return P else: distance = -geo2.Vec3Dot(Q, n) t = -(geo2.Vec3Dot(n, P) + distance) / denom S = geo2.Add(geo2.Scale(d, t), P) return S
def UpdateInSceneContainer(self): if not self.inSceneContainer: return self.UpdateInSceneContainerPosition() lookAtDir = self.GetLookAtDirection() pitch = math.acos(geo2.Vec3Dot(lookAtDir, (0, -1, 0))) rightDir = geo2.Vec3Cross(self.GetUpDirection(), lookAtDir) roll = math.acos(geo2.Vec3Dot(rightDir, (0, 1, 0))) self.inSceneContainer.Update(pitch, roll)
def CreateViewMatrix(self): upVector = (0, 1, 0) xaxis = geo2.Vec3Normalize(geo2.Vec3Cross(upVector, self.direction)) yaxis = geo2.Vec3Cross(self.direction, xaxis) return ((xaxis[0], yaxis[0], self.direction[0], 0.0), (xaxis[1], yaxis[1], self.direction[1], 0.0), (xaxis[2], yaxis[2], self.direction[2], 0.0), (-geo2.Vec3Dot(xaxis, self.cameraPosition), -geo2.Vec3Dot(yaxis, self.cameraPosition), -geo2.Vec3Dot(self.direction, self.cameraPosition), 1.0))
def RayToPlaneIntersection(P, d, Q, n): denom = geo2.Vec3Dot(n, d) if abs(denom) < 1e-05: return P else: distance = -geo2.Vec3Dot(Q, n) t = -(geo2.Vec3Dot(n, P) + distance) / denom scaledRay = geo2.Vector(*d) * t P += scaledRay return P
def _EnforceMinMaxZoom(self, eyePos): vEye = geo2.Subtract(eyePos, self.atPosition) vMaxZoom = geo2.Scale(self.GetZAxis(), self.maxZoom) vEyeToMaxZoom = geo2.Subtract(vEye, vMaxZoom) if geo2.Vec3Dot(vEyeToMaxZoom, vMaxZoom) < 0: eyePos = geo2.Add(self.atPosition, vMaxZoom) self.zoomTarget = None vMinZoom = geo2.Scale(self.GetZAxis(), self.minZoom) vEyeToMinZoom = geo2.Subtract(vEye, vMinZoom) if geo2.Vec3Dot(vEyeToMinZoom, vMinZoom) > 0: eyePos = geo2.Add(self.atPosition, vMinZoom) self.zoomTarget = None return eyePos
def RayToPlaneIntersection(P, d, Q, n, returnSign = False): position = P sign = 1 denom = geo2.Vec3Dot(n, d) if abs(denom) >= 1e-05: distance = -geo2.Vec3Dot(Q, n) t = -(geo2.Vec3Dot(n, P) + distance) / denom if t < 0: sign = -1 S = geo2.Add(geo2.Scale(d, t), P) position = S if returnSign: return (position, sign) return position
def _TransformAxis(self, v): viewMat = trinity.GetViewTransform() viewVec = geo2.Vector(viewMat[0][2], viewMat[1][2], viewMat[2][2]) pos = self.GetTranslation() start = self.startPlanePos - pos start = geo2.Vec3Normalize(start) end = self.endPlanePos - pos end = geo2.Vec3Normalize(end) q = geo2.QuaternionIdentity() dot = geo2.Vec3Dot(start, end) if 1.0 - dot < 1e-05: return q dnormal = geo2.Vec3Cross(start, end) if self.activeManipAxis == 'w': worldInv = geo2.MatrixInverse(self.worldTranslation) axis = geo2.Vec3TransformNormal(viewVec, worldInv) axis = geo2.Vector(*axis) rdot = geo2.Vec3Dot(axis, viewVec) ddot = geo2.Vec3Dot(dnormal, axis) if ddot < 0.0 and rdot > 0.0: axis = -axis elif ddot > 0.0 and rdot < 0.0: axis = -axis elif self.activeManipAxis == 'ww': curP = self._Hemisphere(self.curX, self.curY) preP = self._Hemisphere(self.preX, self.preY) viewInverse = geo2.MatrixInverse(viewMat) norm = geo2.Vec3Cross(preP, curP) worldInv = geo2.MatrixInverse(self.worldTranslation) axis = geo2.Vec3TransformNormal(norm, worldInv) axis = geo2.Vec3TransformNormal(axis, viewInverse) dot = geo2.Vec3Dot(curP, preP) else: axis = self.axis[self.activeManipAxis] if geo2.Vec3Dot(dnormal, axis) < 0.0: axis = -axis if self.activeManipAxis == 'x' and self.worldTranslation[0][ 0] < 0.0 or self.activeManipAxis == 'y' and self.worldTranslation[ 1][1] < 0.0 or self.activeManipAxis == 'z' and self.worldTranslation[ 2][2] < 0.0: axis = -axis self.startPlanePos = self.endPlanePos if dot < -1: dot = -1 elif dot > 1: dot = 1 q = geo2.QuaternionRotationAxis(axis, math.acos(dot)) q = geo2.QuaternionNormalize(q) return q
def SetModel(self, scale): graphic = cfg.invtypes.Get(self.pinKv.typeID).Graphic() self.model = None if graphic and graphic.graphicFile: graphicFile = str(graphic.graphicFile) graphicFile = graphicFile.replace(':/model', ':/dx9/model').replace( '.blue', '.red') self.model = trinity.Load(graphicFile) if not self.model or self.model.__bluetype__ != 'trinity.EveTransform': self.model = trinity.Load( 'res:/dx9/model/worldobject/Orbital/UI/Terrestrial/Command/CommT_T1/CommT_T1.red' ) if not self.model: return EXT = 1.026 self.model.scaling = (scale, scale, scale) self.model.sortValueMultiplier = 0.5 self.model.translation = (EXT * self.surfacePoint.x, EXT * self.surfacePoint.y, EXT * self.surfacePoint.z) plnSurfRotMat = geo2.MatrixRotationAxis( geo2.Vec3Cross( geo2.Vec3Normalize(self.surfacePoint.GetAsXYZTuple()), (0.0, 1.0, 0.0)), -math.acos( geo2.Vec3Dot( geo2.Vec3Normalize(self.surfacePoint.GetAsXYZTuple()), (0.0, 1.0, 0.0)))) rotQuat = geo2.QuaternionRotationMatrix(plnSurfRotMat) self.model.rotation = rotQuat self.model.name = '%s,%s' % (planetCommon.PINTYPE_NORMAL, self.pinKv.id) self.transform.children.append(self.model)
def NewDirectionObstacleCheck(self, destYaw, heading): entity = self.entityClient.GetPlayerEntity() gw = GameWorld.Manager.GetGameWorld(long(entity.scene.sceneID)) posComp = entity.GetComponent('position') movComp = entity.GetComponent('movement') start = posComp.position start = geo2.Vec3Add( start, (0.0, self.AVATAR_COLLISION_DETECTION_CAPSULE_HEIGHT_MOD * movComp.characterController.height, 0.0)) yaw, pitch, roll = geo2.QuaternionRotationGetYawPitchRoll( posComp.rotation) direction = geo2.QuaternionRotationSetYawPitchRoll(yaw + destYaw, 0, 0) end = heading end = geo2.QuaternionTransformVector(direction, end) direction = end = geo2.Vec3Scale( end, self.AVATAR_COLLISION_DETECTION_FEELER_LENGTH) end = geo2.Vec3Add(end, start) hitResult = gw.SweptSphere( start, end, self.AVATAR_COLLISION_DETECTION_FEELER_RADIUS) result = False if hitResult: dotProduct = geo2.Vec3Dot(direction, hitResult[1]) if abs(dotProduct) > self.AVATAR_COLLISION_RESTRICTION_ANGLE_DP: result = True return result
def PickObject(self, x, y): if self.sceneManager.GetActiveScene() != self.renderScene: return rescale = 1.0 / 10000.0 projection = trinity.TriProjection() projection.PerspectiveFov(trinity.GetFieldOfView(), trinity.GetAspectRatio(), trinity.GetFrontClip(), trinity.GetBackClip()) view = trinity.TriView() view.transform = trinity.GetViewTransform() scaling, rotation, translation = geo2.MatrixDecompose( self.transform.worldTransform) pZ = geo2.Vec3Transform((0, 0, 1), self.transform.worldTransform) surfaceNormal = geo2.Subtract(pZ, translation) cameraZ = geo2.Vector(view.transform[0][2], view.transform[1][2], view.transform[2][2]) if geo2.Vec3Dot(surfaceNormal, cameraZ) < 0: return self.renderObject.translation = geo2.Vec3Scale(translation, rescale) self.renderObject.rotation = rotation self.renderObject.scaling = geo2.Vec3Scale(scaling, rescale) scaling, rotation, translation = geo2.MatrixDecompose(view.transform) translation = geo2.Vec3Scale(translation, rescale) view.transform = geo2.MatrixTransformation(None, None, scaling, None, rotation, translation) return self.renderObject.PickObject(x, y, projection, view, trinity.device.viewport)
def GetTransitEyeCurve(self, eyePos, atPos, newDir, atCurve): """ Returns control points for the eye transit curve spline. To get a smooth transition, we do a linear interpolation of the rotation around the y-axis, radius and y-value. """ currDir = self.GetLookAtDirection() try: angle = math.acos(geo2.Vec3Dot(currDir, newDir)) except ValueError: angle = 0 th0 = math.atan2(currDir[2], currDir[0]) th0 = self.ClampAngle(th0) th1 = math.atan2(newDir[2], newDir[0]) th1 = self.ClampAngle(th1) if th0 - th1 > math.pi: th0 -= 2 * math.pi elif th1 - th0 > math.pi: th1 -= 2 * math.pi r0 = geo2.Vec3Distance((self.eyePosition[0], 0, self.eyePosition[2]), (self.atPosition[0], 0, self.atPosition[2])) r1 = geo2.Vec3Distance((eyePos[0], 0, eyePos[2]), (atPos[0], 0, atPos[2])) y0 = self.eyePosition[1] - self.atPosition[1] y1 = eyePos[1] - atPos[1] points = [] for i, atPoint in enumerate(atCurve): t = self._GetHermiteValue(float(i) / len(atCurve)) r = r0 + t * (r1 - r0) th = th0 + t * (th1 - th0) y = y0 + t * (y1 - y0) point = (r * math.cos(th), y, r * math.sin(th)) point = geo2.Vec3Add(point, atCurve[i]) points.append(point) return points
def GetSolidAroundLine(line, radius): rad = math.pi * 2.0 / 3.0 triangle1 = [] triangle1.append((math.cos(0) * radius, math.sin(0) * radius, 0.0)) triangle1.append((math.cos(rad) * radius, math.sin(rad) * radius, 0.0)) triangle1.append( (math.cos(2 * rad) * radius, math.sin(2 * rad) * radius, 0.0)) dirOfLine = geo2.Vec3Normalize(geo2.Vec3Subtract(line[1], line[0])) if abs(geo2.Vec3Dot((0.0, 0.0, 1.0), dirOfLine)) != 1.0: rot = geo2.QuaternionRotationArc((0.0, 0.0, 1.0), dirOfLine) else: rot = geo2.QuaternionIdentity() rot = geo2.MatrixRotationQuaternion(rot) t1 = geo2.MatrixTranslation(*line[0]) t2 = geo2.MatrixTranslation(*line[1]) compA = geo2.MatrixMultiply(rot, t1) compB = geo2.MatrixMultiply(rot, t2) startTri = geo2.Vec3TransformCoordArray(triangle1, compA) endTri = geo2.Vec3TransformCoordArray(triangle1, compB) triangles = [ startTri[1], endTri[0], startTri[0], endTri[1], endTri[0], startTri[1], startTri[2], endTri[1], startTri[1], endTri[2], endTri[1], startTri[2], startTri[0], endTri[2], startTri[2], endTri[0], endTri[2], startTri[0] ] return triangles
def AddExplosion(self, uniqueName, explosionGfxID, spreadOut): if uniqueName not in self.districts: self.logger.error('Could not find district %s for planet with id %s', str(uniqueName), str(self.itemID)) graphics = GetGraphic(explosionGfxID) if graphics is None: self.logger.error("Explosion graphicsID %s doesn't exist!", str(explosionGfxID)) return fx = trinity.Load(graphics.graphicFile) if fx is None: self.logger.error("Explosion %s doesn't exist!", str(graphics.graphicFile)) return if len(fx.curveSets) == 0: self.logger.error('Explosion %s has no curveSets! This is useless...', str(graphics.graphicFile)) return direction = self.districts[uniqueName].centerNormal rotMatrix1 = geo2.MatrixRotationAxis((direction[1], direction[2], direction[0]), random.random() * spreadOut * self.districts[uniqueName].pinRadius) rotMatrix2 = geo2.MatrixRotationAxis(direction, random.uniform(0, 2.0 * math.pi)) direction = geo2.Vec3TransformNormal(direction, rotMatrix1) direction = geo2.Vec3TransformNormal(direction, rotMatrix2) fx.translation = direction fx.scaling = (5000.0 / PLANET_SIZE_SCALE, 5000.0 / PLANET_SIZE_SCALE, 5000.0 / PLANET_SIZE_SCALE) v1 = geo2.Vec3Cross(geo2.Vec3Normalize(direction), (0.0, 1.0, 0.0)) alpha = -math.acos(geo2.Vec3Dot(geo2.Vec3Normalize(direction), (0.0, 1.0, 0.0))) fx.rotation = geo2.QuaternionRotationAxis(v1, alpha) duration = fx.curveSets[0].GetMaxCurveDuration() self.districtExplosions.children.append(fx) uthread.new(self._RemoveExplosionFromDistrict, fx, duration)
def NewDirectionObstacleCheck(self, destYaw, heading): """ Calculates the direction we want to move in, performs a raycast to a specified length. The compares the collision normal if there is one with the direction vector to determine if angle between them is such where we will allow the character to walk and graze the wall. """ entity = self.entityClient.GetPlayerEntity() gw = GameWorld.Manager.GetGameWorld(long(entity.scene.sceneID)) posComp = entity.GetComponent('position') movComp = entity.GetComponent('movement') start = posComp.position start = geo2.Vec3Add( start, (0.0, self.AVATAR_COLLISION_DETECTION_CAPSULE_HEIGHT_MOD * movComp.characterController.height, 0.0)) yaw, pitch, roll = geo2.QuaternionRotationGetYawPitchRoll( posComp.rotation) direction = geo2.QuaternionRotationSetYawPitchRoll(yaw + destYaw, 0, 0) end = heading end = geo2.QuaternionTransformVector(direction, end) direction = end = geo2.Vec3Scale( end, self.AVATAR_COLLISION_DETECTION_FEELER_LENGTH) end = geo2.Vec3Add(end, start) hitResult = gw.SweptSphere( start, end, self.AVATAR_COLLISION_DETECTION_FEELER_RADIUS) result = False if hitResult: dotProduct = geo2.Vec3Dot(direction, hitResult[1]) if abs(dotProduct) > self.AVATAR_COLLISION_RESTRICTION_ANGLE_DP: result = True return result
def Orbit(self, yaw, pitch): dev = trinity.device self.Focus(self.pointOfInterest) up = geo2.Vector(0.0, 1.0, 0.0) t = geo2.Vector(self.localViewMatrix[1][0], self.localViewMatrix[1][1], self.localViewMatrix[1][2]) if geo2.Vec3Dot(t, up) <= 0.0: pitch = -pitch yaw = -yaw pos = self.GetPosition() target = self.pointOfInterest view = geo2.Subtract(pos, target) view = geo2.Vec3Normalize(view) right = geo2.Vec3Cross(view, up) mat = self.localViewMatrix ipmat = geo2.MatrixTranslation(-target[0], -target[1], -target[2]) pmat = geo2.MatrixTranslation(target[0], target[1], target[2]) mat = geo2.MatrixInverse(mat) yrotMat = geo2.MatrixRotationAxis(up, yaw) rrotMat = geo2.MatrixRotationAxis(right, pitch) yrotMat = geo2.MatrixMultiply(yrotMat, rrotMat) mat = geo2.MatrixMultiply(mat, ipmat) mat = geo2.MatrixMultiply(mat, yrotMat) mat = geo2.MatrixMultiply(mat, pmat) self._position = geo2.MatrixDecompose(mat)[2] mat = geo2.MatrixInverse(mat) self.localViewMatrix = mat
def GetMaxLookAtWeight_Facing(ent, targetPos): sourcePos = ent.GetComponent('position').position sourceRot = ent.GetComponent('position').rotation source2Target = geo2.Vec3Subtract(targetPos, sourcePos) source2Target = geo2.Vec3Normalize(source2Target) facingDir = mathCommon.CreateDirectionVectorFromYawAngle(geo2.QuaternionRotationGetYawPitchRoll(sourceRot)[0]) dot = geo2.Vec3Dot(source2Target, facingDir) return max(dot, 0)
def GetAngleLookAtToUpDirection(self): try: vLookAt = self.GetLookAtDirectionWithOffset() return math.acos( geo2.Vec3Dot(vLookAt, self.upDirection) / (geo2.Vec3Length(vLookAt) * geo2.Vec3Length(self.upDirection))) except ValueError: return 0.0
def GetRotationDurationFromVectors(self, startVec, endVec): dotProduct = geo2.Vec3Dot(startVec, endVec) try: angle = math.acos(dotProduct) except ValueError: angle = 0.5 return max(0.01, angle / CONE_ROTATION_SPEED)
def DistanceFromSegment(self, p, p0, p1, v, c2): w = geo2.Vec3Subtract(p, p0) c1 = geo2.Vec3Dot(v, w) if c1 <= 0: return None if c2 <= c1: return geo2.Vec3Distance(p, p1) return geo2.Vec3Distance(p, geo2.Vec3Add(p0, geo2.Vec3Scale(v, c1 / c2)))
def _GetNewLookAtEyePos(self, atPos1, itemID, radius): typeID = self.lookAtBall.typeID if typeID and evetypes.GetGroupID(typeID) == invconst.groupBillboard: direction = GetSpeedDirection(self.lookAtBall) if geo2.Vec3Dot(self.GetLookAtDirection(), direction) < 0: direction = geo2.Vec3Scale(direction, -1) radius = self.lookAtBall.radius * 5 else: direction = self.GetLookAtDirection() eyePos1 = geo2.Vec3Add(atPos1, geo2.Vec3Scale(direction, radius)) return eyePos1
def _TransformAxis(self, v): dev = trinity.device pos = self.GetTranslation() if self.activeManipAxis == 'w': self.targetPos = pos - self.endPlanePos scale = abs(1.0 + float(self.curX - self.startScreenX) / dev.width * 4.0) self.scale = geo2.Vector(scale, scale, scale) else: dir = self.axis[self.activeManipAxis] self.targetPos = geo2.Vec3Scale(dir, geo2.Vec3Dot(pos - self.endPlanePos, dir)) if not self.startPos: self.startPos = self.targetPos start_len = geo2.Vec3Length(self.startPos) current_len = geo2.Vec3Length(self.targetPos) scale = current_len / start_len if geo2.Vec3Dot(self.startPos, self.targetPos) < 0: scale = -scale scale = abs(scale) self.scale = geo2.Vector(scale, scale, scale) return v
def RayToPlaneIntersection(P, d, Q, n): """ Computes the intersection of the ray defined by point P and direction d with the plane defined by the point Q and the normal n. If the P lies on the plane defined by n and Q, there are infinite number of intersection points, so the function returns P. d' = - Q.Dot(n) t = -(n.Dot(P) + d' )/n.Dot(d) S = P + t*d """ denom = geo2.Vec3Dot(n, d) if abs(denom) < 1e-05: return P else: distance = -geo2.Vec3Dot(Q, n) t = -(geo2.Vec3Dot(n, P) + distance) / denom S = geo2.Add(geo2.Scale(d, t), P) return S
def RayToPlaneIntersection(P, d, Q, n): """ The intersection point(S) on a plane where d shot from P would intersect the plane defined by Q and n. If the P lies on the plane defined by n and Q, there are infinite number of intersection points so the function returns P. d' = - Q.Dot(n) t = -(n.Dot(P) + d' )/n.Dot(d) S = P + t*d """ denom = geo2.Vec3Dot(n, d) if abs(denom) < 1e-05: return P else: distance = -geo2.Vec3Dot(Q, n) t = -(geo2.Vec3Dot(n, P) + distance) / denom scaledRay = geo2.Vector(*d) * t P += scaledRay return P
def GetRandomHemisphereVector(axis): radius = geo2.Vec3Length(axis) randVec = RandomVector(radius) dotProduct = geo2.Vec3Dot(randVec, axis) if dotProduct <= 0: randVec = list(randVec) for i in xrange(len(randVec)): if abs(axis[i] - randVec[i]) > radius: randVec[i] *= -1 randVec = tuple(randVec) return randVec
def GetDesiredPlaneNormal(self, ray): x_axis = X_AXIS y_axis = Y_AXIS z_axis = Z_AXIS if self.activeManipAxis: if self.activeManipAxis == 'x': ydot = abs(geo2.Vec3Dot(ray, y_axis)) zdot = abs(geo2.Vec3Dot(ray, z_axis)) if zdot > ydot: return z_axis if ydot > zdot: return y_axis elif self.activeManipAxis == 'y': zdot = abs(geo2.Vec3Dot(ray, z_axis)) xdot = abs(geo2.Vec3Dot(ray, x_axis)) if zdot > xdot: return z_axis if xdot > zdot: return x_axis elif self.activeManipAxis == 'z': xdot = abs(geo2.Vec3Dot(ray, x_axis)) ydot = abs(geo2.Vec3Dot(ray, y_axis)) if xdot > ydot: return x_axis if ydot > xdot: return y_axis else: viewMat = trinity.GetViewTransform() return geo2.Vector(viewMat[0][2], viewMat[1][2], viewMat[2][2]) else: return None
def Render(self): if self.display: viewTrans = trinity.GetViewTransform() view = geo2.Vector(viewTrans[0][2], viewTrans[1][2], viewTrans[2][2]) localpos = self.GetTranslation() campos = geo2.Vector(*trinity.GetViewPosition()) vec = localpos - campos vec = geo2.Vec3Normalize(vec) if geo2.Vec3Dot(vec, view) > 0.0: mat = self.GetTargetPlaneProjectionMatrix() areas = self.geometry.Update(mat) self.geometry.Render(self.Cull(areas))
def Focus(self, point, dist = -1.0): dev = trinity.device pos = self.GetPosition() up = (0.0, 1.0, 0.0) t = (self.localViewMatrix[1][0], self.localViewMatrix[1][1], self.localViewMatrix[1][2]) if geo2.Vec3Dot(t, up) <= 0.0: up = (0.0, -1.0, 0.0) self.pointOfInterest = point self.localViewMatrix = geo2.MatrixLookAtRH(pos, point, up) if dist > 0.0: view = geo2.Vec3Subtract(pos, point) view = geo2.Vec3Normalize(view) self.SetPosition(geo2.Vec3Add(point, geo2.Vec3Scale(view, dist)))
def GetRandomHemisphereVector(axis): """ Returns a random vector on the hemisphere centered on the given axis """ radius = geo2.Vec3Length(axis) randVec = RandomVector(radius) dotProduct = geo2.Vec3Dot(randVec, axis) if dotProduct <= 0: randVec = list(randVec) for i in xrange(len(randVec)): if abs(axis[i] - randVec[i]) > radius: randVec[i] *= -1 randVec = tuple(randVec) return randVec
def GetDesiredPlaneNormal(self, ray): viewMat = trinity.GetViewTransform() view = geo2.Vector(viewMat[0][2], viewMat[1][2], viewMat[2][2]) local_axis = {'x': self.GetRightVec(), 'y': self.GetUpVec(), 'z': self.GetFrontVec()} if self.activeManipAxis in local_axis: axis = local_axis[self.activeManipAxis] if geo2.Vec3Dot(view, axis) > 0.0: norm = -axis else: norm = axis else: norm = view norm = geo2.Vec3Normalize(norm) return norm
def _DiffProjectedPoint(self, ray, start): self.endPlanePos = RayToPlaneIntersection(start, ray, self.GetTranslation(), self.targetPlaneNormal) displacement = self.endPlanePos - self.startPlanePos self.startPlanePos = self.endPlanePos if self.activeManipAxis == 'w': finalDisplacement = displacement else: if self.activeManipAxis == 'x': dir = self.GetRightVec() elif self.activeManipAxis == 'y': dir = self.GetUpVec() elif self.activeManipAxis == 'z': dir = self.GetFrontVec() dir = geo2.Vec3Normalize(dir) scaledDir = geo2.Vec3Scale(dir, geo2.Vec3Dot(displacement, dir)) finalDisplacement = scaledDir return finalDisplacement