Source code for liatool.illumination

import bpy
from mathutils.geometry import intersect_line_plane
import math


[docs] class Illumination(): def __init__(self, *, process, spaceProfile): self._process = process self._spaceProfile = spaceProfile self._illuminationMaterial = self._createIlluminationMaterial() def _createIlluminationMaterial(self): ilspDomain = self._process.ilspDomain illuminationNumber = 0 illuminationBasicName = ilspDomain.name + '_illumination_' for mat in bpy.data.materials: if illuminationBasicName in mat.name: number = int(mat.name.split(illuminationBasicName)[1]) if number >= illuminationNumber: illuminationNumber = number + 1 materialName = illuminationBasicName + str(illuminationNumber) illuminationMaterial = bpy.data.materials.new(materialName) if ilspDomain.data.materials: ilspDomain.data.materials[0] = illuminationMaterial else: ilspDomain.data.materials.append(illuminationMaterial) illuminationMaterial.use_nodes = True illumValues = illuminationMaterial.node_tree.nodes.new( type="ShaderNodeAttribute") colorRamp = illuminationMaterial.node_tree.nodes.new( type="ShaderNodeValToRGB") mathMultiply = illuminationMaterial.node_tree.nodes.new( type='ShaderNodeMath') mathMultiply.operation = 'MULTIPLY' mathMultiply.inputs[1].default_value = 1.0 mathMultiply.name = 'Multiply' # Add Math Node for addition mathAdd = illuminationMaterial.node_tree.nodes.new( type='ShaderNodeMath') mathAdd.operation = 'ADD' mathAdd.inputs[1].default_value = 0.0 mathAdd.name = 'Add' # position = 0.0 # createNew = True # for elem in colorRamp.color_ramp.elements: # if math.isclose(elem.position, position, rel_tol=1e-6): # elem.color = (0.8, 0.8, 0.8, 1) # createNew = False # if createNew: # elem = colorRamp.color_ramp.elements.new(position) # elem.color = (0.8, 0.8, 0.8, 1) # for color in self._spaceProfile.colorBar: # position = color[0] # elem = colorRamp.color_ramp.elements.new(position) # elem.color = color[1] colorRamp.color_ramp.elements.new(0.0) colorRamp.color_ramp.elements.new(0.0) colorRamp.color_ramp.elements.new(1.0) colorRamp.color_ramp.elements.new(1.0) colorRamp.color_ramp.elements[0].color = (0, 0, 1, 1) colorRamp.color_ramp.elements[1].color = (0, 0, 1, 1) colorRamp.color_ramp.elements[2].color = (0, 0, 1, 1) colorRamp.color_ramp.elements[3].color = (0, 1, 0, 1) colorRamp.color_ramp.elements[4].color = (1, 0, 0, 1) colorRamp.color_ramp.elements[5].color = (1, 0, 0, 1) shader = illuminationMaterial.node_tree.nodes["Principled BSDF"] output = illuminationMaterial.node_tree.nodes["Material Output"] illuminationMaterial.node_tree.links.new( illumValues.outputs['Fac'], mathMultiply.inputs[0]) illuminationMaterial.node_tree.links.new( mathMultiply.outputs['Value'], mathAdd.inputs[0]) illuminationMaterial.node_tree.links.new( mathAdd.outputs['Value'], colorRamp.inputs['Fac']) illuminationMaterial.node_tree.links.new( colorRamp.outputs['Color'], shader.inputs['Base Color']) illuminationMaterial.node_tree.links.new( shader.outputs['BSDF'], output.inputs['Surface']) return illuminationMaterial
[docs] def simulate(self, laserBeam): if self._process.processSteps is None: return min = float('inf') max = -float('inf') wm = bpy.context.window_manager wm.progress_begin(0, len(self._process.processSteps)) process = self._process illuminationMaterial = self._illuminationMaterial ilspDomain = process.ilspDomain ilspDomainMesh = ilspDomain.data while process.update(): illumValues = ilspDomainMesh.attributes.new( name=illuminationMaterial.name + "_" + str(process.stepIndex), type="FLOAT", domain="FACE") visibleFaces = self._getVisibleFacesInBeam(ilspDomain, laserBeam) for visibleFace in visibleFaces: normal = process.normals[visibleFace.index] vertexValues = [] for vertex in visibleFace.vertices: vertexValues.append(laserBeam.getValue( coords=process.coords[vertex], normal=normal)) val = sum(vertexValues) / len(vertexValues) if val > max: max = val if (val < min) and val > 0.0: min = val setattr(ilspDomainMesh.attributes[illumValues.name].data[visibleFace.index], "value", val) wm.progress_update(process.stepIndex) wm.progress_end() illumValuesProcess = [] for att in ilspDomainMesh.attributes: if illuminationMaterial.name in att.name: illumValuesProcess.append(att) for illumValuesIdx in range(1, len(illumValuesProcess)): illumValues = illumValuesProcess[illumValuesIdx] illumValuesPrev = illumValuesProcess[illumValuesIdx - 1] for polygon in ilspDomainMesh.polygons: if bpy.context.scene.ilsp_process.simulation_type == 'MAXIMUM': if illumValuesPrev.data[polygon.index].value > illumValues.data[polygon.index].value: illumValues.data[polygon.index].value = illumValuesPrev.data[polygon.index].value else: illumValues.data[polygon.index].value += illumValuesPrev.data[polygon.index].value if illumValues.data[polygon.index].value > max: max = illumValues.data[polygon.index].value if illumValues.data[polygon.index].value < min: min = illumValues.data[polygon.index].value # if illumValuesPrev.data[polygon.index].value > illumValues.data[polygon.index].value: # illumValues.data[polygon.index].value = illumValuesPrev.data[polygon.index].value return min, max
def _getVisibleFacesInBeam(self, ilspDomain, laserBeam): # See http//blender.stackexchange.com/questions/57540/automated-way-to-make-select-interior-faces-ignore-select-faces-that-are-visib bpy.ops.object.mode_set(mode='OBJECT') matrix_world = ilspDomain.matrix_world visibleFaces = [] origin = laserBeam.point direction = laserBeam.axis normDir = direction normDir.normalize() for face in ilspDomain.data.polygons: faceCenter = matrix_world @ face.center if laserBeam.inBeam(coords=faceCenter): newOrigin = intersect_line_plane(faceCenter, faceCenter + direction, origin, direction) faceIndex = bpy.context.scene.ray_cast(bpy.context.view_layer.depsgraph, newOrigin, normDir)[3] if faceIndex == face.index: visibleFaces.append(face) return visibleFaces