diff --git a/Diya/Diya2DNode.class.st b/Diya/Diya2DNode.class.st index 607db27..b8aeddb 100644 --- a/Diya/Diya2DNode.class.st +++ b/Diya/Diya2DNode.class.st @@ -49,7 +49,8 @@ Diya2DNode >> initialize [ { #category : #'as yet unclassified' } Diya2DNode >> recFromBuffer [ |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| x := vbuffer at: i. y := vbuffer at: i + 1. diff --git a/Diya/Diya2DPrimShape.class.st b/Diya/Diya2DPrimShape.class.st index c2b6ad4..4578c8c 100644 --- a/Diya/Diya2DPrimShape.class.st +++ b/Diya/Diya2DPrimShape.class.st @@ -69,7 +69,7 @@ Diya2DPrimShape >> initialize [ children := nil. type := GL_TRIANGLES. border := 0. - bcolor := Color white + bcolor := Color white. ] { #category : #initialization } diff --git a/Diya/Diya2DShader.class.st b/Diya/Diya2DShader.class.st index a67aa60..11b010b 100644 --- a/Diya/Diya2DShader.class.st +++ b/Diya/Diya2DShader.class.st @@ -17,7 +17,6 @@ uniform float u_time; // 2D uniforms uniform int u_texture_type; uniform vec4 u_color; -uniform vec4 u_border_color; uniform sampler2D u_texture; varying vec2 texcoord; void main(void) { @@ -57,5 +56,5 @@ Diya2DShader >> setUpUniforms [ self addUniform: #u_texture_type of: Uniform1i. self addUniform: #u_color of: Uniform4F. self addUniform: #u_border_color of: Uniform4F. - self addUniform: #u_border of: Uniform1i. + self addUniform: #u_border of: Uniform1F. ] diff --git a/Diya/DiyaBoot.class.st b/Diya/DiyaBoot.class.st index 22a955e..2aad0c1 100644 --- a/Diya/DiyaBoot.class.st +++ b/Diya/DiyaBoot.class.st @@ -74,10 +74,11 @@ DiyaBoot >> createWindow [ { #category : #events } DiyaBoot >> exampleNodes [ - |root node style| + |root node style tex| + tex := (DiyaImageTex fromFile:Smalltalk imageDirectory / 'assets'/'mrsang.png'). root := DiyaRootNode new. 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 borderColor: Color red. node borderWidth: 3.0. @@ -104,8 +105,16 @@ DiyaBoot >> exampleNodes [ node := root addNode: (DiyaCircle r: 100) at: 200@200. 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 := 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 ] diff --git a/Diya/DiyaConvexPolygon.class.st b/Diya/DiyaConvexPolygon.class.st new file mode 100644 index 0000000..1f547c1 --- /dev/null +++ b/Diya/DiyaConvexPolygon.class.st @@ -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 +] diff --git a/Diya/DiyaEllipse.class.st b/Diya/DiyaEllipse.class.st index 6241f05..790f00b 100644 --- a/Diya/DiyaEllipse.class.st +++ b/Diya/DiyaEllipse.class.st @@ -3,8 +3,7 @@ Class { #superclass : #Diya2DPrimShape, #instVars : [ 'rx', - 'ry', - 'delta' + 'ry' ], #category : #'Diya-Graphics' } @@ -24,29 +23,28 @@ DiyaEllipse class >> rx: rx ry: ry shader: s [ yourself ] -{ #category : #accessing } -DiyaEllipse >> delta [ - ^ delta -] - -{ #category : #accessing } -DiyaEllipse >> delta: anObject [ - delta := anObject +{ #category : #initialization } +DiyaEllipse >> draw [ + OpenGL + enable: GL_BLEND; + blendFnWithSfactor: GL_SRC_ALPHA dfactor: GL_ONE_MINUS_SRC_ALPHA. + super draw. + OpenGL + disable: GL_BLEND ] { #category : #initialization } -DiyaEllipse >> drawLines [ - 0 to: (vbuffer size >> 2) by: 3 do:[: i| - self drawLineAt: i - ]. +DiyaEllipse >> drawBorder [ + "do nothing" ] { #category : #initialization } DiyaEllipse >> initialize [ super initialize. translation := nil. - vbuffer := FFIExternalArray externalNewType: GLfloat size:4332. + vbuffer := FFIExternalArray externalNewType: GLfloat size: 24. vbuffer autoRelease. + shader := DiyaEllipseShader uniqueInstance. ] { #category : #accessing } @@ -71,36 +69,27 @@ DiyaEllipse >> ry: anObject [ 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 } DiyaEllipse >> update [ - |theta c s x y index t| - bbox := Rectangle origin: ((rx negated) @ (ry negated)) / 2.0 corner: (rx @ ry) / 2.0. - theta := 2.0 * (Float pi) / 360.0. - c := theta cos. - s := theta sin. - x := 1. - y := 0. - index := 1. - 0 to: 360 do:[:a| - vbuffer - 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. - ]. + bbox := Rectangle origin: ((rx negated) @ (ry negated)) corner: (rx @ ry). + { + bbox origin x. bbox corner y. 0.0. 0.0. + bbox origin x. bbox origin y. 0.0. 1.0. + bbox corner x. bbox origin y. 1.0. 1.0. + + bbox corner x. bbox origin y. 1.0. 1.0. + bbox corner x. bbox corner y. 1.0. 0.0. + bbox origin x. bbox corner y. 0.0. 0.0. + } doWithIndex: [:e :i| vbuffer at: i put: e]. ^true ] diff --git a/Diya/DiyaEllipseShader.class.st b/Diya/DiyaEllipseShader.class.st new file mode 100644 index 0000000..5c6b49a --- /dev/null +++ b/Diya/DiyaEllipseShader.class.st @@ -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. +] diff --git a/Diya/DiyaLine.class.st b/Diya/DiyaLine.class.st index f989608..8c2cd65 100644 --- a/Diya/DiyaLine.class.st +++ b/Diya/DiyaLine.class.st @@ -90,9 +90,13 @@ DiyaLine >> to: anObject [ { #category : #accessing } DiyaLine >> update [ |extent| - translation = from ifFalse:[self position: from]. - bbox := (Rectangle origin: 0@0 corner: to - from ). + bbox := (Rectangle origin: from corner: to ). + bbox origin = translation ifFalse:[self position: bbox origin]. + from := from - bbox origin. + to := to - bbox origin. extent := bbox extent. + bbox := (Rectangle origin: 0@0 corner: extent ). + { 0.0. 0.0. 0.0. 0.0. extent x. extent y. 0.0. 0.0. diff --git a/Diya/DiyaPolygon.class.st b/Diya/DiyaPolygon.class.st index 9e44aca..d48192d 100644 --- a/Diya/DiyaPolygon.class.st +++ b/Diya/DiyaPolygon.class.st @@ -1,5 +1,67 @@ Class { #name : #DiyaPolygon, #superclass : #Diya2DPrimShape, + #instVars : [ + 'points' + ], #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 +] diff --git a/Diya/DiyaText.class.st b/Diya/DiyaText.class.st index 49b666d..61f36f6 100644 --- a/Diya/DiyaText.class.st +++ b/Diya/DiyaText.class.st @@ -74,7 +74,7 @@ DiyaText >> drawText [ { #category : #accessing } DiyaText >> extent: v [ - bbox := Rectangle origin: 0@0 corner: v. + bbox := Rectangle origin: 0@0 corner: (v x) @ (v y negated ). dirty := true ]