black formatting and changes in shader typing

This commit is contained in:
Lucas Nascimento
2024-12-18 14:46:46 -03:00
committed by Dion Moult
parent 80996dee1f
commit dff9f56ce3
7 changed files with 644 additions and 640 deletions
+12 -10
View File
@@ -32,6 +32,7 @@ def refresh():
BoundaryConditionsData.is_loaded = False BoundaryConditionsData.is_loaded = False
LoadGroupDecorationData.is_loaded = False LoadGroupDecorationData.is_loaded = False
class LoadGroupDecorationData: class LoadGroupDecorationData:
data = {} data = {}
is_loaded = False is_loaded = False
@@ -40,15 +41,16 @@ class LoadGroupDecorationData:
def load(cls): def load(cls):
cls.data = {"load groups to show": cls.load_groups_to_show()} cls.data = {"load groups to show": cls.load_groups_to_show()}
cls.is_loaded = True cls.is_loaded = True
@classmethod @classmethod
def load_groups_to_show(cls): def load_groups_to_show(cls):
ret = [] ret = []
abrv = {"LOAD_CASE": "L.Case: ", abrv = {
"LOAD_COMBINATION": "L.Comb: ", "LOAD_CASE": "L.Case: ",
"LOAD_GROUP": "L.Gr: ", "LOAD_COMBINATION": "L.Comb: ",
"USERDEFINED": "U.Def: ", "LOAD_GROUP": "L.Gr: ",
"NOTDEFINED": "N.Def: " "USERDEFINED": "U.Def: ",
"NOTDEFINED": "N.Def: ",
} }
models = tool.Ifc.get().by_type("IfcStructuralAnalysisModel") models = tool.Ifc.get().by_type("IfcStructuralAnalysisModel")
m = models[0] m = models[0]
@@ -56,21 +58,21 @@ class LoadGroupDecorationData:
if props.activity_type == "Action": if props.activity_type == "Action":
groups = m.LoadedBy or [] groups = m.LoadedBy or []
for g in groups: for g in groups:
ret.append((str(g.id()),". "+abrv[g.PredefinedType]+" "+g.Name,"")) ret.append((str(g.id()), ". " + abrv[g.PredefinedType] + " " + g.Name, ""))
related_objects = [rel.RelatedObjects for rel in g.IsGroupedBy] related_objects = [rel.RelatedObjects for rel in g.IsGroupedBy]
for item in related_objects: for item in related_objects:
for subgoup in [sg for sg in item if sg.is_a("IfcStructuralLoadGroup")]: for subgoup in [sg for sg in item if sg.is_a("IfcStructuralLoadGroup")]:
ret.append((str(subgoup.id()),". "+abrv[subgoup.PredefinedType]+subgoup.Name,"")) ret.append((str(subgoup.id()), ". " + abrv[subgoup.PredefinedType] + subgoup.Name, ""))
if props.activity_type == "External Reaction": if props.activity_type == "External Reaction":
groups = m.HasResults or [] groups = m.HasResults or []
for g in groups: for g in groups:
result_name = g.ResultForLoadGroup.Name or "" result_name = g.ResultForLoadGroup.Name or ""
group_name = g.Name or "" group_name = g.Name or ""
ret.append((str(g.id()), group_name + " " + result_name,"")) ret.append((str(g.id()), group_name + " " + result_name, ""))
if len(ret) == 0: if len(ret) == 0:
ret.append(("","","")) ret.append(("", "", ""))
return ret return ret
@@ -26,8 +26,10 @@ from gpu_extras.batch import batch_for_shader
from typing import Iterable, Union from typing import Iterable, Union
from bonsai.bim.module.structural.load_decoration_data import ShaderInfo from bonsai.bim.module.structural.load_decoration_data import ShaderInfo
class LoadsDecorator: class LoadsDecorator:
"""Decorator to show strucutural loads in 3D""" """Decorator to show strucutural loads in 3D"""
is_installed = False is_installed = False
handlers = [] handlers = []
decoration_data = None decoration_data = None
@@ -36,20 +38,20 @@ class LoadsDecorator:
depth_array = None depth_array = None
@classmethod @classmethod
def install(cls, context: bpy.types.Context)-> None: def install(cls, context: bpy.types.Context) -> None:
if cls.is_installed: if cls.is_installed:
cls.uninstall() cls.uninstall()
handler = cls() handler = cls()
cls.handlers.append( cls.handlers.append(
SpaceView3D.draw_handler_add(handler.draw_load_values, ((context,)), "WINDOW", "POST_PIXEL") SpaceView3D.draw_handler_add(handler.draw_load_values, ((context,)), "WINDOW", "POST_PIXEL")
) )
cls.handlers.append(SpaceView3D.draw_handler_add(handler, (), "WINDOW", "POST_VIEW")) cls.handlers.append(SpaceView3D.draw_handler_add(handler, (), "WINDOW", "POST_VIEW"))
cls.decoration_data = ShaderInfo() cls.decoration_data = ShaderInfo()
cls.update() cls.update()
cls.is_installed = True cls.is_installed = True
@classmethod @classmethod
def uninstall(cls)-> None: def uninstall(cls) -> None:
for handler in cls.handlers: for handler in cls.handlers:
try: try:
SpaceView3D.draw_handler_remove(handler, "WINDOW") SpaceView3D.draw_handler_remove(handler, "WINDOW")
@@ -68,8 +70,8 @@ class LoadsDecorator:
# set open gl configurations # set open gl configurations
original_blend = gpu.state.blend_get() original_blend = gpu.state.blend_get()
original_depth_test = gpu.state.depth_test_get() original_depth_test = gpu.state.depth_test_get()
gpu.state.blend_set('ALPHA') gpu.state.blend_set("ALPHA")
gpu.state.depth_test_set('LESS_EQUAL') gpu.state.depth_test_set("LESS_EQUAL")
self.draw_batch() self.draw_batch()
@@ -80,11 +82,11 @@ class LoadsDecorator:
def draw_batch(self) -> None: def draw_batch(self) -> None:
"""draw the 3D representation of loads""" """draw the 3D representation of loads"""
if not self.decoration_data.is_empty: if not self.decoration_data.is_empty:
for info in self.shader_info: for info in self.shader_info:
shader = info["shader"] shader = info["shader"]
args = info["args"] args = info["args"]
indices = info["indices"] indices = info["indices"]
batch = batch_for_shader(shader, 'TRIS', args, indices=indices) batch = batch_for_shader(shader, "TRIS", args, indices=indices)
matrix = bpy.context.region_data.perspective_matrix matrix = bpy.context.region_data.perspective_matrix
shader.bind() shader.bind()
shader.uniform_float("viewProjectionMatrix", matrix) shader.uniform_float("viewProjectionMatrix", matrix)
@@ -96,10 +98,10 @@ class LoadsDecorator:
def draw_load_values(self, context: bpy.types.Context) -> None: def draw_load_values(self, context: bpy.types.Context) -> None:
"""draw text representing the load values""" """draw text representing the load values"""
#getting depth buffer info, code adapted from: # getting depth buffer info, code adapted from:
#https://blender.stackexchange.com/questions/177185/is-there-a-way-to-render-depth-buffer-into-a-texture-with-gpu-bgl-python-modules # https://blender.stackexchange.com/questions/177185/is-there-a-way-to-render-depth-buffer-into-a-texture-with-gpu-bgl-python-modules
framebuffer = gpu.state.active_framebuffer_get() framebuffer = gpu.state.active_framebuffer_get()
width = context.region.width width = context.region.width
height = context.region.height height = context.region.height
depth_buffer = framebuffer.read_depth(0, 0, width, height) depth_buffer = framebuffer.read_depth(0, 0, width, height)
depth_array = np.array(depth_buffer.to_list()) depth_array = np.array(depth_buffer.to_list())
@@ -110,7 +112,7 @@ class LoadsDecorator:
self.depth_array = n / (f - (f - n) * depth_array) * (f - n) self.depth_array = n / (f - (f - n) * depth_array) * (f - n)
for info in self.text_info: for info in self.text_info:
text_position = self.location_3d_to_region_2d(info["position"],context) text_position = self.location_3d_to_region_2d(info["position"], context)
if text_position is not None: if text_position is not None:
font_id = 0 font_id = 0
blf.position(font_id, text_position[0], text_position[1], text_position[2]) blf.position(font_id, text_position[0], text_position[1], text_position[2])
@@ -118,7 +120,7 @@ class LoadsDecorator:
blf.color(font_id, 0.9, 0.9, 0.9, 1.0) blf.color(font_id, 0.9, 0.9, 0.9, 1.0)
blf.draw(font_id, info["text"]) blf.draw(font_id, info["text"])
def location_3d_to_region_2d(self, coord: Iterable, context: bpy.types.Context) -> Union[Vector,None]: def location_3d_to_region_2d(self, coord: Iterable, context: bpy.types.Context) -> Union[Vector, None]:
"""Convert from 3D space to 2D screen space. """Convert from 3D space to 2D screen space.
Filter out the text supposed to be hidden by 3D elements, using the depth array. Filter out the text supposed to be hidden by 3D elements, using the depth array.
It also hides text that are distant from the camera view to avoid clutter""" It also hides text that are distant from the camera view to avoid clutter"""
@@ -129,18 +131,26 @@ class LoadsDecorator:
view_matrix = rv3d.view_matrix view_matrix = rv3d.view_matrix
point_view_space = view_matrix @ coord point_view_space = view_matrix @ coord
if perspective == "ORTHO" or -10 < point_view_space.z < 0:
if perspective == 'ORTHO' or -10 < point_view_space.z < 0:
prj = rv3d.perspective_matrix @ Vector((coord[0], coord[1], coord[2], 1.0)) prj = rv3d.perspective_matrix @ Vector((coord[0], coord[1], coord[2], 1.0))
width_half = context.region.width / 2.0 width_half = context.region.width / 2.0
height_half = context.region.height / 2.0 height_half = context.region.height / 2.0
coord_2d = Vector((width_half + width_half * (prj.x / prj.w), coord_2d = Vector(
height_half + height_half * (prj.y / prj.w), (
point_view_space.z)) width_half + width_half * (prj.x / prj.w),
if coord_2d[0] < 0 or coord_2d[0]> context.region.width or coord_2d[1] > context.region.height or coord_2d[1] < 0: height_half + height_half * (prj.y / prj.w),
point_view_space.z,
)
)
if (
coord_2d[0] < 0
or coord_2d[0] > context.region.width
or coord_2d[1] > context.region.height
or coord_2d[1] < 0
):
return None return None
depth = self.depth_array[int(coord_2d[1])][int(coord_2d[0])] depth = self.depth_array[int(coord_2d[1])][int(coord_2d[0])]
if -0.98*point_view_space.z > depth: if -0.98 * point_view_space.z > depth:
return None return None
return coord_2d return coord_2d
return None return None
File diff suppressed because it is too large Load Diff
@@ -29,24 +29,26 @@ from mathutils import Vector, Matrix
from bonsai.bim.ifc import IfcStore from bonsai.bim.ifc import IfcStore
from bonsai.bim.module.structural.decorator import LoadsDecorator from bonsai.bim.module.structural.decorator import LoadsDecorator
class ShowLoads(bpy.types.Operator): class ShowLoads(bpy.types.Operator):
"""Draw decorations to show strucutural actions in 3d view""" """Draw decorations to show strucutural actions in 3d view"""
bl_idname = "bim.show_loads" bl_idname = "bim.show_loads"
bl_label = "Show loads in 3D View" bl_label = "Show loads in 3D View"
def modal(self, context, event): def modal(self, context, event):
if event.type == 'F5': if event.type == "F5":
LoadsDecorator.update() LoadsDecorator.update()
for area in context.screen.areas: for area in context.screen.areas:
if area.type == 'VIEW_3D': if area.type == "VIEW_3D":
area.tag_redraw() area.tag_redraw()
if event.type == 'ESC': if event.type == "ESC":
LoadsDecorator.uninstall() LoadsDecorator.uninstall()
for area in context.screen.areas: for area in context.screen.areas:
if area.type == 'VIEW_3D': if area.type == "VIEW_3D":
area.tag_redraw() area.tag_redraw()
return {'FINISHED'} return {"FINISHED"}
return {'PASS_THROUGH'} return {"PASS_THROUGH"}
def invoke(self, context, event): def invoke(self, context, event):
collection = bpy.data.collections["IfcStructuralItem"] collection = bpy.data.collections["IfcStructuralItem"]
@@ -60,10 +62,10 @@ class ShowLoads(bpy.types.Operator):
context.window.cursor_modal_restore() context.window.cursor_modal_restore()
context.window_manager.modal_handler_add(self) context.window_manager.modal_handler_add(self)
for area in context.screen.areas: for area in context.screen.areas:
if area.type == 'VIEW_3D': if area.type == "VIEW_3D":
area.tag_redraw() area.tag_redraw()
return {'RUNNING_MODAL'} return {"RUNNING_MODAL"}
class AddStructuralMemberConnection(bpy.types.Operator, tool.Ifc.Operator): class AddStructuralMemberConnection(bpy.types.Operator, tool.Ifc.Operator):
@@ -21,7 +21,12 @@ import bpy
import bonsai.tool as tool import bonsai.tool as tool
from bonsai.bim.ifc import IfcStore from bonsai.bim.ifc import IfcStore
from bonsai.bim.prop import StrProperty, Attribute from bonsai.bim.prop import StrProperty, Attribute
from bonsai.bim.module.structural.data import StructuralLoadCasesData, StructuralLoadsData, BoundaryConditionsData, LoadGroupDecorationData from bonsai.bim.module.structural.data import (
StructuralLoadCasesData,
StructuralLoadsData,
BoundaryConditionsData,
LoadGroupDecorationData,
)
from bpy.types import PropertyGroup from bpy.types import PropertyGroup
from bpy.props import ( from bpy.props import (
PointerProperty, PointerProperty,
@@ -34,14 +39,17 @@ from bpy.props import (
CollectionProperty, CollectionProperty,
) )
def get_load_groups_to_show(self, context): def get_load_groups_to_show(self, context):
if not LoadGroupDecorationData.is_loaded: if not LoadGroupDecorationData.is_loaded:
LoadGroupDecorationData.load() LoadGroupDecorationData.load()
return LoadGroupDecorationData.data["load groups to show"] return LoadGroupDecorationData.data["load groups to show"]
def update_activity_type(self, context): def update_activity_type(self, context):
LoadGroupDecorationData.is_loaded = False LoadGroupDecorationData.is_loaded = False
def get_applicable_structural_load_types(self, context): def get_applicable_structural_load_types(self, context):
if not StructuralLoadCasesData.is_loaded: if not StructuralLoadCasesData.is_loaded:
StructuralLoadCasesData.load() StructuralLoadCasesData.load()
@@ -162,13 +170,22 @@ class BIMStructuralProperties(PropertyGroup):
show_loads: BoolProperty(name="Show Loads", default=False) show_loads: BoolProperty(name="Show Loads", default=False)
update_load_repr: BoolProperty(name="Update Load Representation", default=False) update_load_repr: BoolProperty(name="Update Load Representation", default=False)
enable_repr_auto_update: BoolProperty(name="Auto Update", default=False) enable_repr_auto_update: BoolProperty(name="Auto Update", default=False)
reference_frame: EnumProperty(items=[("GLOBAL_COORDS","Global","Show loads in global reference frame"), reference_frame: EnumProperty(
("LOCAL_COORDS","Local","Show loads in local reference frame")], name= "Reference Frame") items=[
activity_type: EnumProperty(items=[("Action","Actions","Show actions loads"), ("GLOBAL_COORDS", "Global", "Show loads in global reference frame"),
("External Reaction","External Reactions","Show reactions on boundary conditions"), ("LOCAL_COORDS", "Local", "Show loads in local reference frame"),
("Internal Reactions","Internal Reactions","Show internal reactions on members")], ],
name="Activity Type", name="Reference Frame",
update=update_activity_type) )
activity_type: EnumProperty(
items=[
("Action", "Actions", "Show actions loads"),
("External Reaction", "External Reactions", "Show reactions on boundary conditions"),
("Internal Reactions", "Internal Reactions", "Show internal reactions on members"),
],
name="Activity Type",
update=update_activity_type,
)
load_group_to_show: EnumProperty(items=get_load_groups_to_show, name="Load Groups") load_group_to_show: EnumProperty(items=get_load_groups_to_show, name="Load Groups")
+171 -180
View File
@@ -17,38 +17,49 @@
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>. # along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import gpu import gpu
from typing import Literal
class DecorationShader: class DecorationShader:
"shader for the load decorations" "shader for the load decorations"
def __init__(self): def __init__(self):
pass pass
def new(self, pattern: str) -> gpu.types.GPUShader:
def new(self, pattern: Literal["PERPENDICULAR DISTRIBUTED FORCE",
"PARALLEL DISTRIBUTED FORCE",
"DISTRIBUTED MOMENT",
"SINGLE FORCE",
"SINGLE MOMENT",
"PLANAR LOAD",]) -> gpu.types.GPUShader:
"""pattern: string description of the desired shader """pattern: string description of the desired shader
Possible values Possible values
PERPENDICULAR DISTRIBUTED FORCE: pattern for distributed force PERPENDICULAR DISTRIBUTED FORCE: pattern for distributed force
perpendicular to the curve member axis perpendicular to the curve member axis
PARALLEL DISTRIBUTED FORCE: pattern for distributed force PARALLEL DISTRIBUTED FORCE: pattern for distributed force
along the curve member axis along the curve member axis
DISTRIBUTED MOMENT: pattern for distributed moment in curve members DISTRIBUTED MOMENT: pattern for distributed moment in curve members
SINGLE FORCE: pattern for single forces SINGLE FORCE: pattern for single forces
SINGLE MOMENT: pattern for single moments SINGLE MOMENT: pattern for single moments
PLANAR LOAD: pattern for planar loads PLANAR LOAD: pattern for planar loads
""" """
valid_patterns = {"PERPENDICULAR DISTRIBUTED FORCE", valid_patterns = {
"PARALLEL DISTRIBUTED FORCE", "PERPENDICULAR DISTRIBUTED FORCE",
"DISTRIBUTED MOMENT", "PARALLEL DISTRIBUTED FORCE",
"SINGLE FORCE", "DISTRIBUTED MOMENT",
"SINGLE MOMENT", "SINGLE FORCE",
"PLANAR LOAD" "SINGLE MOMENT",
} "PLANAR LOAD",
}
if pattern not in valid_patterns: if pattern not in valid_patterns:
raise ValueError("""pattern must be one of: raise ValueError(
"""pattern must be one of:
PERPENDICULAR DISTRIBUTED FORCE PERPENDICULAR DISTRIBUTED FORCE
PARALLEL DISTRIBUTED FORCE, PARALLEL DISTRIBUTED FORCE,
DISTRIBUTED MOMENT, DISTRIBUTED MOMENT,
SINGLE FORCE, SINGLE FORCE,
SINGLE MOMENT, SINGLE MOMENT,
PLANAR LOAD""") PLANAR LOAD"""
)
if "DISTRIBUTED" in pattern.upper(): if "DISTRIBUTED" in pattern.upper():
shader = self.get_linear_shader(pattern) shader = self.get_linear_shader(pattern)
return shader return shader
@@ -59,29 +70,31 @@ class DecorationShader:
shader = self.get_planar_shader() shader = self.get_planar_shader()
return shader return shader
def get_linear_shader(self, pattern: str) -> gpu.types.GPUShader: def get_linear_shader(self, pattern: Literal["PERPENDICULAR DISTRIBUTED FORCE",
"PARALLEL DISTRIBUTED FORCE",
"DISTRIBUTED MOMENT"]) -> gpu.types.GPUShader:
"""pattern: type of pattern """pattern: type of pattern
PERPENDICULAR DISTRIBUTED FORCE PERPENDICULAR DISTRIBUTED FORCE
PARALLEL DISTRIBUTED FORCE, PARALLEL DISTRIBUTED FORCE,
DISTRIBUTED MOMENT, DISTRIBUTED MOMENT,
""" """
vert_out = gpu.types.GPUStageInterfaceInfo("my_interface") vert_out = gpu.types.GPUStageInterfaceInfo("my_interface")
vert_out.smooth('VEC3', "forces") vert_out.smooth("VEC3", "forces")
vert_out.smooth('VEC3', "co") vert_out.smooth("VEC3", "co")
shader_info = gpu.types.GPUShaderCreateInfo() shader_info = gpu.types.GPUShaderCreateInfo()
shader_info.push_constant('MAT4', "viewProjectionMatrix") shader_info.push_constant("MAT4", "viewProjectionMatrix")
shader_info.push_constant('VEC4', "color") shader_info.push_constant("VEC4", "color")
shader_info.push_constant('FLOAT', "spacing") shader_info.push_constant("FLOAT", "spacing")
shader_info.push_constant('FLOAT', "maxload") shader_info.push_constant("FLOAT", "maxload")
shader_info.vertex_in(0, 'VEC3', "position") shader_info.vertex_in(0, "VEC3", "position")
shader_info.vertex_in(1, 'VEC3', "sin_quad_lin_forces") shader_info.vertex_in(1, "VEC3", "sin_quad_lin_forces")
shader_info.vertex_in(2, 'VEC3', "coord") shader_info.vertex_in(2, "VEC3", "coord")
shader_info.vertex_out(vert_out) shader_info.vertex_out(vert_out)
shader_info.fragment_out(0, 'VEC4', "FragColor") shader_info.fragment_out(0, "VEC4", "FragColor")
shader_info.vertex_source( shader_info.vertex_source(
"void main()" "void main()"
"{" "{"
@@ -90,207 +103,185 @@ class DecorationShader:
" forces = sin_quad_lin_forces;" " forces = sin_quad_lin_forces;"
"}" "}"
) )
if pattern == "PERPENDICULAR DISTRIBUTED FORCE": if pattern == "PERPENDICULAR DISTRIBUTED FORCE":
shader_info.fragment_source( shader_info.fragment_source(
"void main()" "void main()"
"{" "{"
"float x = co.x;" "float x = co.x;"
"float y = co.y;" "float y = co.y;"
"float abs_y = abs(y);" "float abs_y = abs(y);"
"float a = abs(mod(x,spacing)-0.5*spacing)*5.0;"
"float a = abs(mod(x,spacing)-0.5*spacing)*5.0;" "float b = step(a,abs_y)*(step(abs_y,1.2*spacing));"
"float b = step(a,abs_y)*(step(abs_y,1.2*spacing));" "float c = step(0.8*spacing,mod(x+0.4*spacing,spacing))*(step(1.2*spacing,abs_y));"
"float c = step(0.8*spacing,mod(x+0.4*spacing,spacing))*(step(1.2*spacing,abs_y));" "float sinvalue = forces.x;"
"float quadraticvalue = forces.y;"
"float sinvalue = forces.x;" "float linearvalue = forces.z;"
"float quadraticvalue = forces.y;" "x = co.x/co.z;"
"float linearvalue = forces.z;" "float f = (sin(x*3.1416)*sinvalue"
"x = co.x/co.z;" "+(-4.*x*x+4.*x)*quadraticvalue"
"float f = (sin(x*3.1416)*sinvalue" "+linearvalue)/maxload;"
"+(-4.*x*x+4.*x)*quadraticvalue" "float mask = step(0.,y)*step(y,f)+step(y,0.)*step(f,y);"
"+linearvalue)/maxload;" "float top = step(abs(y-f),0.2*1.2*spacing);"
"float mask = step(0.,y)*step(y,f)+step(y,0.)*step(f,y);" "float d = clamp(top+b+c,0.0,0.9)*mask;"
"if (d == 0.0) discard;"
"float top = step(abs(y-f),0.2*1.2*spacing);" "FragColor = vec4(color.xyz,d*color.w);"
"float d = clamp(top+b+c,0.0,0.9)*mask;" "}"
"if (d == 0.0) discard;" )
"FragColor = vec4(color.xyz,d*color.w);"
"}"
)
elif pattern == "PARALLEL DISTRIBUTED FORCE": elif pattern == "PARALLEL DISTRIBUTED FORCE":
shader_info.fragment_source( shader_info.fragment_source(
"void main()" "void main()"
"{" "{"
"float y = co.y;" "float y = co.y;"
"float x = step(0.,y)*(co.z-co.x)+step(y,0.)*(co.x);" "float x = step(0.,y)*(co.z-co.x)+step(y,0.)*(co.x);"
"float abs_y = abs(y);" "float abs_y = abs(y);"
"float a = abs(mod(abs_y,spacing)-0.5*spacing)*5.0;"
"float a = abs(mod(abs_y,spacing)-0.5*spacing)*5.0;" "float a2 = mod(x,3.0*spacing);"
"float a2 = mod(x,3.0*spacing);" "float b = step(a,a2)*step(a2,1.2*spacing);"
"float b = step(a,a2)*step(a2,1.2*spacing);" "float c = step(0.8*spacing,mod(abs_y+0.4*spacing,spacing))"
"float c = step(0.8*spacing,mod(abs_y+0.4*spacing,spacing))" "*(step(1.2*spacing,a2))*step(a2,2.5*spacing);"
"*(step(1.2*spacing,a2))*step(a2,2.5*spacing);" "float sinvalue = forces.x;"
"float sinvalue = forces.x;" "float quadraticvalue = forces.y;"
"float quadraticvalue = forces.y;" "float linearvalue = forces.z;"
"float linearvalue = forces.z;" "x = co.x/co.z;"
"x = co.x/co.z;" "float f = (sin(x*3.1416)*sinvalue"
"float f = (sin(x*3.1416)*sinvalue" "+(-4.*x*x+4.*x)*quadraticvalue"
"+(-4.*x*x+4.*x)*quadraticvalue" "+linearvalue)/maxload;"
"+linearvalue)/maxload;" "float mask = step(0.,y)*step(y,f)+step(y,0.)*step(f,y);"
"float mask = step(0.,y)*step(y,f)+step(y,0.)*step(f,y);" "float top = step(abs(y-f),0.2*1.2*spacing);"
"float d = clamp(top+b+c,0.0,0.9)*mask;"
"float top = step(abs(y-f),0.2*1.2*spacing);" "if (d == 0.0) discard;"
"float d = clamp(top+b+c,0.0,0.9)*mask;" "FragColor = vec4(color.xyz,d*color.w);"
"if (d == 0.0) discard;" "}"
"FragColor = vec4(color.xyz,d*color.w);" )
"}"
)
elif pattern == "DISTRIBUTED MOMENT": elif pattern == "DISTRIBUTED MOMENT":
shader_info.fragment_source( shader_info.fragment_source(
"void main()" "void main()"
"{" "{"
"float x = step(co.y,0.)*(co.x)+step(0.,co.y)*(co.z-co.x);" "float x = step(co.y,0.)*(co.x)+step(0.,co.y)*(co.z-co.x);"
"float y = step(co.y,-0.00001)*(co.y)+step(0.,co.y)*(0.-co.y);" "float y = step(co.y,-0.00001)*(co.y)+step(0.,co.y)*(0.-co.y);"
"x = mod((0.5/spacing)*x,1.4)-0.7;" "x = mod((0.5/spacing)*x,1.4)-0.7;"
"y = mod((0.5/spacing)*y,1.4)-0.7;" "y = mod((0.5/spacing)*y,1.4)-0.7;"
"float abs_y = abs(y);" "float abs_y = abs(y);"
"vec2 st = vec2(1.9*x,y);" "vec2 st = vec2(1.9*x,y);"
"vec2 orig = vec2(0.,0.);" "vec2 orig = vec2(0.,0.);"
"float circ = step(distance(st,orig),0.33)*step(0.27,distance(st,orig));"
"float circ = step(distance(st,orig),0.33)*step(0.27,distance(st,orig));" "float tri_mask = step(st.y,st.x)+step(-st.x,st.y);"
"float tri_mask = step(st.y,st.x)+step(-st.x,st.y);" "float circ_arrow = step(st.x,4.0*st.y-0.75)*step(0.25*st.y-0.34,st.x)*(1.-tri_mask);"
"float circ_arrow = step(st.x,4.0*st.y-0.75)*step(0.25*st.y-0.34,st.x)*(1.-tri_mask);" "float circmask = step(distance(st,orig),0.1)+step(0.5,distance(st,orig))+step(st.x,0.);"
"float body = step(-0.03,st.y)*step(st.y,0.03)*step(-0.3,x)*step(x,0.576);"
"float body_arrow = step(-0.5+3.*st.y,x)*step(-0.5-3.*st.y,x)*step(x,-0.3);"
"float d = clamp(circmask*(body+body_arrow)+circ_arrow+circ*tri_mask,0.,1.);"
"float sinvalue = forces.x;"
"float quadraticvalue = forces.y;"
"float linearvalue = forces.z;"
"x = co.x/co.z;"
"float f = (sin(x*3.1416)*sinvalue"
"+(-4.*x*x+4.*x)*quadraticvalue"
"+linearvalue)/maxload;"
"float mask = step(0.,co.y)*step(co.y,f)+step(co.y,0.)*step(f,co.y);"
"float top = step(abs(co.y-f),0.2*1.2*spacing);"
"d = clamp(top+d,0.0,0.9)*mask;"
"if (d == 0.0) discard;"
"FragColor = vec4(color.xyz,d*color.w);"
"}"
)
"float circmask = step(distance(st,orig),0.1)+step(0.5,distance(st,orig))+step(st.x,0.);"
"float body = step(-0.03,st.y)*step(st.y,0.03)*step(-0.3,x)*step(x,0.576);"
"float body_arrow = step(-0.5+3.*st.y,x)*step(-0.5-3.*st.y,x)*step(x,-0.3);"
"float d = clamp(circmask*(body+body_arrow)+circ_arrow+circ*tri_mask,0.,1.);"
"float sinvalue = forces.x;"
"float quadraticvalue = forces.y;"
"float linearvalue = forces.z;"
"x = co.x/co.z;"
"float f = (sin(x*3.1416)*sinvalue"
"+(-4.*x*x+4.*x)*quadraticvalue"
"+linearvalue)/maxload;"
"float mask = step(0.,co.y)*step(co.y,f)+step(co.y,0.)*step(f,co.y);"
"float top = step(abs(co.y-f),0.2*1.2*spacing);"
"d = clamp(top+d,0.0,0.9)*mask;"
"if (d == 0.0) discard;"
"FragColor = vec4(color.xyz,d*color.w);"
"}"
)
shader = gpu.shader.create_from_info(shader_info) shader = gpu.shader.create_from_info(shader_info)
del vert_out del vert_out
del shader_info del shader_info
return shader return shader
def get_point_shader(self, pattern: str) -> gpu.types.GPUShader: def get_point_shader(self, pattern: Literal["SINGLE FORCE","SINGLE MOMENT"]) -> gpu.types.GPUShader:
""" param: pattern: type of pattern """param: pattern: type of pattern
SINGLE FORCE, SINGLE FORCE,
SINGLE MOMENT""" SINGLE MOMENT"""
vert_out = gpu.types.GPUStageInterfaceInfo("my_interface") vert_out = gpu.types.GPUStageInterfaceInfo("my_interface")
vert_out.smooth('VEC3', "co") vert_out.smooth("VEC3", "co")
shader_info = gpu.types.GPUShaderCreateInfo() shader_info = gpu.types.GPUShaderCreateInfo()
shader_info.push_constant('MAT4', "viewProjectionMatrix") shader_info.push_constant("MAT4", "viewProjectionMatrix")
shader_info.push_constant('VEC4', "color") shader_info.push_constant("VEC4", "color")
shader_info.push_constant('FLOAT', "spacing") shader_info.push_constant("FLOAT", "spacing")
shader_info.vertex_in(0, 'VEC3', "position") shader_info.vertex_in(0, "VEC3", "position")
shader_info.vertex_in(1, 'VEC3', "coord") shader_info.vertex_in(1, "VEC3", "coord")
shader_info.vertex_out(vert_out) shader_info.vertex_out(vert_out)
shader_info.fragment_out(0, 'VEC4', "FragColor") shader_info.fragment_out(0, "VEC4", "FragColor")
shader_info.vertex_source( shader_info.vertex_source(
"void main()" "void main()" "{" " gl_Position = viewProjectionMatrix * vec4(position, 1.0f);" " co = coord;" "}"
"{"
" gl_Position = viewProjectionMatrix * vec4(position, 1.0f);"
" co = coord;"
"}"
) )
if pattern == "SINGLE FORCE": if pattern == "SINGLE FORCE":
shader_info.fragment_source( shader_info.fragment_source(
"void main()" "void main()"
"{" "{"
"float body = step(abs(co.x),0.2*spacing)*step(2.*spacing,co.y);" "float body = step(abs(co.x),0.2*spacing)*step(2.*spacing,co.y);"
"float arrow = step(3.5*abs(co.x)+0.02,abs(co.y))*step(co.y,2.*spacing)*step(0.,co.y);" "float arrow = step(3.5*abs(co.x)+0.02,abs(co.y))*step(co.y,2.*spacing)*step(0.,co.y);"
"float d = clamp(body+arrow,0.0,0.5);" "float d = clamp(body+arrow,0.0,0.5);"
"if (d == 0.0) discard;" "if (d == 0.0) discard;"
"FragColor = vec4(color.xyz,d*color.w);" "FragColor = vec4(color.xyz,d*color.w);"
"}" "}"
) )
elif pattern == "SINGLE MOMENT": elif pattern == "SINGLE MOMENT":
shader_info.fragment_source( shader_info.fragment_source(
"void main()" "void main()"
"{" "{"
"float circ = step(distance(co.xy,vec2(0.,0.)),0.33)*step(0.27,distance(co.xy,vec2(0.,0.)));" "float circ = step(distance(co.xy,vec2(0.,0.)),0.33)*step(0.27,distance(co.xy,vec2(0.,0.)));"
"float mask = step(co.y,co.x)+step(-co.x,co.y);" "float mask = step(co.y,co.x)+step(-co.x,co.y);"
"float circ_arrow = step(co.x,4.0*co.y-0.75)*step(0.25*co.y-0.34,co.x)*(1.-mask);" "float circ_arrow = step(co.x,4.0*co.y-0.75)*step(0.25*co.y-0.34,co.x)*(1.-mask);"
"float d = clamp(circ_arrow+circ*mask,0.0,0.5);" "float d = clamp(circ_arrow+circ*mask,0.0,0.5);"
"if (d == 0.0) discard;" "if (d == 0.0) discard;"
"FragColor = vec4(color.xyz,d*color.w);" "FragColor = vec4(color.xyz,d*color.w);"
"}" "}"
) )
shader = gpu.shader.create_from_info(shader_info) shader = gpu.shader.create_from_info(shader_info)
del vert_out del vert_out
del shader_info del shader_info
return shader return shader
def get_planar_shader(self) -> gpu.types.GPUShader: def get_planar_shader(self) -> gpu.types.GPUShader:
"""shader for planar loads""" """shader for planar loads"""
vert_out = gpu.types.GPUStageInterfaceInfo("my_interface") vert_out = gpu.types.GPUStageInterfaceInfo("my_interface")
vert_out.smooth('VEC3', "co") vert_out.smooth("VEC3", "co")
shader_info = gpu.types.GPUShaderCreateInfo() shader_info = gpu.types.GPUShaderCreateInfo()
shader_info.push_constant('MAT4', "viewProjectionMatrix") shader_info.push_constant("MAT4", "viewProjectionMatrix")
shader_info.push_constant('VEC4', "color") shader_info.push_constant("VEC4", "color")
shader_info.push_constant('FLOAT', "spacing") shader_info.push_constant("FLOAT", "spacing")
shader_info.vertex_in(0, 'VEC3', "position") shader_info.vertex_in(0, "VEC3", "position")
shader_info.vertex_in(1, 'VEC3', "coord") shader_info.vertex_in(1, "VEC3", "coord")
shader_info.vertex_out(vert_out) shader_info.vertex_out(vert_out)
shader_info.fragment_out(0, 'VEC4', "FragColor") shader_info.fragment_out(0, "VEC4", "FragColor")
shader_info.vertex_source( shader_info.vertex_source(
"void main()" "{" " gl_Position = viewProjectionMatrix * vec4(position, 1.0f);" " co = coord;" "}"
)
shader_info.fragment_source(
"void main()" "void main()"
"{" "{"
" gl_Position = viewProjectionMatrix * vec4(position, 1.0f);"
" co = coord;"
"}"
)
shader_info.fragment_source(
"void main()"
"{"
"float x = co.x;" "float x = co.x;"
"float y = co.y;" "float y = co.y;"
"float abs_y = abs(y);" "float abs_y = abs(y);"
"float a = abs(mod(x,spacing)-0.5*spacing)*5.0;" "float a = abs(mod(x,spacing)-0.5*spacing)*5.0;"
"float b = step(a,abs_y)*(step(abs_y,1.2*spacing));" "float b = step(a,abs_y)*(step(abs_y,1.2*spacing));"
"float c = step(0.8*spacing,mod(x+0.4*spacing,spacing))*(step(1.2*spacing,abs_y));" "float c = step(0.8*spacing,mod(x+0.4*spacing,spacing))*(step(1.2*spacing,abs_y));"
"float mask = step(0.,y)*step(y,0.98)+step(y,0.)*step(0.98,y);" "float mask = step(0.,y)*step(y,0.98)+step(y,0.)*step(0.98,y);"
"float top = step(abs(y-0.98),0.2*1.2*spacing);" "float top = step(abs(y-0.98),0.2*1.2*spacing);"
"float d = clamp(0.2*y+(top+b+c)*mask,0.0,0.4);" "float d = clamp(0.2*y+(top+b+c)*mask,0.0,0.4);"
"FragColor = vec4(color.xyz,d*color.w);" "FragColor = vec4(color.xyz,d*color.w);"
"}" "}"
) )
shader = gpu.shader.create_from_info(shader_info) shader = gpu.shader.create_from_info(shader_info)
del vert_out del vert_out
del shader_info del shader_info
@@ -444,6 +444,7 @@ class BIM_UL_structural_activities(UIList):
row.label(text=item.name) row.label(text=item.name)
row.label(text=item.applied_load_class) row.label(text=item.applied_load_class)
class BIM_PT_show_structural_activities(Panel): class BIM_PT_show_structural_activities(Panel):
bl_label = "Show Loads" bl_label = "Show Loads"
bl_idname = "BIM_PT_show_structural_activities" bl_idname = "BIM_PT_show_structural_activities"
@@ -463,16 +464,16 @@ class BIM_PT_show_structural_activities(Panel):
row = self.layout.row(align=True) row = self.layout.row(align=True)
row.operator( row.operator(
"bim.show_loads", "bim.show_loads",
text="Show loads" , text="Show loads",
icon="HIDE_OFF", icon="HIDE_OFF",
) )
row = self.layout.row(align=True) row = self.layout.row(align=True)
row.prop(self.props,"reference_frame") row.prop(self.props, "reference_frame")
row = self.layout.row(align=True) row = self.layout.row(align=True)
row.prop(self.props,"activity_type") row.prop(self.props, "activity_type")
row = self.layout.row(align=True) row = self.layout.row(align=True)
row.prop(self.props,"load_group_to_show") row.prop(self.props, "load_group_to_show")
class BIM_PT_structural_loads(Panel): class BIM_PT_structural_loads(Panel):