def calcFrustumLineObject(invViewProjMatrix): # get frustum points frustum = [ core.Vector3(-1.0, -1.0, -1.0), core.Vector3(1.0, -1.0, -1.0), core.Vector3(1.0, 1.0, -1.0), core.Vector3(-1.0, 1.0, -1.0), core.Vector3(-1.0, -1.0, 1.0), core.Vector3(1.0, -1.0, 1.0), core.Vector3(1.0, 1.0, 1.0), core.Vector3(-1.0, 1.0, 1.0) ] # camera to world-space for v in frustum: v.transform(invViewProjMatrix) obj = [None] * 6 obj[0] = frustum[0:4] # near poly ccw obj[1] = frustum[4:] # far poly ccw obj[2] = [frustum[0], frustum[3], frustum[7], frustum[4]] # left poly ccw obj[3] = [frustum[1], frustum[5], frustum[6], frustum[2]] # right poly ccw obj[4] = [frustum[4], frustum[5], frustum[1], frustum[0]] # bottom poly ccw obj[5] = [frustum[6], frustum[7], frustum[3], frustum[2]] # top poly ccw return obj
def __init__(self, type=TYPE_DIRECTIONAL, pos=core.Vector3(0, 1, 0), color=core.Color(1, 1, 1, 1)): core.Light.__init__(self, type, pos, color) self.constAttenuation = 1 self.linearAttenuation = 0 self.quadraticAttenuation = 0
def interpolate(self, t, type): x = Spline.splineInterpolate(self.p0.x, self.p1.x, self.p2.x, self.p3.x, t, type) y = Spline.splineInterpolate(self.p0.y, self.p1.y, self.p2.y, self.p3.y, t, type) z = Spline.splineInterpolate(self.p0.z, self.p1.z, self.p2.z, self.p3.z, t, type) return core.Vector3(x, y, z)
def lineObjectFromAABB(aabb): aabbMin = aabb.min aabbMax = aabb.max box = [ core.Vector3(aabbMin.x, aabbMin.y, aabbMin.z), core.Vector3(aabbMax.x, aabbMin.y, aabbMin.z), core.Vector3(aabbMax.x, aabbMax.y, aabbMin.z), core.Vector3(aabbMin.x, aabbMax.y, aabbMin.z), core.Vector3(aabbMin.x, aabbMin.y, aabbMax.z), core.Vector3(aabbMax.x, aabbMin.y, aabbMax.z), core.Vector3(aabbMax.x, aabbMax.y, aabbMax.z), core.Vector3(aabbMin.x, aabbMax.y, aabbMax.z) ] obj = [None] * 6 obj[0] = box[0:4] obj[1] = box[4:] obj[2] = [box[0], box[3], box[7], box[4]] obj[3] = [box[1], box[5], box[6], box[2]] obj[4] = [box[4], box[5], box[1], box[0]] obj[5] = [box[6], box[7], box[3], box[2]] return obj
def calcFocusedLightVolumePoints(invViewProj, lightDir, aabb): obj = calcFrustumLineObject(invViewProj) if aabb: obj = clipObjectByAABB(obj, aabb) else: points = [ core.Vector3(-1.0, -1.0, -1.0), core.Vector3(1.0, -1.0, -1.0), core.Vector3(1.0, 1.0, -1.0), core.Vector3(-1.0, 1.0, -1.0), core.Vector3(-1.0, -1.0, 1.0), core.Vector3(1.0, -1.0, 1.0), core.Vector3(1.0, 1.0, 1.0), core.Vector3(-1.0, 1.0, 1.0) ] # camera to world-space for v in points: v.transform(invViewProj) aabb = aabbFromPoints(points) return includeObjectLightVolume(obj, lightDir, aabb)
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.fixedFrameRate = 0.0 self.setGravity(core.Vector3(0, -10, 0))
def setDirection(self, dir): assert self.type is TYPE_DIRECTIONAL pos = -core.Vector3(dir) pos.normalize() self.position = pos
def direction(self): if self.type is TYPE_DIRECTIONAL: dir = -core.Vector3(self.position) dir.normalize() return dir
def setView(self, pos, dir, up=core.Vector3(0.0, 1.0, 0.0)): super().setView(pos, dir, up)
def lispSMMatrices(camera, lightDir, sceneAABB, useBodyVector=True): invViewProj = camera.viewProjectionMatrix() invViewProj.inverse() points = calcFocusedLightVolumePoints(invViewProj, lightDir, sceneAABB) cameraPos = camera.position() viewDir = camera.direction() dp = _dot(viewDir, lightDir) sinGamma = math.sqrt(1.0 - dp * dp) # calc up-vector if useBodyVector: newDir = calcBodyVector(points, cameraPos) left = _cross(lightDir, newDir) else: left = _cross(lightDir, viewDir) upVector = _normalize(_cross(left, lightDir)) # temporal light View # look from position (cameraPos) # into direction (lightDir) # with up vector (upVector) viewMatrix = calcViewMatrix(cameraPos, lightDir, upVector) # transform the light volume points from world into light space numPoints = len(points) pointsCopy = [None] * numPoints for i in range(numPoints): v = points[i] points[i] = _coreVector(v) pointsCopy[i] = _coreVector(v) points[i].transform(viewMatrix) # calculate cubic hull (AABB) aabb = aabbFromPoints(points) if numPoints > 0 else _frustumAabb points = pointsCopy del pointsCopy nearPt = core.Vector3(0, 0, -1) # frustum near-center nearPt.transform(invViewProj) # camera space to world space nearDist = (nearPt - cameraPos).length() # get camera near distance # LiSPSM formulas of the paper to get n (and f) factor = 1.0 / sinGamma z_n = factor * nearDist # often 1 d = abs(aabb.max.y - aabb.min.y) # perspective transform depth # light space y extents z_f = z_n + d * sinGamma n = (z_n + math.sqrt(z_f * z_n)) / sinGamma f = n + d # new observer point n-1 behind eye position # pos = eyePos-up*(n-nearDist) pos = _linear(cameraPos, upVector, -(n - nearDist)) viewMatrix = calcViewMatrix(pos, lightDir, upVector) # one possibility for a simple perspective transformation matrix # with the two parameters n(near) and f(far) in y direction # [ 1 0 0 0] a = (f+n)/(f-n) # [ 0 a 0 1] b = -2*f*n/(f-n) # [ 0 0 1 0] # [ 0 b 0 0] lispMatrix = core.Matrix4(1.0, 0.0, 0.0, 0.0, 0.0, (f + n) / (f - n), 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, -2.0 * f * n / (f - n), 0.0, 0.0) # temporal arrangement for the transformation of the points to post-perspective space lightProjection = viewMatrix * lispMatrix # transform the light volume points from world into the distorted light space for v in points: v.transform(lightProjection) # calculate the cubic hull (an AABB) aabb = aabbFromPoints(points) if numPoints > 0 else _frustumAabb # refit to unit cube projectionMatrix = calcProjectionMatrixForRHToFitAABB(aabb) return viewMatrix, lispMatrix * projectionMatrix
* b.y - a.y * b.x) _add = lambda a, b: Vector(a.x + b.x, a.y + b.y, a.z + b.z) _subtract = lambda a, b: Vector(a.x - b.x, a.y - b.y, a.z - b.z) _linear = lambda a, b, t: Vector(a.x + b.x * t, a.y + b.y * t, a.z + b.z * t) _lengthSq = lambda a: a.x * a.x + a.y * a.y + a.z * a.z _length = lambda a: math.sqrt(_lengthSq(a)) _mulScalar = lambda a, b: Vector(a.x * b, a.y * b, a.z * b) def _normalize(a): length = _length(a) return _mulScalar(a, 1.0 / length) if length > 0.0 else a _copyVector = lambda a: Vector(a.x, a.y, a.z) _coreVector = lambda a: core.Vector3(a.x, a.y, a.z) _epsilon = 0.001 _inf = float('inf') _fltMin = 1.175494351e-38 _fltMax = 3.402823466e+38 _dblMin = 2.2250738585072014e-308 _dblMax = 1.7976931348623158e+308 _isEqual = lambda a, b: abs(a.x - b.x) < _epsilon and abs( a.y - b.y) < _epsilon and abs(a.z - b.z) < _epsilon _frustumAabb = AABB(core.Vector3(-1.0, -1.0, -1.0), core.Vector3(1.0, 1.0, 1.0)) def calcFrustumLineObject(invViewProjMatrix):