def applyIdealDistance(self): if self.isActive(): self.idealDistance = clampScalar(self.idealDistance, self._minDistance, self._maxDistance) if self._practicalDistance is None: self._zoomToDistance(self.idealDistance)
def dartTask(self, task): for dart in self.dartList: desiredPos = dart.getDefaultPos() (newPos, theta) = self.clampSpherePtToHorizon(desiredPos) framePos = self._transSphereToFramePt(newPos) if -1.1000000000000001 < framePos[0]: pass framePos[0] < 1.1000000000000001 if 1: if -1.1000000000000001 < framePos[1]: pass framePos[1] < 1.1000000000000001 if 1: dart.setEdgeMode(False) dart.setPos(newPos) if theta: theta = clampScalar(0, math.pi / 4, theta) dart.setScale(-2 * theta / math.pi + 1) else: dart.setScale(1) dart.setPos(newPos) angle = math.atan2(-framePos[0], -framePos[1]) angle = angle * 180 / math.pi dart.setEdgeMode(True) dart.edgeModeNode.setR(angle) absFramePos = (abs(framePos[0]), abs(framePos[1])) markerFramePos = framePos / max(absFramePos) dart.edgeModeNode.setPos(markerFramePos[0], 0, markerFramePos[1]) return task.cont
def _mouseUpdateTask(self, task): if OrbitCamera._mouseUpdateTask(self, task) == task.cont or self.mouseDelta[0] or self.mouseDelta[1]: sensitivity = 0.5 self.camTimer = -1.0 self.setRotation(self.getRotation() - self.mouseDelta[0] * sensitivity) self.setEscapement(clampScalar(self.escapement + self.mouseDelta[1] * sensitivity * 0.59999999999999998, self._minEsc, self._maxEsc)) return task.cont
def clampSpherePtToHorizon(self, pt): camRaySpherePt = self.findCamRaySpherePt(pt) if camRaySpherePt and not pt.almostEqual(camRaySpherePt, 0.0001): camToSphere = self.cam.getTransform(self._rNode) OC = camToSphere.getMat().xformPoint(Vec3(0, 0, 0)) theta = math.acos( clampScalar(-1.0, 1.0, self._radius / OC.length())) axis = OC.cross(pt) axis.normalize() q = Quat(math.cos(theta / 2), axis * math.sin(theta / 2)) ts = TransformState.makeQuat(q) OC.normalize() OC *= self._radius newPt = ts.getMat().xformPoint(OC) dTheta = math.acos(clampScalar(-1.0, 1.0, pt.dot(newPt))) return (newPt, dTheta) else: return (pt, 0)
def getOrthTiltLimitQuat(self, thetaLimit=10): X = Vec3.unitX() Y = Vec3.unitY() Z = Vec3.unitZ() upSpaceNodePath = self rNodeNorth = Z arcballNorth = -Y baseQuat = self._rNode.getQuat(upSpaceNodePath) quatX = Quat.identQuat() quatY = Quat.identQuat() rNodeToUpSpace = TransformState.makeQuat(baseQuat) northPole = rNodeToUpSpace.getMat().xformPoint(rNodeNorth) dot = northPole.dot(X) proj = northPole - X * dot theta = math.acos( clampScalar(-1.0, 1.0, proj.dot(arcballNorth) / proj.length())) if theta > thetaLimit: theta -= thetaLimit if northPole.dot(Z) < 0.0: theta *= -1 quatX = Quat(math.cos(theta / 2.0), X * math.sin(theta / 2.0)) baseQuat *= quatX rNodeToUpSpace = TransformState.makeQuat(baseQuat) northPole = rNodeToUpSpace.getMat().xformPoint(rNodeNorth) dot = northPole.dot(Z) proj = northPole - Z * dot theta = math.acos( clampScalar(-1.0, 1.0, proj.dot(arcballNorth) / proj.length())) if theta > thetaLimit: theta -= thetaLimit if northPole.dot(X) >= 0.0: theta *= -1 quatY = Quat(math.cos(theta / 2.0), Z * math.sin(theta / 2.0)) baseQuat *= quatY return quatX * quatY
def _getRotateAboutAxisQuat(self, axis, p0, p1, factor=1.0): axis = axis / axis.length() dot0 = axis.dot(p0) proj0 = p0 - axis * dot0 dot1 = axis.dot(p1) proj1 = p1 - axis * dot1 axis = proj0.cross(proj1) area = axis.length() axis.normalize() theta = math.acos( clampScalar(-1, 1, proj0.dot(proj1) / proj0.length() * proj1.length())) return (Quat(math.cos(theta / 2.0), axis * math.sin(theta / 2.0)), area)
def _getPtToPtQuat(self, p0, p1, factor=1.0): p0.normalize() p1.normalize() theta = math.acos(clampScalar(-1, 1, p0.dot(p1))) axis = p0.cross(p1) axis.normalize() if factor == 1.0: return Quat(math.cos(theta / 2.0), axis * math.sin(theta / 2.0)) elif 0.0 < factor: pass elif factor == 1.0: q = nLerp( Quat.identQuat(), Quat(math.cos(theta / 2.0), axis * math.sin(theta / 2.0)), factor) return q
def _lerpEscapement(self, escapement, duration=None): curEsc = self.getEscapement() escapement = clampScalar(escapement, self._minEsc, self._maxEsc) if duration is None: diff = abs(curEsc - escapement) speed = (max(curEsc, self._maxEsc) - min(curEsc, self._minEsc)) * 0.025000000000000001 duration = diff / speed self._stopEscapementLerp() self._escLerpIval = LerpFunctionInterval( self.setEscapement, fromData=curEsc, toData=escapement, duration=duration, blendType='easeOut', name='OrbitCamera.escapementLerp') self._escLerpIval.start()
def getTiltLimitQuat(self, thetaLimit): Y = Vec3.unitY() Z = Vec3.unitZ() upSpaceNodePath = self rNodeNorth = Z arcballNorth = -Y rNodeToUpSpace = TransformState.makeHpr( self._rNode.getHpr(upSpaceNodePath)) northPole = rNodeToUpSpace.getMat().xformPoint(rNodeNorth) dot = northPole.dot(arcballNorth) theta = math.acos(clampScalar(-1, 1, dot)) if theta < thetaLimit: return Quat.identQuat() else: axis = northPole.cross(arcballNorth) axis.normalize() theta -= thetaLimit return Quat(math.cos(theta / 2.0), axis * math.sin(theta / 2.0))
def __init__(self, name, worldMap, maxTilt=math.pi / 4, mapSize=2.0, *args, **kwargs): ArcBall.__init__(self, name, *args, **kwargs) self.worldMap = worldMap maxTilt = clampScalar(0, math.pi / 4.0, maxTilt) _maxDist = math.tan(maxTilt * 2) self.tsMat = Mat3( TransformState.makeScale2d(Vec2(_maxDist / mapSize / 2.0)).getMat3()) self.tsMatInv = invert(self.tsMat) self._mapOrigin = self.mapPosToSpherePt(Point2(0)) self._worldNorth = Point3(0, 1, 0) self._loadModels()
def getUprightCorrectionQuat(self, pt): Y = Vec3.unitY() Z = Vec3.unitZ() rNodeNorth = self._north upSpaceNodePath = self axis = pt / pt.length() up = Z rNodeToUpSpace = TransformState.makeHpr( self._rNode.getHpr(upSpaceNodePath)) northPole = rNodeToUpSpace.getMat().xformPoint(rNodeNorth) right = up.cross(axis) final = axis.cross(right) dot = northPole.dot(axis) proj = northPole - axis * dot theta = math.acos( clampScalar(-1.0, 1.0, proj.dot(final) / proj.length() * final.length())) if northPole.dot(right) < 0.0: theta *= -1 return Quat(math.cos(theta / 2.0), Vec3(axis) * math.sin(theta / 2.0))
def setZoom(self, zoom): self._zoom = clampScalar(0.0, 0.75, zoom) self.buffer.camera.setY(lerp(self.camY[0], self.camY[1], self._zoom)) self.mapBall._setTiltLimit(lerp(self.tiltLimit[0], self.tiltLimit[1], self._zoom)) self.mapBall.updateTextZoom(self._zoom)
def createCurvedArrow(self, axis, p0, p1, width, numPanels=10): N = numPanels self.tail_geom_node.removeAllGeoms() self.head_geom_node.removeAllGeoms() axis = axis / axis.length() dot0 = axis.dot(p0) proj0 = p0 - axis * dot0 dot1 = axis.dot(p1) proj1 = p1 - axis * dot1 theta = math.acos( clampScalar(-1, 1, proj0.dot(proj1) / proj0.length() * proj1.length())) if not proj0.almostEqual(proj1, 0.0001) and theta != 0: if proj0.lengthSquared() >= proj1.lengthSquared(): A = proj0 C = proj1 else: A = proj1 C = proj0 a = A.length() aUnit = A / a x = A.dot(C) / a yy = C.lengthSquared() - x * x bUnit = A.cross(C).cross(A) bUnit.normalize() b = math.sqrt(max(0.0, yy / (1 - x * x / a * a))) t = math.atan2(a, b / math.tan(theta)) aUnit *= a bUnit *= b pts = [ aUnit * math.cos(x * t / N) + bUnit * math.sin(x * t / N) for x in range(N + 1) ] pts = [ pt + axis * math.sqrt(self._radius * self._radius - pt.lengthSquared()) for pt in pts ] if A != proj0: pts.reverse() format = GeomVertexFormat.getV3c4t2() vertex_data = GeomVertexData('arc_ball', format, Geom.UHStatic) vertex_writer = GeomVertexWriter(vertex_data, 'vertex') color_writer = GeomVertexWriter(vertex_data, 'color') texture_writer = GeomVertexWriter(vertex_data, 'texcoord') triStrip = GeomTristrips(Geom.UHStatic) cross = pts[0].cross(pts[1] - pts[0]) cross.normalize() cross *= width / 2.0 pt = pts[0] vertex_writer.addData3f(pt[0] + cross[0], pt[1] + cross[1], pt[2] + cross[2]) vertex_writer.addData3f(pt[0] - cross[0], pt[1] - cross[1], pt[2] - cross[2]) color_writer.addData4f(0, 1, 0, 1) color_writer.addData4f(0, 1, 0, 1) texture_writer.addData2f(0, 1) texture_writer.addData2f(1, 1) diffA = pts[1] - pts[0] diffB = pts[2] - pts[1] cross = pts[1].cross((diffB + diffA) / 2.0) cross.normalize() cross *= width / 2.0 pt = pts[1] vertex_writer.addData3f(pt[0] + cross[0], pt[1] + cross[1], pt[2] + cross[2]) vertex_writer.addData3f(pt[0] - cross[0], pt[1] - cross[1], pt[2] - cross[2]) color_writer.addData4f(0, 1, 0, 1) color_writer.addData4f(0, 1, 0, 1) texture_writer.addData2f(0, 0) texture_writer.addData2f(1, 0) triStrip.addNextVertices(4) geometry = Geom(vertex_data) geometry.addPrimitive(triStrip) self.head_geom_node.addGeom(geometry) format = GeomVertexFormat.getV3c4t2() vertex_data = GeomVertexData('arc_ball', format, Geom.UHStatic) vertex_writer = GeomVertexWriter(vertex_data, 'vertex') color_writer = GeomVertexWriter(vertex_data, 'color') texture_writer = GeomVertexWriter(vertex_data, 'texcoord') triStrip = GeomTristrips(Geom.UHStatic) for x in range(len(pts[1:-1])): cross = pts[x + 1].cross(pts[x + 2] - pts[x]) cross.normalize() cross *= width / 2.0 pt = pts[x + 1] vertex_writer.addData3f(pt[0] + cross[0], pt[1] + cross[1], pt[2] + cross[2]) vertex_writer.addData3f(pt[0] - cross[0], pt[1] - cross[1], pt[2] - cross[2]) color_writer.addData4f(0, 1, 0, 1) color_writer.addData4f(0, 1, 0, 1) if x % 2: texture_writer.addData2f(0, 1) texture_writer.addData2f(1, 1) else: texture_writer.addData2f(0, 0) texture_writer.addData2f(1, 0) triStrip.addNextVertices(2) cross = pts[-1].cross(pts[-1] - pts[-2]) cross.normalize() cross *= width / 2.0 pt = pts[-1] vertex_writer.addData3f(pt[0] + cross[0], pt[1] + cross[1], pt[2] + cross[2]) vertex_writer.addData3f(pt[0] - cross[0], pt[1] - cross[1], pt[2] - cross[2]) color_writer.addData4f(0, 1, 0, 1) color_writer.addData4f(0, 1, 0, 1) if N % 2: texture_writer.addData2f(0, 0) texture_writer.addData2f(1, 0) else: texture_writer.addData2f(0, 1) texture_writer.addData2f(1, 1) triStrip.addNextVertices(2) geometry = Geom(vertex_data) geometry.addPrimitive(triStrip) self.tail_geom_node.addGeom(geometry)
def createStraightArrow(self, p0, p1, width): p0.normalize() p1.normalize() dot = p0.dot(p1) cross = p0.cross(p1) arcLen = math.acos(clampScalar(-1, 1, dot)) self.tail_geom_node.removeAllGeoms() self.head_geom_node.removeAllGeoms() if arcLen > 0.0: cross.normalize() cross *= width / 2.0 theta = 2 * math.asin(width / 2.0) div = arcLen / theta steps = int(div) remainder = div - steps pts = [] for n in range(steps + 1): pts.append(sLerp(p1, p0, n / div, arcLen) * self._radius) format = GeomVertexFormat.getV3c4t2() vertex_data = GeomVertexData('arc_ball', format, Geom.UHStatic) vertex_writer = GeomVertexWriter(vertex_data, 'vertex') color_writer = GeomVertexWriter(vertex_data, 'color') texture_writer = GeomVertexWriter(vertex_data, 'texcoord') triStrip = GeomTristrips(Geom.UHStatic) if len(pts) == 1: vertex_writer.addData3f(p1[0] - cross[0], p1[1] - cross[1], p1[2] - cross[2]) vertex_writer.addData3f(p1[0] + cross[0], p1[1] + cross[1], p1[2] + cross[2]) color_writer.addData4f(0, 1, 0, 1) color_writer.addData4f(0, 1, 0, 1) texture_writer.addData2f(1, 1) texture_writer.addData2f(0, 1) vertex_writer.addData3f(p0[0] - cross[0], p0[1] - cross[1], p0[2] - cross[2]) vertex_writer.addData3f(p0[0] + cross[0], p0[1] + cross[1], p0[2] + cross[2]) color_writer.addData4f(0, 1, 0, 1) color_writer.addData4f(0, 1, 0, 1) texture_writer.addData2f(1, 1 - remainder) texture_writer.addData2f(0, 1 - remainder) triStrip.addNextVertices(4) else: for pt in pts[:2]: vertex_writer.addData3f(pt[0] - cross[0], pt[1] - cross[1], pt[2] - cross[2]) vertex_writer.addData3f(pt[0] + cross[0], pt[1] + cross[1], pt[2] + cross[2]) color_writer.addData4f(0, 1, 0, 1) color_writer.addData4f(0, 1, 0, 1) texture_writer.addData2f(1, 1) texture_writer.addData2f(0, 1) texture_writer.addData2f(1, 0) texture_writer.addData2f(0, 0) triStrip.addNextVertices(4) geometry = Geom(vertex_data) geometry.addPrimitive(triStrip) self.head_geom_node.addGeom(geometry) format = GeomVertexFormat.getV3c4t2() vertex_data = GeomVertexData('arc_ball', format, Geom.UHStatic) vertex_writer = GeomVertexWriter(vertex_data, 'vertex') color_writer = GeomVertexWriter(vertex_data, 'color') texture_writer = GeomVertexWriter(vertex_data, 'texcoord') triStrip = GeomTristrips(Geom.UHStatic) for pt in pts[1:]: vertex_writer.addData3f(pt[0] - cross[0], pt[1] - cross[1], pt[2] - cross[2]) vertex_writer.addData3f(pt[0] + cross[0], pt[1] + cross[1], pt[2] + cross[2]) color_writer.addData4f(0, 1, 0, 1) color_writer.addData4f(0, 1, 0, 1) numPts = len(pts[1:]) for x in range(numPts / 2): texture_writer.addData2f(1, 1) texture_writer.addData2f(0, 1) texture_writer.addData2f(1, 0) texture_writer.addData2f(0, 0) if numPts % 2: texture_writer.addData2f(1, 1) texture_writer.addData2f(0, 1) vertex_writer.addData3f(p0[0] - cross[0], p0[1] - cross[1], p0[2] - cross[2]) vertex_writer.addData3f(p0[0] + cross[0], p0[1] + cross[1], p0[2] + cross[2]) color_writer.addData4f(0, 1, 0, 1) color_writer.addData4f(0, 1, 0, 1) if numPts % 2: texture_writer.addData2f(1, 1 - remainder) texture_writer.addData2f(0, 1 - remainder) else: texture_writer.addData2f(1, remainder) texture_writer.addData2f(0, remainder) triStrip.addNextVertices(numPts * 2 + 2) geometry = Geom(vertex_data) geometry.addPrimitive(triStrip) self.tail_geom_node.addGeom(geometry)