def transform_wavefront_file(src_file_path, dest_file_path, transform_matrix): dest_dir = path.dirname(dest_file_path) if (not path.exists(dest_dir)): os.makedirs(dest_dir) src_file = open(src_file_path, 'r') dest_file = open(dest_file_path, 'w') # Keep a separated non-translation matrix to use on the mesh's vertex normal non_translation_matrix = Matrix44.from_matrix33(transform_matrix.matrix33) # print("non_translation_matrix: {}".format(non_translation_matrix)) # Parse each lines in the original mesh file for line in src_file: line_args = line.split() if len(line_args): type = line_args[0] # Transform each vertex if (type == 'v'): src_vertex = pyrr.Vector4([float(line_args[1]), float(line_args[2]), float(line_args[3]), 1.0]) dest_vertex = transform_matrix * src_vertex dest_file.write("v {:.6f} {:.6f} {:.6f}\n".format(dest_vertex.x, dest_vertex.y, dest_vertex.z)) continue # Transform each vertex normal of the mesh elif (type == 'vn'): src_vertex = pyrr.Vector4([float(line_args[1]), float(line_args[2]), float(line_args[3]), 1.0]) dest_vertex = non_translation_matrix * src_vertex dest_vertex = pyrr.vector.normalize([dest_vertex.x, dest_vertex.y, dest_vertex.z]) dest_file.write("vn {:.6f} {:.6f} {:.6f}\n".format(dest_vertex[0], dest_vertex[1], dest_vertex[2])) continue dest_file.write(line) src_file.close() dest_file.close()
def sun_shadowmap_matrix(sun_from_world_matrix, view_from_world_matrix, near, far): INFINITY = float('inf') aabb = { 'min': pyrr.Vector3([INFINITY, INFINITY, INFINITY]), 'max': pyrr.Vector3([-INFINITY, -INFINITY, -INFINITY]) } for corner in frustum_corners(view_from_world_matrix, near, far): corner = sun_from_world_matrix * corner aabb['min'].x = min(aabb['min'].x, corner.x) aabb['min'].y = min(aabb['min'].y, corner.y) aabb['min'].z = min(aabb['min'].z, corner.z) aabb['max'].x = max(aabb['max'].x, corner.x) aabb['max'].y = max(aabb['max'].y, corner.y) aabb['max'].z = max(aabb['max'].z, corner.z) world_from_light_space = sun_from_world_matrix.inverse size = aabb['max'] - aabb['min'] aabb['min'] = world_from_light_space * pyrr.Vector4( [*aabb['min'].tolist(), 1.0]) aabb['max'] = world_from_light_space * pyrr.Vector4( [*aabb['max'].tolist(), 1.0]) center = (aabb['min'] + aabb['max']) / 2.0 center = pyrr.Vector3(center.tolist()[:3]) scale = pyrr.Matrix44.from_scale(size) translate = pyrr.Matrix44.from_translation(center) matrix = translate * world_from_light_space * scale screen = pyrr.Matrix44([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1]) return screen * matrix.inverse
def v4Normalize(v=(DataTypes.FloatVector4, pyrr.Vector4()), result=(DataTypes.Reference, (DataTypes.Bool, False))): '''Normalizes a single vector to unit length.\nIf zero-length - returns original one.''' try: res = pyrr.Vector4(pyrr.vector.normalize(v)) result(True) return res except: result(False) return v
def v4Normalize(v=('FloatVector4Pin', pyrr.Vector4()), result=("Reference", ('BoolPin', False))): '''Normalizes a single vector to unit length.\nIf zero-length - returns original one.''' try: res = pyrr.Vector4(pyrr.vector.normalize(v)) result(True) return res except: result(False) return v
def asDataTypeClass(self): return pyrr.Vector4([ self.dsbX.value(), self.dsbY.value(), self.dsbZ.value(), self.dsbW.value() ])
def test_rotation(): a = radiant.Object3D() assert a.dirty is True a.update() assert a.dirty is False values = [ pyrr.Quaternion.from_x_rotation(0), pyrr.Matrix33.from_x_rotation(0), pyrr.Matrix44.from_x_rotation(0), pyrr.Vector3([0, 0, 0]), pyrr.Vector4([0, 0, 0, 1]), np.array([0, 0, 0]), np.array([0, 0, 0, 1]), np.identity(4), np.identity(3), np.array([0, 0, 0]).tolist(), np.array([0, 0, 0, 1]).tolist(), np.identity(4).tolist(), np.identity(3).tolist(), ] for value in values: a.rotation = value assert a.dirty is True a.update() assert a.dirty is False npt.assert_array_equal(a.rotation, [0., 0., 0., 1.]) assert a.rotation.dtype.kind == 'f' assert a.rotation.dtype.itemsize == 4 assert isinstance(a.rotation, pyrr.Quaternion)
def get_sun_cascades(sun_from_world_matrix, projection_matrix, view_from_world_matrix, cascades_count, cascades_distribution_scalar, cascades_max_distance): cascades = [] splits = [] #if is ortho if projection_matrix[3][3] == 1.0: for i in range(cascades_count): split = -1.0 + (2.0 / cascades_count) * (i + 1) splits.append(split) #is perspective else: clip_start = projection_matrix.inverse * pyrr.Vector4([0, 0, 0, 1]) clip_start /= clip_start.w clip_start = clip_start.z def lerp(a, b, f): f = max(0, min(f, 1)) return a * (1.0 - f) + b * f n = clip_start f = -cascades_max_distance m = cascades_count for i in range(1, cascades_count + 1): split_log = n * pow(f / n, i / m) split_uniform = n + (f - n) * (i / m) split = lerp(split_uniform, split_log, cascades_distribution_scalar) projected = projection_matrix * pyrr.Vector4([0, 0, split, 1]) projected = (projected / projected.w) * (1.0 if projected.w >= 0 else -1.0) depth = projected.z splits.append(depth) for i in range(len(splits)): near = -1 if i > 0: near = splits[i - 1] far = splits[i] cascades.append( sun_shadowmap_matrix(sun_from_world_matrix, view_from_world_matrix, near, far)) return cascades
def test_imports(self): import pyrr pyrr.Vector4() pyrr.vector4.Vector4() pyrr.objects.vector4.Vector4() from pyrr import Vector4 from pyrr.objects import Vector4 from pyrr.objects.vector4 import Vector4
def get_sun_cascades(sun_from_world_matrix, projection_matrix, view_from_world_matrix, cascades_count, cascades_distribution_exponent): cascades = [] splits = [] #if is ortho if projection_matrix[3][3] == 1.0: for i in range(cascades_count): split = -1.0 + (2.0 / cascades_count) * (i + 1) splits.append(split) #is perspective else: clip_end = projection_matrix.inverse * pyrr.Vector4([0, 0, 1, 1]) clip_end /= clip_end.w clip_end = -clip_end.z step_size = clip_end / cascades_count for i in range(cascades_count): split = (i + 1) * step_size projected = projection_matrix * pyrr.Vector4([0, 0, -split, 1]) projected = (projected / projected.w) * (1.0 if projected.w >= 0 else -1.0) depth = projected.z #normalize depth (0,1) depth = depth * 0.5 + 0.5 #make steps less linear depth = depth**cascades_distribution_exponent #back to (-1,+1) range depth = depth * 2.0 - 1.0 splits.append(depth) for i in range(len(splits)): near = -1 if i > 0: near = splits[i - 1] far = splits[i] cascades.append( sun_shadowmap_matrix(sun_from_world_matrix, view_from_world_matrix, near, far)) return cascades
def get_sun_cascades(sun_from_world_matrix, projection_matrix, view_from_world_matrix, cascades_count, cascades_distribution_scalar, cascades_max_distance): cascades = [] splits = [] n, f = 0, 0 if projection_matrix[3][3] == 1.0: # ortho n = cascades_max_distance / 2 f = -cascades_max_distance / 2 else: # perspective clip_start = projection_matrix.inverse * pyrr.Vector4([0, 0, -1, 1]) clip_start /= clip_start.w n = clip_start.z f = -cascades_max_distance def lerp(a, b, f): f = max(0, min(f, 1)) return a * (1.0 - f) + b * f for i in range(cascades_count + 1): split_log = n * pow(f / n, i / cascades_count) split_uniform = n + (f - n) * (i / cascades_count) split = lerp(split_uniform, split_log, cascades_distribution_scalar) projected = projection_matrix * pyrr.Vector4([0, 0, split, 1]) projected = (projected / projected.w) * (1.0 if projected.w >= 0 else -1.0) splits.append(projected.z) for i in range(1, len(splits)): near = splits[i - 1] far = splits[i] cascades.append( sun_shadowmap_matrix(sun_from_world_matrix, view_from_world_matrix, near, far)) return cascades
def frustum_corners(view_from_world_matrix, near, far): m = view_from_world_matrix.inverse corners = [] for x in (-1, 1): for y in (-1, 1): for z in (near, far): v = pyrr.Vector4([x, y, z, 1]) v = m * v v /= v.w corners.append(v) return corners
def v4Len(v=('FloatVector4Pin', pyrr.Vector4())): '''Returns the length of a vector.''' return pyrr.vector.length(v)
def v4SquaredLen(v=('FloatVector4Pin', pyrr.Vector4())): '''Calculates the squared length of a vector.\nUseful when trying to avoid the performance penalty of a square root operation.''' return pyrr.vector.squared_length(v)
def v4Create(a=('FloatPin', 0.0), b=('FloatPin', 0.0), c=('FloatPin', 0.0), W=('FloatPin', 0.0)): '''Creates vector4 from given components.''' return pyrr.Vector4([a, b, c, W])
def v4FromV3(v=('FloatVector3Pin', pyrr.Vector4())): '''Creates vector4 from vector3.''' return pyrr.Vector4(pyrr.vector4.create_from_vector3(v))
class Vector4(FunctionLibraryBase): '''doc string for Vector4''' def __init__(self, packageName): super(Vector4, self).__init__(packageName) @staticmethod @IMPLEMENT_NODE(returns=('FloatVector4Pin', pyrr.Vector4()), meta={ 'Category': 'Math|Vector4', 'Keywords': ['vector4'] }) def v4Create(): '''Zero vector4.''' return pyrr.Vector4() @staticmethod @IMPLEMENT_NODE(returns=('StringPin', str(pyrr.Vector4())), meta={ 'Category': 'Math|Vector4', 'Keywords': ['vector4'] }) def v4ToStr(v=('FloatVector4Pin', pyrr.Vector4())): return str(v) @staticmethod @IMPLEMENT_NODE(returns=('FloatVector4Pin', pyrr.Vector4()), meta={ 'Category': 'Math|Vector4', 'Keywords': ['vector4'] }) def v4FromUnitLenX(): '''Unit length x vector4.''' return pyrr.Vector4(pyrr.vector4.create_unit_length_x()) @staticmethod @IMPLEMENT_NODE(returns=('FloatVector4Pin', pyrr.Vector4()), meta={ 'Category': 'Math|Vector4', 'Keywords': ['vector4'] }) def v4FromUnitLenY(): '''Unit length y vector4.''' return pyrr.Vector4(pyrr.vector4.create_unit_length_y()) @staticmethod @IMPLEMENT_NODE(returns=('FloatVector4Pin', pyrr.Vector4()), meta={ 'Category': 'Math|Vector4', 'Keywords': ['vector4'] }) def v4FromUnitLenZ(): '''Unit length z vector4.''' return pyrr.Vector4(pyrr.vector4.create_unit_length_z()) @staticmethod @IMPLEMENT_NODE(returns=('FloatVector4Pin', pyrr.Vector4()), meta={ 'Category': 'Math|Vector4', 'Keywords': ['vector4'] }) def v4FromUnitLenW(): '''Unit length w vector4.''' return pyrr.Vector4(pyrr.vector4.create_unit_length_w()) @staticmethod @IMPLEMENT_NODE(returns=('FloatVector4Pin', pyrr.Vector4()), meta={ 'Category': 'Math|Vector4', 'Keywords': ['vector4'] }) def v4FromV3(v=('FloatVector3Pin', pyrr.Vector4())): '''Creates vector4 from vector3.''' return pyrr.Vector4(pyrr.vector4.create_from_vector3(v)) @staticmethod @IMPLEMENT_NODE(returns=('FloatPin', 0.0), meta={ 'Category': 'Math|Vector4', 'Keywords': ['vector4'] }) def v4X(v=('FloatVector4Pin', pyrr.Vector4())): '''Returns x component of the vector4.''' return v.x @staticmethod @IMPLEMENT_NODE(returns=('FloatPin', 0.0), meta={ 'Category': 'Math|Vector4', 'Keywords': ['vector4'] }) def v4Y(v=('FloatVector4Pin', pyrr.Vector4())): '''Returns y component of the vector4.''' return v.y @staticmethod @IMPLEMENT_NODE(returns=('FloatPin', 0.0), meta={ 'Category': 'Math|Vector4', 'Keywords': ['vector4'] }) def v4Z(v=('FloatVector4Pin', pyrr.Vector4())): '''Returns z component of the vector4.''' return v.z @staticmethod @IMPLEMENT_NODE(returns=('FloatPin', 0.0), meta={ 'Category': 'Math|Vector4', 'Keywords': ['vector4'] }) def v4W(v=('FloatVector4Pin', pyrr.Vector4())): '''Returns w component of the vector4.''' return v.w @staticmethod @IMPLEMENT_NODE(returns=('FloatVector4Pin', pyrr.Vector4()), meta={ 'Category': 'Math|Vector4', 'Keywords': ['vector4', '+'] }) def v4Add(a=('FloatVector4Pin', pyrr.Vector4()), b=('FloatVector4Pin', pyrr.Vector4())): '''Adds vector4 a and b.''' return a + b @staticmethod @IMPLEMENT_NODE(returns=('FloatVector4Pin', pyrr.Vector4()), meta={ 'Category': 'Math|Vector4', 'Keywords': ['vector4', '-'] }) def v4Substract(a=('FloatVector4Pin', pyrr.Vector4()), b=('FloatVector4Pin', pyrr.Vector4())): '''Substracts vector a and b.''' return a - b @staticmethod @IMPLEMENT_NODE(returns=('FloatPin', 0.0), meta={ 'Category': 'Math|Vector4', 'Keywords': ['vector4', '|'] }) def v4Dot(a=('FloatVector4Pin', pyrr.Vector4()), b=('FloatVector4Pin', pyrr.Vector4())): '''Dot product of two vectors.''' return a | b @staticmethod @IMPLEMENT_NODE(returns=('FloatVector4Pin', pyrr.Vector4()), meta={ 'Category': 'Math|Vector4', 'Keywords': ['vector4'] }) def v4Lerp(a=('FloatVector4Pin', pyrr.Vector4()), b=('FloatVector4Pin', pyrr.Vector4([1.0, 1.0, 1.0, 1.0])), alpha=('FloatPin', 0.0)): '''Vector4 lerp.''' return pyrr.Vector4( pyrr.vector.interpolate(a, b, clamp(alpha, 0.0, 1.0))) @staticmethod @IMPLEMENT_NODE(returns=('BoolPin', True), meta={ 'Category': 'Math|Vector4', 'Keywords': ['vector4', '=='] }) def v4Equals(a=('FloatVector4Pin', pyrr.Vector4()), b=('FloatVector4Pin', pyrr.Vector4())): '''Check if vectors are equals.''' return a == b @staticmethod @IMPLEMENT_NODE(returns=('FloatPin', 0.0), meta={ 'Category': 'Math|Vector4', 'Keywords': ['vector4'] }) def v4Len(v=('FloatVector4Pin', pyrr.Vector4())): '''Returns the length of a vector.''' return pyrr.vector.length(v) @staticmethod @IMPLEMENT_NODE(returns=('FloatPin', 0.0), meta={ 'Category': 'Math|Vector3', 'Keywords': ['vector4'] }) def v4SquaredLen(v=('FloatVector4Pin', pyrr.Vector4())): '''Calculates the squared length of a vector.\nUseful when trying to avoid the performance penalty of a square root operation.''' return pyrr.vector.squared_length(v) @staticmethod @IMPLEMENT_NODE(returns=('FloatVector4Pin', pyrr.Vector4()), meta={ 'Category': 'Math|Vector4', 'Keywords': ['vector4'] }) def v4Normalize(v=('FloatVector4Pin', pyrr.Vector4()), result=("Reference", ('BoolPin', False))): '''Normalizes a single vector to unit length.\nIf zero-length - returns original one.''' try: res = pyrr.Vector4(pyrr.vector.normalize(v)) result(True) return res except: result(False) return v @staticmethod @IMPLEMENT_NODE(returns=('FloatPin', 0.0), meta={ 'Category': 'Math|Vector4', 'Keywords': ['vector4', 'resize'] }) def v4SetLen(v=('FloatVector4Pin', pyrr.Vector4()), length=('FloatPin', 0.0)): '''Resizes a vector to "length".''' return pyrr.Vector4(pyrr.vector.set_length(v, length)) @staticmethod @IMPLEMENT_NODE(returns=('FloatVector4Pin', pyrr.Vector4()), meta={ 'Category': 'Math|Vector4', 'Keywords': ['vector4'] }) def v4Create(a=('FloatPin', 0.0), b=('FloatPin', 0.0), c=('FloatPin', 0.0), W=('FloatPin', 0.0)): '''Creates vector4 from given components.''' return pyrr.Vector4([a, b, c, W]) @staticmethod @IMPLEMENT_NODE(returns=('FloatVector4Pin', pyrr.Vector4()), meta={ 'Category': 'Math|Vector4', 'Keywords': ['vector4'] }) def v4FromM44Tr(m=('Matrix44Pin', pyrr.Matrix44())): '''Create vector4 from matrix44 translation.''' return pyrr.Vector4(pyrr.vector4.create_from_matrix44_translation(m))
def v4FromUnitLenY(): '''Unit length y vector4.''' return pyrr.Vector4(pyrr.vector4.create_unit_length_y())
def v4ToStr(v=('FloatVector4Pin', pyrr.Vector4())): return str(v)
def v4SetLen(v=('FloatVector4Pin', pyrr.Vector4()), length=('FloatPin', 0.0)): '''Resizes a vector to "length".''' return pyrr.Vector4(pyrr.vector.set_length(v, length))
def v4Add(a=('FloatVector4Pin', pyrr.Vector4()), b=('FloatVector4Pin', pyrr.Vector4())): '''Adds vector4 a and b.''' return a + b
def v4FromM44Tr(m=('Matrix44Pin', pyrr.Matrix44())): '''Create vector4 from matrix44 translation.''' return pyrr.Vector4(pyrr.vector4.create_from_matrix44_translation(m))
def v4Substract(a=('FloatVector4Pin', pyrr.Vector4()), b=('FloatVector4Pin', pyrr.Vector4())): '''Substracts vector a and b.''' return a - b
def v4FromUnitLenX(): '''Unit length x vector4.''' return pyrr.Vector4(pyrr.vector4.create_unit_length_x())
def v4Dot(a=('FloatVector4Pin', pyrr.Vector4()), b=('FloatVector4Pin', pyrr.Vector4())): '''Dot product of two vectors.''' return a | b
def v4FromUnitLenZ(): '''Unit length z vector4.''' return pyrr.Vector4(pyrr.vector4.create_unit_length_z())
def v4Lerp(a=('FloatVector4Pin', pyrr.Vector4()), b=('FloatVector4Pin', pyrr.Vector4([1.0, 1.0, 1.0, 1.0])), alpha=('FloatPin', 0.0)): '''Vector4 lerp.''' return pyrr.Vector4( pyrr.vector.interpolate(a, b, clamp(alpha, 0.0, 1.0)))
def v4FromUnitLenW(): '''Unit length w vector4.''' return pyrr.Vector4(pyrr.vector4.create_unit_length_w())
def v4Create(): '''Zero vector4.''' return pyrr.Vector4()
def v4Y(v=('FloatVector4Pin', pyrr.Vector4())): '''Returns y component of the vector4.''' return v.y
def v4Equals(a=('FloatVector4Pin', pyrr.Vector4()), b=('FloatVector4Pin', pyrr.Vector4())): '''Check if vectors are equals.''' return a == b