1
0
mirror of https://github.com/lxsang/Diya-API.git synced 2025-04-20 07:26:45 +02:00

Support for basic primitive shapes

This commit is contained in:
DanyLE 2022-03-16 17:48:18 +01:00
parent 89c5e04d36
commit e8b724daa1
10 changed files with 312 additions and 54 deletions

View File

@ -49,7 +49,8 @@ Diya2DNode >> initialize [
{ #category : #'as yet unclassified' } { #category : #'as yet unclassified' }
Diya2DNode >> recFromBuffer [ Diya2DNode >> recFromBuffer [
|maxX maxY minX minY x y| |maxX maxY minX minY x y|
maxX := maxY := minX := minY := 0. maxX := minX := vbuffer at: 1.
maxY := minY := vbuffer at: 2.
1 to: vbuffer size by: 4 do: [ :i| 1 to: vbuffer size by: 4 do: [ :i|
x := vbuffer at: i. x := vbuffer at: i.
y := vbuffer at: i + 1. y := vbuffer at: i + 1.

View File

@ -69,7 +69,7 @@ Diya2DPrimShape >> initialize [
children := nil. children := nil.
type := GL_TRIANGLES. type := GL_TRIANGLES.
border := 0. border := 0.
bcolor := Color white bcolor := Color white.
] ]
{ #category : #initialization } { #category : #initialization }

View File

@ -17,7 +17,6 @@ uniform float u_time;
// 2D uniforms // 2D uniforms
uniform int u_texture_type; uniform int u_texture_type;
uniform vec4 u_color; uniform vec4 u_color;
uniform vec4 u_border_color;
uniform sampler2D u_texture; uniform sampler2D u_texture;
varying vec2 texcoord; varying vec2 texcoord;
void main(void) { void main(void) {
@ -57,5 +56,5 @@ Diya2DShader >> setUpUniforms [
self addUniform: #u_texture_type of: Uniform1i. self addUniform: #u_texture_type of: Uniform1i.
self addUniform: #u_color of: Uniform4F. self addUniform: #u_color of: Uniform4F.
self addUniform: #u_border_color of: Uniform4F. self addUniform: #u_border_color of: Uniform4F.
self addUniform: #u_border of: Uniform1i. self addUniform: #u_border of: Uniform1F.
] ]

View File

@ -74,10 +74,11 @@ DiyaBoot >> createWindow [
{ #category : #events } { #category : #events }
DiyaBoot >> exampleNodes [ DiyaBoot >> exampleNodes [
|root node style| |root node style tex|
tex := (DiyaImageTex fromFile:Smalltalk imageDirectory / 'assets'/'mrsang.png').
root := DiyaRootNode new. root := DiyaRootNode new.
node := root addNode: (DiyaRectangle size: 200@200) at: 250 @ 430. node := root addNode: (DiyaRectangle size: 200@200) at: 250 @ 430.
node texture: (DiyaImageTex fromFile:Smalltalk imageDirectory / 'assets'/'mrsang.png'). node texture: tex.
node color: (Color r: 1.0 g:1.0 b:1.0 alpha:1.0 ). node color: (Color r: 1.0 g:1.0 b:1.0 alpha:1.0 ).
node borderColor: Color red. node borderColor: Color red.
node borderWidth: 3.0. node borderWidth: 3.0.
@ -104,8 +105,16 @@ DiyaBoot >> exampleNodes [
node := root addNode: (DiyaCircle r: 100) at: 200@200. node := root addNode: (DiyaCircle r: 100) at: 200@200.
node borderColor: Color red. node borderColor: Color red.
node borderWidth: 2.0. node color: Color white.
node borderWidth: 3.0.
node texture: tex.
"node rotation:(Float pi / 4.0)." "node rotation:(Float pi / 4.0)."
node := root addNode: (DiyaConvexPolygon points:{250@100. 400@250. 450@80. 350@60}).
node color: Color green.
node borderColor: Color red.
node texture: tex.
node borderWidth: 3.0.
^ root ^ root
] ]

View File

@ -0,0 +1,48 @@
Class {
#name : #DiyaConvexPolygon,
#superclass : #DiyaPolygon,
#category : #'Diya-Graphics'
}
{ #category : #accessing }
DiyaConvexPolygon >> calculateVertices [
|size index p texcoord|
size := (points size + 1) << 2.
vbuffer ifNotNil: [ vbuffer free ].
vbuffer := FFIExternalArray externalNewType: GLfloat size:size.
vbuffer autoRelease.
points sort:[:a :b| a angle < b angle].
index := 1.
points do:[:point|
texcoord := self texcoordOf: point.
vbuffer
at: index put: point x;
at: index + 1 put: point y;
at: index + 2 put: texcoord x;
at: index + 3 put: 1.0 - texcoord y.
index := index + 4.
].
p := points at: 2.
texcoord := self texcoordOf: p.
vbuffer
at: index put: p x;
at: index + 1 put: p y;
at: index + 2 put: texcoord x;
at: index + 3 put: 1.0 - texcoord y.
]
{ #category : #initialization }
DiyaConvexPolygon >> drawLines [
OpenGL drawArrays: GL_LINE_LOOP first:0 count: (vbuffer size >> 2) - 1.
]
{ #category : #initialization }
DiyaConvexPolygon >> initialize [
super initialize.
type := GL_TRIANGLE_FAN
]
{ #category : #accessing }
DiyaConvexPolygon >> texcoordOf: point [
^ (point / (self extent )) asFloatPoint
]

View File

@ -3,8 +3,7 @@ Class {
#superclass : #Diya2DPrimShape, #superclass : #Diya2DPrimShape,
#instVars : [ #instVars : [
'rx', 'rx',
'ry', 'ry'
'delta'
], ],
#category : #'Diya-Graphics' #category : #'Diya-Graphics'
} }
@ -24,29 +23,28 @@ DiyaEllipse class >> rx: rx ry: ry shader: s [
yourself yourself
] ]
{ #category : #accessing } { #category : #initialization }
DiyaEllipse >> delta [ DiyaEllipse >> draw [
^ delta OpenGL
] enable: GL_BLEND;
blendFnWithSfactor: GL_SRC_ALPHA dfactor: GL_ONE_MINUS_SRC_ALPHA.
{ #category : #accessing } super draw.
DiyaEllipse >> delta: anObject [ OpenGL
delta := anObject disable: GL_BLEND
] ]
{ #category : #initialization } { #category : #initialization }
DiyaEllipse >> drawLines [ DiyaEllipse >> drawBorder [
0 to: (vbuffer size >> 2) by: 3 do:[: i| "do nothing"
self drawLineAt: i
].
] ]
{ #category : #initialization } { #category : #initialization }
DiyaEllipse >> initialize [ DiyaEllipse >> initialize [
super initialize. super initialize.
translation := nil. translation := nil.
vbuffer := FFIExternalArray externalNewType: GLfloat size:4332. vbuffer := FFIExternalArray externalNewType: GLfloat size: 24.
vbuffer autoRelease. vbuffer autoRelease.
shader := DiyaEllipseShader uniqueInstance.
] ]
{ #category : #accessing } { #category : #accessing }
@ -71,36 +69,27 @@ DiyaEllipse >> ry: anObject [
dirty := true dirty := true
] ]
{ #category : #initialization }
DiyaEllipse >> setUpShader [
super setUpShader.
self shader
setUniform: #u_border value: border;
setUniform: #u_border_color value: bcolor asGL4FArray;
setUniform: #u_rx value: rx;
setUniform: #u_ry value: ry.
]
{ #category : #accessing } { #category : #accessing }
DiyaEllipse >> update [ DiyaEllipse >> update [
|theta c s x y index t| bbox := Rectangle origin: ((rx negated) @ (ry negated)) corner: (rx @ ry).
bbox := Rectangle origin: ((rx negated) @ (ry negated)) / 2.0 corner: (rx @ ry) / 2.0. {
theta := 2.0 * (Float pi) / 360.0. bbox origin x. bbox corner y. 0.0. 0.0.
c := theta cos. bbox origin x. bbox origin y. 0.0. 1.0.
s := theta sin. bbox corner x. bbox origin y. 1.0. 1.0.
x := 1.
y := 0. bbox corner x. bbox origin y. 1.0. 1.0.
index := 1. bbox corner x. bbox corner y. 1.0. 0.0.
0 to: 360 do:[:a| bbox origin x. bbox corner y. 0.0. 0.0.
vbuffer } doWithIndex: [:e :i| vbuffer at: i put: e].
at: index + 4 put: x * rx;
at: index + 5 put: y * ry;
at: index + 6 put: 0.0;
at: index + 7 put: 0.0.
t := x.
x := (c * x) - (s * y).
y := (s * t) + (c * y).
vbuffer
at: index put: x*rx;
at: index + 1 put: y*ry;
at: index + 2 put: 0.0;
at: index + 3 put: 0.0;
at: index + 8 put: 0.0;
at: index + 9 put: 0.0;
at: index + 10 put: 0.0;
at: index + 11 put: 0.0.
index := index + 12.
].
^true ^true
] ]

View File

@ -0,0 +1,146 @@
Class {
#name : #DiyaEllipseShader,
#superclass : #Diya2DShader,
#category : #'Diya-Shaders'
}
{ #category : #accessing }
DiyaEllipseShader class >> fragmentShader [
^'
#ifdef GL_ES
precision highp float;
#endif
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
// 2D uniforms
uniform int u_texture_type;
uniform vec4 u_color;
uniform vec4 u_border_color;
uniform sampler2D u_texture;
uniform float u_border;
uniform float u_rx;
uniform float u_ry;
varying float rotation;
varying vec2 middle;
varying vec2 texcoord;
struct Ellipse
{
vec2 c;
float minor;
float major;
float f;
};
float get_foci(float major, float minor)
{
return sqrt((major*major)-(minor*minor));
}
Ellipse create_ellipse(vec2 c, float mi, float ma)
{
Ellipse e;
e.c = c;
e.major = max(mi,ma);
e.minor = min(mi,ma);
e.f = get_foci(e.major, e.minor);
return e;
}
bool is_inside_ellipse(vec2 p, Ellipse e)
{
float first = ((p.x-e.c.x)*(p.x-e.c.x)) / (e.major*e.major);
float second = ((p.y-e.c.y)*(p.y-e.c.y)) / (e.minor*e.minor);
return first+second <= 1.0;
}
bool is_inside_border(vec2 p, Ellipse e, float w)
{
float first = ((p.x-e.c.x)*(p.x-e.c.x)) / ((e.major-w)*(e.major-w));
float second = ((p.y-e.c.y)*(p.y-e.c.y)) / ((e.minor-w)*(e.minor-w));
float sum = first + second;
return sum<= 1.0;
}
void draw_ellipse(inout vec4 c, vec2 p, Ellipse e, float border)
{
c = vec4(0);
if (is_inside_border(p,e, border))
{
vec4 texcolor = vec4(1);
// vec2 uv = (p - (e.c - vec2(e.major , e.minor))) / vec2(e.major*2.0, e.minor*2.0);
// alpha
if(u_texture_type == 0x1906) {
texcolor = vec4(1, 1, 1, texture2D(u_texture, texcoord).a);
}
// rgba
else if (u_texture_type == 0x1908){
texcolor = texture2D(u_texture, texcoord);
}
c = texcolor * u_color;
}
else
{
if (is_inside_ellipse(p, e))
{
c = u_border_color;
}
}
}
vec2 rotate_point(vec2 center, vec2 p,float angle)
{
float s = sin(angle);
float c = cos(angle);
// translate point back to origin:
p.x -= center.x;
p.y -= center.y;
// rotate point
float xnew = p.x * c - p.y * s;
float ynew = p.x * s + p.y * c;
// translate point back:
p.x = xnew + center.x;
p.y = ynew + center.y;
return p;
}
void main() {
vec4 color = vec4(0);
//defining ellipse
Ellipse e = create_ellipse(middle, u_ry, u_rx);
draw_ellipse(color, rotate_point(middle, gl_FragCoord.xy, rotation), e, u_border);
// Output to screen
gl_FragColor = color;
}
'
]
{ #category : #accessing }
DiyaEllipseShader class >> vertexShader [
^'
#ifdef GL_ES
precision mediump float;
#endif
uniform mat4 u_projection;
uniform mat3 u_transform;
varying float rotation;
varying vec2 middle;
varying vec2 texcoord;
void main()
{
vec3 coord_global = u_transform * vec3(gl_Vertex.xy, 1.0);
gl_Position = u_projection * vec4(coord_global.xy, 0, 1.0);
rotation = atan(u_transform[1][0], u_transform[0][0]);
middle = (u_transform * vec3(0.0,0.0,1.0)).xy;
texcoord = gl_Vertex.zw;
}'
]
{ #category : #initialization }
DiyaEllipseShader >> setUpUniforms [
super setUpUniforms.
self addUniform: #u_rx of: Uniform1F.
self addUniform: #u_ry of: Uniform1F.
]

View File

@ -90,9 +90,13 @@ DiyaLine >> to: anObject [
{ #category : #accessing } { #category : #accessing }
DiyaLine >> update [ DiyaLine >> update [
|extent| |extent|
translation = from ifFalse:[self position: from]. bbox := (Rectangle origin: from corner: to ).
bbox := (Rectangle origin: 0@0 corner: to - from ). bbox origin = translation ifFalse:[self position: bbox origin].
from := from - bbox origin.
to := to - bbox origin.
extent := bbox extent. extent := bbox extent.
bbox := (Rectangle origin: 0@0 corner: extent ).
{ {
0.0. 0.0. 0.0. 0.0. 0.0. 0.0. 0.0. 0.0.
extent x. extent y. 0.0. 0.0. extent x. extent y. 0.0. 0.0.

View File

@ -1,5 +1,67 @@
Class { Class {
#name : #DiyaPolygon, #name : #DiyaPolygon,
#superclass : #Diya2DPrimShape, #superclass : #Diya2DPrimShape,
#instVars : [
'points'
],
#category : #'Diya-Graphics' #category : #'Diya-Graphics'
} }
{ #category : #'as yet unclassified' }
DiyaPolygon class >> points: points [
^self new points: points; yourself
]
{ #category : #'as yet unclassified' }
DiyaPolygon class >> points: points shader:s [
^self new points: points; shader:s; yourself
]
{ #category : #accessing }
DiyaPolygon >> calculateVertices [
^self subclassResponsibility
]
{ #category : #initialization }
DiyaPolygon >> initialize [
super initialize.
points := {}.
vbuffer := nil.
]
{ #category : #accessing }
DiyaPolygon >> points [
^ points
]
{ #category : #accessing }
DiyaPolygon >> points: anObject [
points := anObject.
dirty := true
]
{ #category : #accessing }
DiyaPolygon >> recFromPoints [
|maxX maxY minX minY x y|
maxX := minX := (points at: 1) x.
maxY := minY := (points at: 1) y.
points do: [ :p|
x := p x.
y := p y.
maxX := maxX max: x.
maxY := maxY max: y.
minX := minX min: x.
minY := minY min: y.
].
^ Rectangle origin: minX@minY corner: maxX @ maxY
]
{ #category : #accessing }
DiyaPolygon >> update [
bbox := self recFromPoints.
translation = bbox origin ifFalse:[ self position: bbox origin].
points := points collect:[:e | e - bbox origin].
bbox := self recFromPoints.
self calculateVertices.
^true
]

View File

@ -74,7 +74,7 @@ DiyaText >> drawText [
{ #category : #accessing } { #category : #accessing }
DiyaText >> extent: v [ DiyaText >> extent: v [
bbox := Rectangle origin: 0@0 corner: v. bbox := Rectangle origin: 0@0 corner: (v x) @ (v y negated ).
dirty := true dirty := true
] ]