Skip to content

Commit

Permalink
Use triangle_stripe for Tags
Browse files Browse the repository at this point in the history
  • Loading branch information
Licini committed Aug 14, 2024
1 parent 23b6046 commit 21f16c6
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 37 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* Added `SettingLayout` to manage complex layout with config input.
* Added `robot.py` example.
* Added `ortho` option to view.
* Added `vertical_align` and `horizontal_align` options to `Tag`.

### Changed

* Fixed `GroupObject` `pointcolor` not found error with impliment `exclude_type_list`.
* Fixed `Tag` inconsistent height issue.

### Removed

Expand Down
14 changes: 6 additions & 8 deletions scripts/tag.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@

from compas.geometry import Box
from compas_viewer import Viewer
from compas_viewer.scene import Tag

box1 = Box.from_width_height_depth(5, 1, 1)
box2 = Box.from_width_height_depth(1, 5, 1)
t = Tag("EN", (5, 1, 1), height=50)
viewer = Viewer()
t1 = Tag("Align to left", (0, 0, 0), height=50) # default align is left and bottom
t2 = Tag("Align to center", (0, 5, 0), height=50, horizontal_align="center", vertical_align="center")
t3 = Tag("Align to right", (0, 10, 0), height=50, horizontal_align="right", vertical_align="top")
t4 = Tag("Absolute height", (5, 0, 0), absolute_height=True, height=100)

# Simple list of objects
group1 = viewer.scene.add([box1, box2, t])
viewer = Viewer()
viewer.scene.add([t1, t2, t3, t4])
viewer.show()
2 changes: 1 addition & 1 deletion src/compas_viewer/renderer/renderer.py
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,7 @@ def paint(self):
self.shader_tag.bind()
self.shader_tag.uniform4x4("viewworld", viewworld)
for obj in tag_objs:
obj.draw(self.shader_tag, self.camera.position)
obj.draw(self.shader_tag, self.camera.position, self.width(), self.height())
self.shader_tag.release()

# draw 2D box for multi-selection
Expand Down
9 changes: 2 additions & 7 deletions src/compas_viewer/renderer/shaders/shader.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,16 +204,11 @@ def draw_texts(self, elements: Any = None, n: int = 0):
n : int, optional
The number of elements.
"""
GL.glDisable(GL.GL_POINT_SMOOTH)
GL.glEnable(GL.GL_POINT_SPRITE)
GL.glEnable(GL.GL_PROGRAM_POINT_SIZE)
if elements:
GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, elements)
GL.glDrawElements(GL.GL_POINTS, n, GL.GL_UNSIGNED_INT, None)
GL.glDrawElements(GL.GL_TRIANGLE_STRIP, n, GL.GL_UNSIGNED_INT, None)
else:
GL.glDrawArrays(GL.GL_POINTS, 0, GL.GL_BUFFER_SIZE)
GL.glDisable(GL.GL_POINT_SPRITE)
GL.glEnable(GL.GL_POINT_SMOOTH)
GL.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, GL.GL_BUFFER_SIZE)

def draw_arrows(self, elements: Any, n: int, width: float, background: bool = False):
"""
Expand Down
12 changes: 5 additions & 7 deletions src/compas_viewer/renderer/shaders/tag.frag
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,12 @@ uniform sampler2D tex;
uniform int text_num;
uniform vec3 text_color;

varying vec2 texcoord;

void main()
{
vec2 xy = gl_PointCoord;
xy.y -= 0.5;
xy.y *= text_num;
if (xy.y > 0 || xy.y < -1) {
discard;
}
{
vec2 xy = texcoord;
xy.y = 1.0 - xy.y;
float a = texture2D(tex, xy).r;
gl_FragColor = vec4(text_color, a);
if (a <= 0){
Expand Down
41 changes: 36 additions & 5 deletions src/compas_viewer/renderer/shaders/tag.vert
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,43 @@ attribute vec3 position;
uniform mat4 projection;
uniform mat4 viewworld;
uniform mat4 transform;
uniform float screen_aspect;
uniform float screen_height;
uniform float text_aspect;
uniform float text_height;
uniform vec3 text_position;
uniform int vertical_align;
uniform int horizontal_align;

uniform int text_height;
uniform int text_num;

varying vec2 texcoord;

void main()
{
gl_PointSize = text_height * text_num;
gl_Position = projection * viewworld * transform * vec4(position, 1.0);
{

texcoord = vec2(position.x, position.y);

vec2 position = vec2(position.x, position.y);

if (horizontal_align == 0) {
position.x -= 0.5;
}
else if (horizontal_align == 1) {
position.x -= 1.0;
}

if (vertical_align == 0) {
position.y -= 0.5;
}
else if (vertical_align == 1) {
position.y -= 1.0;
}


vec4 screen_position = projection * viewworld * vec4(text_position, 1.0);
vec2 adjustedPos = vec2(position.x / screen_aspect * text_aspect, position.y) * text_height / screen_height;
vec4 offset = vec4(adjustedPos * screen_position.w, 0.0, 0.0);
screen_position += offset;
gl_Position = screen_position;

}
46 changes: 37 additions & 9 deletions src/compas_viewer/scene/tagobject.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ def __init__(
height: float = 50,
absolute_height: bool = False,
font: Optional[PathLike] = None,
vertical_align: str = "bottom",
horizontal_align: str = "left",
):
super().__init__()
self.text = text
Expand All @@ -88,6 +90,8 @@ def __init__(
self.height = height
self.absolute_height = absolute_height
self.font = font or FONT
self.vertical_align = vertical_align
self.horizontal_align = horizontal_align

def transform(self, transformation):
"""Transform the tag.
Expand All @@ -109,12 +113,31 @@ class TagObject(ViewerSceneObject, GeometryObject):

geometry: Tag

VERTICAL_ALIGN = {"top": 1, "center": 0, "bottom": -1}
HORIZONTAL_ALIGN = {"left": -1, "center": 0, "right": 1}

def make_buffers(self):

positions = [
0,
0,
0,
1,
0,
0,
0,
1,
0,
1,
1,
0,
]

self._text_buffer = {
"positions": make_vertex_buffer(self.geometry.position),
"elements": make_index_buffer([0]),
"positions": make_vertex_buffer(positions),
"elements": make_index_buffer([0, 1, 2, 3]),
"text_texture": self.make_text_texture(),
"n": 1,
"n": 4,
}

def make_text_texture(self):
Expand Down Expand Up @@ -142,8 +165,7 @@ def make_text_texture(self):

# The width and height of the texture must be a multiple of 4
total_width = (total_width + 3) // 4 * 4
# The height is doubled because the text is rendered in the middle of the texture
max_height = (max_height * 2 + 3) // 4 * 4
max_height = (max_height + 10 + 3) // 4 * 4

string_buffer = zeros(shape=(max_height, total_width), dtype="uint8")

Expand Down Expand Up @@ -186,6 +208,8 @@ def make_text_texture(self):
GL.GL_UNSIGNED_BYTE,
string_buffer,
)

self.text_aspect = total_width / 50
return texture

def _calculate_text_height(self, camera_position):
Expand All @@ -195,19 +219,23 @@ def _calculate_text_height(self, camera_position):
else:
return self.geometry.height

def draw(self, shader, camera_position):
def draw(self, shader, camera_position, width, height):
"""Draw the object from its buffers"""
shader.enable_attribute("position")
if self.worldtransformation is not None:
shader.uniform4x4("transform", self.worldtransformation.matrix)
shader.uniform1f("object_opacity", self.opacity)
shader.uniform1i("text_height", self._calculate_text_height(camera_position))
shader.uniform1i("text_num", len(self.geometry.text))
shader.uniform1f("screen_aspect", width / height)
shader.uniform1f("screen_height", height)
shader.uniform1f("text_aspect", self.text_aspect)
shader.uniform1f("text_height", self._calculate_text_height(camera_position))
shader.uniform3f("text_position", self.geometry.position)
shader.uniform3f("text_color", self.geometry.color)
shader.uniform1i("vertical_align", self.VERTICAL_ALIGN[self.geometry.vertical_align])
shader.uniform1i("horizontal_align", self.HORIZONTAL_ALIGN[self.geometry.horizontal_align])
shader.uniformText("text_texture", self._text_buffer["text_texture"])
shader.bind_attribute("position", self._text_buffer["positions"])
shader.draw_texts(elements=self._text_buffer["elements"], n=self._text_buffer["n"])
shader.uniform1i("is_text", 0)
shader.uniform1f("object_opacity", 1)
shader.disable_attribute("position")

Expand Down

0 comments on commit 21f16c6

Please sign in to comment.