mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-20 06:58:56 +00:00
decorations for Dim, Eq, Leader, Stair
close #1177, #1176, #1158, #1150
This commit is contained in:
@@ -66,19 +66,19 @@ class BaseDecorator():
|
|||||||
}
|
}
|
||||||
|
|
||||||
void circle_head(in vec2 p0, in vec2 p1, out vec2 head[CIRCLE_SEGS]) {
|
void circle_head(in vec2 p0, in vec2 p1, out vec2 head[CIRCLE_SEGS]) {
|
||||||
vec2 nose = normalize(p1 - p0) * CIRCLE_SIZE ;
|
float angle_d = PI * 2 / CIRCLE_SEGS;
|
||||||
float angle = PI / (CIRCLE_SEGS / 2);
|
|
||||||
for(int i = 0; i<CIRCLE_SEGS; i++) {
|
for(int i = 0; i<CIRCLE_SEGS; i++) {
|
||||||
float c = cos(angle * i), s = sin(angle * i);
|
float angle = angle_d * i;
|
||||||
head[i] = mat2(c, -s, +s, c) * nose;
|
head[i] = vec2(cos(angle), sin(angle)) * CIRCLE_SIZE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
DEF_GLSL = """
|
DEF_GLSL = """
|
||||||
#define PI 3.141592653589793
|
#define PI 3.141592653589793
|
||||||
#define CIRCLE_SEGS 36
|
#define CIRCLE_SEGS 24
|
||||||
#define SEGMENT_POINTS 42
|
// max points = SEGS (circle) + 2 (stem) + 3 (arrow)
|
||||||
|
#define MAX_POINTS 29
|
||||||
#define ARROW_ANGLE PI / 12.0
|
#define ARROW_ANGLE PI / 12.0
|
||||||
#define ARROW_SIZE 16.0
|
#define ARROW_SIZE 16.0
|
||||||
#define CIRCLE_SIZE 8.0
|
#define CIRCLE_SIZE 8.0
|
||||||
@@ -130,13 +130,7 @@ class BaseDecorator():
|
|||||||
collection = bpy.data.collections.get("IfcGroup/" + drawing.name)
|
collection = bpy.data.collections.get("IfcGroup/" + drawing.name)
|
||||||
return filter(lambda o: self.basename in o.name, collection.objects)
|
return filter(lambda o: self.basename in o.name, collection.objects)
|
||||||
|
|
||||||
def decorate(self, object):
|
def get_path_geom(self, obj):
|
||||||
"""perform actuall drawing stuff"""
|
|
||||||
raise NotImplementedError()
|
|
||||||
|
|
||||||
|
|
||||||
class PathDecorator():
|
|
||||||
def get_geom(self, obj):
|
|
||||||
"""parse path geometry into line segments
|
"""parse path geometry into line segments
|
||||||
returns:
|
returns:
|
||||||
- vertices: 3-tuples of coords
|
- vertices: 3-tuples of coords
|
||||||
@@ -161,15 +155,124 @@ class PathDecorator():
|
|||||||
|
|
||||||
return vertices, indices, styles
|
return vertices, indices, styles
|
||||||
|
|
||||||
|
def get_mesh_geom(self, obj):
|
||||||
|
"""parse mesh geometry into line segments
|
||||||
|
returns:
|
||||||
|
- vertices: 3-tuples of coords
|
||||||
|
- indices: 2-tuples of each segment verices' indices
|
||||||
|
- styles: 0=internal, 1=beginning, 2=ending
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
class DimensionDecorator(PathDecorator, BaseDecorator):
|
def decorate(self, object):
|
||||||
|
"""perform actuall drawing stuff"""
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def draw_lines(self, obj, geom):
|
||||||
|
region = self.context.region
|
||||||
|
region3d = self.context.region_data
|
||||||
|
|
||||||
|
vertices, indices, styles = geom
|
||||||
|
|
||||||
|
fmt = GPUVertFormat()
|
||||||
|
fmt.attr_add(id="pos", comp_type='F32', len=3, fetch_mode='FLOAT')
|
||||||
|
|
||||||
|
vbo = GPUVertBuf(len=len(vertices), format=fmt)
|
||||||
|
vbo.attr_fill(id="pos", data=vertices)
|
||||||
|
|
||||||
|
ibo = GPUIndexBuf(type='LINES', seq=indices)
|
||||||
|
|
||||||
|
batch = GPUBatch(type='LINES', buf=vbo, elem=ibo)
|
||||||
|
|
||||||
|
self.shader.bind()
|
||||||
|
self.shader.uniform_float
|
||||||
|
self.shader.uniform_float("viewMatrix", region3d.perspective_matrix)
|
||||||
|
self.shader.uniform_float("windowW", region.width)
|
||||||
|
self.shader.uniform_float("windowH", region.height)
|
||||||
|
batch.draw(self.shader)
|
||||||
|
|
||||||
|
def draw_lines_styled(self, obj, geom):
|
||||||
|
region = self.context.region
|
||||||
|
region3d = self.context.region_data
|
||||||
|
|
||||||
|
vertices, indices, styles = geom
|
||||||
|
|
||||||
|
fmt = GPUVertFormat()
|
||||||
|
fmt.attr_add(id="pos", comp_type='F32', len=3, fetch_mode='FLOAT')
|
||||||
|
fmt.attr_add(id="style", comp_type='U8', len=1, fetch_mode='INT')
|
||||||
|
|
||||||
|
vbo = GPUVertBuf(len=len(vertices), format=fmt)
|
||||||
|
vbo.attr_fill(id="pos", data=vertices)
|
||||||
|
vbo.attr_fill(id="style", data=styles)
|
||||||
|
|
||||||
|
ibo = GPUIndexBuf(type='LINES', seq=indices)
|
||||||
|
|
||||||
|
batch = GPUBatch(type='LINES', buf=vbo, elem=ibo)
|
||||||
|
|
||||||
|
self.shader.bind()
|
||||||
|
self.shader.uniform_float
|
||||||
|
self.shader.uniform_float("viewMatrix", region3d.perspective_matrix)
|
||||||
|
self.shader.uniform_float("windowW", region.width)
|
||||||
|
self.shader.uniform_float("windowH", region.height)
|
||||||
|
batch.draw(self.shader)
|
||||||
|
|
||||||
|
|
||||||
|
class DimensionDecorator(BaseDecorator):
|
||||||
"""Decorator for dimension objects
|
"""Decorator for dimension objects
|
||||||
- outlines each segment
|
- each edge of a segment with arrow
|
||||||
- augments with arrows on both sides
|
|
||||||
- puts metric text next to each segment
|
- puts metric text next to each segment
|
||||||
"""
|
"""
|
||||||
basename = "IfcAnnotation/Dimension"
|
basename = "IfcAnnotation/Dimension"
|
||||||
installed = None
|
installed = None
|
||||||
|
GEOM_GLSL = """
|
||||||
|
layout(lines) in;
|
||||||
|
layout(line_strip, max_vertices=MAX_POINTS) out;
|
||||||
|
|
||||||
|
uniform float windowW;
|
||||||
|
uniform float windowH;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec4 p0 = gl_in[0].gl_Position, p1 = gl_in[1].gl_Position;
|
||||||
|
|
||||||
|
// converting NDC to/from window coords
|
||||||
|
float hw = windowW/2, hh= windowH/2;
|
||||||
|
mat4 windowMatrix = mat4(hw, 0, 0, 0, 0, hh, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||||
|
mat4 unwindowMatrix = inverse(windowMatrix);
|
||||||
|
vec2 p0w = (windowMatrix * (p0 / p0.w)).xy, p1w = (windowMatrix * (p1 / p1.w)).xy;
|
||||||
|
|
||||||
|
vec2 head[3];
|
||||||
|
vec4 head_ndc[3];
|
||||||
|
arrow_head(p0w, p1w, head);
|
||||||
|
for(int i=0; i<3; i++) head_ndc[i] = unwindowMatrix * vec4(head[i], 0, 0) * p1.w;
|
||||||
|
vec4 nose = head_ndc[0];
|
||||||
|
|
||||||
|
gl_Position = p0;
|
||||||
|
EmitVertex();
|
||||||
|
gl_Position = p0 + head_ndc[1];
|
||||||
|
EmitVertex();
|
||||||
|
gl_Position = p0 + head_ndc[2];
|
||||||
|
EmitVertex();
|
||||||
|
gl_Position = p0;
|
||||||
|
EmitVertex();
|
||||||
|
EndPrimitive();
|
||||||
|
|
||||||
|
gl_Position = p1;
|
||||||
|
EmitVertex();
|
||||||
|
gl_Position = p1 - head_ndc[1];
|
||||||
|
EmitVertex();
|
||||||
|
gl_Position = p1 - head_ndc[2];
|
||||||
|
EmitVertex();
|
||||||
|
gl_Position = p1;
|
||||||
|
EmitVertex();
|
||||||
|
EndPrimitive();
|
||||||
|
|
||||||
|
gl_Position = p0 + nose;
|
||||||
|
EmitVertex();
|
||||||
|
gl_Position = p1 - nose;
|
||||||
|
EmitVertex();
|
||||||
|
EndPrimitive();
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self, props, context):
|
def __init__(self, props, context):
|
||||||
super().__init__(props, context)
|
super().__init__(props, context)
|
||||||
@@ -177,7 +280,8 @@ class DimensionDecorator(PathDecorator, BaseDecorator):
|
|||||||
self.dpi = context.preferences.system.dpi
|
self.dpi = context.preferences.system.dpi
|
||||||
|
|
||||||
def decorate(self, obj):
|
def decorate(self, obj):
|
||||||
geom = self.get_geom(obj)
|
geom = self.get_path_geom(obj)
|
||||||
|
self.draw_lines(obj, geom)
|
||||||
self.draw_labels(obj, geom)
|
self.draw_labels(obj, geom)
|
||||||
|
|
||||||
def draw_labels(self, obj, geom):
|
def draw_labels(self, obj, geom):
|
||||||
@@ -250,26 +354,20 @@ class EqualityDecorator(DimensionDecorator):
|
|||||||
|
|
||||||
|
|
||||||
class LeaderDecorator(BaseDecorator):
|
class LeaderDecorator(BaseDecorator):
|
||||||
|
"""Decorating stairs
|
||||||
|
- head point with arrow
|
||||||
|
- middle points w/out decorations
|
||||||
|
"""
|
||||||
basename = "IfcAnnotation/Leader"
|
basename = "IfcAnnotation/Leader"
|
||||||
installed = None
|
installed = None
|
||||||
|
|
||||||
def decorate(self, obj):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class StairDecorator(PathDecorator, BaseDecorator):
|
|
||||||
basename = "IfcAnnotation/Stair"
|
|
||||||
installed = None
|
|
||||||
|
|
||||||
GEOM_GLSL = """
|
GEOM_GLSL = """
|
||||||
layout(lines) in;
|
layout(lines) in;
|
||||||
layout(line_strip, max_vertices=SEGMENT_POINTS) out;
|
layout(line_strip, max_vertices=MAX_POINTS) out;
|
||||||
in uint vstyle[];
|
in uint vstyle[];
|
||||||
|
|
||||||
uniform float windowW;
|
uniform float windowW;
|
||||||
uniform float windowH;
|
uniform float windowH;
|
||||||
uniform float arrow_length;
|
|
||||||
uniform float arrow_angle;
|
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec4 p0 = gl_in[0].gl_Position, p1 = gl_in[1].gl_Position;
|
vec4 p0 = gl_in[0].gl_Position, p1 = gl_in[1].gl_Position;
|
||||||
@@ -281,11 +379,69 @@ class StairDecorator(PathDecorator, BaseDecorator):
|
|||||||
mat4 unwindowMatrix = inverse(windowMatrix);
|
mat4 unwindowMatrix = inverse(windowMatrix);
|
||||||
vec2 p0w = (windowMatrix * (p0 / p0.w)).xy, p1w = (windowMatrix * (p1 / p1.w)).xy;
|
vec2 p0w = (windowMatrix * (p0 / p0.w)).xy, p1w = (windowMatrix * (p1 / p1.w)).xy;
|
||||||
|
|
||||||
|
vec4 nose1 = vec4(0);
|
||||||
|
|
||||||
|
vec2 head[3];
|
||||||
|
vec4 head_ndc[3];
|
||||||
|
arrow_head(p0w, p1w, head);
|
||||||
|
for(int i=0; i<3; i++) head_ndc[i] = unwindowMatrix * vec4(head[i], 0, 0) * p1.w;
|
||||||
|
|
||||||
|
if (s1 == 2u) {
|
||||||
|
gl_Position = p1;
|
||||||
|
EmitVertex();
|
||||||
|
gl_Position = p1 - head_ndc[1];
|
||||||
|
EmitVertex();
|
||||||
|
gl_Position = p1 - head_ndc[2];
|
||||||
|
EmitVertex();
|
||||||
|
gl_Position = p1;
|
||||||
|
EmitVertex();
|
||||||
|
EndPrimitive();
|
||||||
|
|
||||||
|
vec2 nose = normalize(p1w - p0w) * ARROW_SIZE;
|
||||||
|
nose1 = unwindowMatrix * vec4(nose, 0, 0) * p1.w;
|
||||||
|
}
|
||||||
|
|
||||||
gl_Position = p0;
|
gl_Position = p0;
|
||||||
EmitVertex();
|
EmitVertex();
|
||||||
gl_Position = p1;
|
gl_Position = p1 - nose1;
|
||||||
EmitVertex();
|
EmitVertex();
|
||||||
EndPrimitive();
|
EndPrimitive();
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
def decorate(self, obj):
|
||||||
|
geom = self.get_path_geom(obj)
|
||||||
|
self.draw_lines_styled(obj, geom)
|
||||||
|
|
||||||
|
|
||||||
|
class StairDecorator(BaseDecorator):
|
||||||
|
"""Decorating stairs
|
||||||
|
- head point with arrow
|
||||||
|
- tail point with circle
|
||||||
|
- middle points w/out decorations
|
||||||
|
"""
|
||||||
|
basename = "IfcAnnotation/Stair"
|
||||||
|
installed = None
|
||||||
|
|
||||||
|
GEOM_GLSL = """
|
||||||
|
layout(lines) in;
|
||||||
|
layout(line_strip, max_vertices=MAX_POINTS) out;
|
||||||
|
in uint vstyle[];
|
||||||
|
|
||||||
|
uniform float windowW;
|
||||||
|
uniform float windowH;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec4 p0 = gl_in[0].gl_Position, p1 = gl_in[1].gl_Position;
|
||||||
|
uint s0 = vstyle[0], s1 = vstyle[1];
|
||||||
|
|
||||||
|
// converting NDC to/from window coords
|
||||||
|
float hw = windowW/2, hh= windowH/2;
|
||||||
|
mat4 windowMatrix = mat4(hw, 0, 0, 0, 0, hh, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||||
|
mat4 unwindowMatrix = inverse(windowMatrix);
|
||||||
|
vec2 p0w = (windowMatrix * (p0 / p0.w)).xy, p1w = (windowMatrix * (p1 / p1.w)).xy;
|
||||||
|
|
||||||
|
vec4 nose0 = vec4(0), nose1 = vec4(0);
|
||||||
|
|
||||||
if (s0 == 1u) {
|
if (s0 == 1u) {
|
||||||
vec2 head[CIRCLE_SEGS];
|
vec2 head[CIRCLE_SEGS];
|
||||||
@@ -297,6 +453,9 @@ class StairDecorator(PathDecorator, BaseDecorator):
|
|||||||
gl_Position = p0 + unwindowMatrix * vec4(head[0], 0, 0) * p0.w;
|
gl_Position = p0 + unwindowMatrix * vec4(head[0], 0, 0) * p0.w;
|
||||||
EmitVertex();
|
EmitVertex();
|
||||||
EndPrimitive();
|
EndPrimitive();
|
||||||
|
|
||||||
|
vec2 nose = normalize(p1w - p0w) * CIRCLE_SIZE;
|
||||||
|
nose0 = unwindowMatrix * vec4(nose, 0, 0) * p0.w;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s1 == 2u) {
|
if (s1 == 2u) {
|
||||||
@@ -314,38 +473,22 @@ class StairDecorator(PathDecorator, BaseDecorator):
|
|||||||
gl_Position = p1;
|
gl_Position = p1;
|
||||||
EmitVertex();
|
EmitVertex();
|
||||||
EndPrimitive();
|
EndPrimitive();
|
||||||
|
|
||||||
|
vec2 nose = normalize(p1w - p0w) * ARROW_SIZE;
|
||||||
|
nose1 = unwindowMatrix * vec4(nose, 0, 0) * p1.w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gl_Position = p0 + nose0;
|
||||||
|
EmitVertex();
|
||||||
|
gl_Position = p1 - nose1;
|
||||||
|
EmitVertex();
|
||||||
|
EndPrimitive();
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def decorate(self, obj):
|
def decorate(self, obj):
|
||||||
geom = self.get_geom(obj)
|
geom = self.get_path_geom(obj)
|
||||||
self.draw_lines(obj, geom)
|
self.draw_lines_styled(obj, geom)
|
||||||
|
|
||||||
def draw_lines(self, obj, geom):
|
|
||||||
region = self.context.region
|
|
||||||
region3d = self.context.region_data
|
|
||||||
|
|
||||||
vertices, indices, styles = geom
|
|
||||||
|
|
||||||
fmt = GPUVertFormat()
|
|
||||||
fmt.attr_add(id="pos", comp_type='F32', len=3, fetch_mode='FLOAT')
|
|
||||||
fmt.attr_add(id="style", comp_type='U8', len=1, fetch_mode='INT')
|
|
||||||
|
|
||||||
vbo = GPUVertBuf(len=len(vertices), format=fmt)
|
|
||||||
vbo.attr_fill(id="pos", data=vertices)
|
|
||||||
vbo.attr_fill(id="style", data=styles)
|
|
||||||
|
|
||||||
ibo = GPUIndexBuf(type='LINES', seq=indices)
|
|
||||||
|
|
||||||
batch = GPUBatch(type='LINES', buf=vbo, elem=ibo)
|
|
||||||
|
|
||||||
self.shader.bind()
|
|
||||||
self.shader.uniform_float
|
|
||||||
self.shader.uniform_float("viewMatrix", region3d.perspective_matrix)
|
|
||||||
self.shader.uniform_float("windowW", region.width)
|
|
||||||
self.shader.uniform_float("windowH", region.height)
|
|
||||||
batch.draw(self.shader)
|
|
||||||
|
|
||||||
|
|
||||||
class HiddenDecorator(BaseDecorator):
|
class HiddenDecorator(BaseDecorator):
|
||||||
@@ -353,4 +496,5 @@ class HiddenDecorator(BaseDecorator):
|
|||||||
installed = None
|
installed = None
|
||||||
|
|
||||||
def decorate(self, obj):
|
def decorate(self, obj):
|
||||||
pass
|
geom = self.get_mesh_geom(obj)
|
||||||
|
self.draw_lines(obj, geom)
|
||||||
|
|||||||
Reference in New Issue
Block a user