1
0
mirror of https://github.com/lxsang/Diya-API.git synced 2024-12-26 19:38:22 +01:00

WIP: draw ellipse and circle

This commit is contained in:
Dany LE 2022-03-16 01:32:01 +01:00
parent 653fe07692
commit 89c5e04d36
12 changed files with 410 additions and 68 deletions

View File

@ -4,11 +4,16 @@ Class {
#instVars : [
'color',
'vbuffer',
'nvertices'
'bbox'
],
#category : #'Diya-Graphics'
}
{ #category : #accessing }
Diya2DNode >> boundingBox [
^ bbox
]
{ #category : #accessing }
Diya2DNode >> color [
^ color
@ -19,6 +24,16 @@ Diya2DNode >> color: anObject [
color := anObject
]
{ #category : #accessing }
Diya2DNode >> extent [
^ bbox extent
]
{ #category : #accessing }
Diya2DNode >> height [
^ self extent y
]
{ #category : #initialization }
Diya2DNode >> initialize [
super initialize.
@ -29,7 +44,21 @@ Diya2DNode >> initialize [
shader := Diya2DShader uniqueInstance.
color := Color white.
vbuffer := nil.
nvertices := 0.
]
{ #category : #'as yet unclassified' }
Diya2DNode >> recFromBuffer [
|maxX maxY minX minY x y|
maxX := maxY := minX := minY := 0.
1 to: vbuffer size by: 4 do: [ :i|
x := vbuffer at: i.
y := vbuffer at: i + 1.
maxX := maxX max: x.
maxY := maxY max: y.
minX := minX min: x.
minY := minY min: y.
].
^ Rectangle origin: minX@minY corner: maxX @ maxY
]
{ #category : #initialization }
@ -64,3 +93,8 @@ Diya2DNode >> updateTF [
children do:[:c| c updateTF ]].
]
{ #category : #accessing }
Diya2DNode >> width [
^ self extent x
]

View File

@ -2,11 +2,24 @@ Class {
#name : #Diya2DPrimShape,
#superclass : #Diya2DNode,
#instVars : [
'texture'
'texture',
'type',
'border',
'bcolor'
],
#category : #'Diya-Graphics'
}
{ #category : #accessing }
Diya2DPrimShape >> borderColor: c [
bcolor := c
]
{ #category : #accessing }
Diya2DPrimShape >> borderWidth: w [
border := w
]
{ #category : #initialization }
Diya2DPrimShape >> draw [
vbuffer ifNil: [ ^self ].
@ -19,17 +32,44 @@ Diya2DPrimShape >> draw [
context vao enableAttribute: 0.
OpenGLVertexArray vertexAttributePointerIndex: 0 size:4 type: GL_FLOAT normalized: GL_FALSE stride: 16 pointer: nil .
context vbo data: GL_ARRAY_BUFFER data: vbuffer usage: GL_STATIC_DRAW.
OpenGL drawArrays: GL_TRIANGLES first:0 count:nvertices.
context vao disableAttribute: 0.
OpenGL drawArrays: type first:0 count:((vbuffer size )>> 2 ).
"reset value"
self texture ifNotNil: [self texture drop.].
border > 0 ifTrue: [ self drawBorder ].
context vao disableAttribute: 0.
]
{ #category : #initialization }
Diya2DPrimShape >> drawBorder [
"Diya2DShader uniqueInstance use."
color = bcolor ifFalse:[
shader setUniform: #u_color value: bcolor asGL4FArray;
setUniform: #u_texture_type value: 0.
].
OpenGL
lineWidth: border.
self drawLines.
OpenGL lineWidth: 1.0.
]
{ #category : #initialization }
Diya2DPrimShape >> drawLineAt: offset [
OpenGL drawArrays: GL_LINES first:(offset) count:2.
]
{ #category : #initialization }
Diya2DPrimShape >> drawLines [
self subclassResponsibility
]
{ #category : #initialization }
Diya2DPrimShape >> initialize [
super initialize.
texture := nil.
children := nil
children := nil.
type := GL_TRIANGLES.
border := 0.
bcolor := Color white
]
{ #category : #initialization }

View File

@ -48,6 +48,12 @@ DiyaBoot >> createGLContext [
{ #category : #events }
DiyaBoot >> createWindow [
SDL2
glSetAttribute: SDL_GL_MULTISAMPLEBUFFERS value: 1;
glSetAttribute: SDL_GL_MULTISAMPLESAMPLES value: 2.
OpenGL enable: GL_MULTISAMPLE.
window := SDL2 createWindow: 'Diya'
x: 0
y: 0
@ -68,24 +74,38 @@ DiyaBoot >> createWindow [
{ #category : #events }
DiyaBoot >> exampleNodes [
|root text rec style|
|root node style|
root := DiyaRootNode new.
rec := root addNode: (DiyaRectangle size: 200@200) at: 250 @ 430.
rec texture: (DiyaImageTex fromFile:Smalltalk imageDirectory / 'assets'/'mrsang.png').
rec color: (Color r: 1.0 g:1.0 b:1.0 alpha:1.0 ).
node := root addNode: (DiyaRectangle size: 200@200) at: 250 @ 430.
node texture: (DiyaImageTex fromFile:Smalltalk imageDirectory / 'assets'/'mrsang.png').
node color: (Color r: 1.0 g:1.0 b:1.0 alpha:1.0 ).
node borderColor: Color red.
node borderWidth: 3.0.
style := DiyaFontManager uniqueInstance style: 'Bold' from:'Ubuntu'.
rec := root addNode: (DiyaRectangle size: 208@288) at: 250 @ 50.
rec color: (Color orange).
rec texture: (style textureOf: 20).
node := root addNode: (DiyaRectangle size: 208@288) at: 250 @ 50.
node color: (Color orange).
node texture: (style textureOf: 20).
node borderColor: Color red.
node borderWidth: 3.0.
rec := root addNode: (DiyaRectangle size:100@150 shader: DiyaExampleShader uniqueInstance) at: 20 @ 400.
rec rotation: (Float pi / -8.0).
rec scale: 1.5@1.5.
node := root addNode: (DiyaRectangle size:100@150 shader: DiyaExampleShader uniqueInstance) at: 20 @ 400.
node rotation: (Float pi / -8.0).
node scale: 1.5@1.5.
text := root addNode: (DiyaText data: String loremIpsum) at: 20@320.
text extent: 200@320.
text wordWrap: true.
node := root addNode: (DiyaText data: String loremIpsum) at: 10@340.
node extent: 230@320.
node wordWrap: true.
node := root addNode: (DiyaLine from: 10@620 to: 200@635).
node color: (Color red).
node borderWidth: 2.0.
node := root addNode: (DiyaCircle r: 100) at: 200@200.
node borderColor: Color red.
node borderWidth: 2.0.
"node rotation:(Float pi / 4.0)."
^ root
]
@ -136,19 +156,24 @@ DiyaBoot >> randomColorChannel [
{ #category : #events }
DiyaBoot >> render [
|event root text delta|
|event root text delta fps maxfps minfps|
event := SDL_Event new.
root := self exampleNodes.
DiyaRenderer uniqueInstance root: root.
text := root addNode:(DiyaText data: 'tick') at: (display w - 80)@40.
text extent: 80@40.
text := root addNode:(DiyaText data: 'tick') at: (display w - 250)@40.
text extent: 250@40.
text fontSize: 20.
text color: Color red.
DiyaRendererContext uniqueInstance.
self GLinit.
fps := maxfps := 0.
minfps := self class maxFPS.
[ running ] whileTrue: [
delta := DiyaClock uniqueInstance delta asMilliSeconds.
text data: ('FPS:', (1000/delta) asInteger asString).
fps := ((1000/delta) asInteger).
maxfps := maxfps max: fps.
minfps := minfps min: fps.
text data: ('FPS:', fps asString, '(Min ', minfps asString, ', max ', maxfps asString, ')').
DiyaClock uniqueInstance tick.
[(SDL2 pollEvent: event) > 0] whileTrue: [
self processEvent: event

View File

@ -3,3 +3,13 @@ Class {
#superclass : #DiyaEllipse,
#category : #'Diya-Graphics'
}
{ #category : #'as yet unclassified' }
DiyaCircle class >> r: r [
^self rx: r ry:r
]
{ #category : #'as yet unclassified' }
DiyaCircle class >> r: r shader:s [
^self rx: r ry:r shader:s
]

View File

@ -1,5 +1,106 @@
Class {
#name : #DiyaEllipse,
#superclass : #Diya2DPrimShape,
#instVars : [
'rx',
'ry',
'delta'
],
#category : #'Diya-Graphics'
}
{ #category : #'as yet unclassified' }
DiyaEllipse class >> rx: rx ry: ry [
^self new rx: rx;
ry: ry;
yourself
]
{ #category : #'as yet unclassified' }
DiyaEllipse class >> rx: rx ry: ry shader: s [
^self new rx: rx;
ry: ry;
shader: s;
yourself
]
{ #category : #accessing }
DiyaEllipse >> delta [
^ delta
]
{ #category : #accessing }
DiyaEllipse >> delta: anObject [
delta := anObject
]
{ #category : #initialization }
DiyaEllipse >> drawLines [
0 to: (vbuffer size >> 2) by: 3 do:[: i|
self drawLineAt: i
].
]
{ #category : #initialization }
DiyaEllipse >> initialize [
super initialize.
translation := nil.
vbuffer := FFIExternalArray externalNewType: GLfloat size:4332.
vbuffer autoRelease.
]
{ #category : #accessing }
DiyaEllipse >> rx [
^ rx
]
{ #category : #accessing }
DiyaEllipse >> rx: anObject [
rx := anObject.
dirty := true.
]
{ #category : #accessing }
DiyaEllipse >> ry [
^ ry
]
{ #category : #accessing }
DiyaEllipse >> ry: anObject [
ry := anObject.
dirty := true
]
{ #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.
].
^true
]

View File

@ -1,5 +1,101 @@
Class {
#name : #DiyaLine,
#superclass : #Diya2DPrimShape,
#instVars : [
'from',
'to'
],
#category : #'Diya-Graphics'
}
{ #category : #'instance creation' }
DiyaLine class >> from: p1 to: p2 [
^ self new
from: p1;
to: p2;
yourself
]
{ #category : #'instance creation' }
DiyaLine class >> from: p1 to: p2 shader:s [
^ self new
from: p1;
to: p2;
shader: s;
yourself
]
{ #category : #'instance creation' }
DiyaLine class >> points: points [
^ self new
points: points;
yourself
]
{ #category : #accessing }
DiyaLine >> borderColor: c [
color := c
]
{ #category : #initialization }
DiyaLine >> draw [
OpenGL
"enable: GL_LINE_SMOOTH;
hint: GL_LINE_SMOOTH_HINT mode: GL_NICEST;"
lineWidth: border.
super draw.
OpenGL lineWidth: 1.0";
disable: GL_LINE_SMOOTH".
]
{ #category : #initialization }
DiyaLine >> drawBorder [
"do nothing"
]
{ #category : #accessing }
DiyaLine >> from [
^ from
]
{ #category : #accessing }
DiyaLine >> from: anObject [
from := anObject.
dirty := true.
]
{ #category : #initialization }
DiyaLine >> initialize [
super initialize.
translation := nil.
self from: 0@0.
self to: 10@10.
vbuffer := FFIExternalArray externalNewType: GLfloat size:8.
vbuffer autoRelease.
type := GL_LINES.
border := 1.0
]
{ #category : #accessing }
DiyaLine >> to [
^ to
]
{ #category : #accessing }
DiyaLine >> to: anObject [
to := anObject.
dirty := true.
]
{ #category : #accessing }
DiyaLine >> update [
|extent|
translation = from ifFalse:[self position: from].
bbox := (Rectangle origin: 0@0 corner: to - from ).
extent := bbox extent.
{
0.0. 0.0. 0.0. 0.0.
extent x. extent y. 0.0. 0.0.
} doWithIndex: [:e :i| vbuffer at: i put: e].
^true
]

View File

@ -10,7 +10,6 @@ Class {
'tf',
'shader',
'context',
'extent',
'dirty'
],
#pools : [
@ -20,16 +19,6 @@ Class {
#category : #'Diya-Graphics'
}
{ #category : #'instance creation' }
DiyaNode class >> size: size [
^(self new) extent: size; yourself
]
{ #category : #'instance creation' }
DiyaNode class >> size: size shader:s [
^(self with:s) extent: size; yourself
]
{ #category : #'instance creation' }
DiyaNode class >> with: shader [
^self new shader: shader; yourself
@ -66,18 +55,7 @@ DiyaNode >> draw [
{ #category : #accessing }
DiyaNode >> extent [
^ extent
]
{ #category : #accessing }
DiyaNode >> extent: anObject [
extent := anObject.
dirty := true
]
{ #category : #accessing }
DiyaNode >> height [
^ extent y
^ self subclassResponsibility
]
{ #category : #initialization }
@ -194,8 +172,3 @@ DiyaNode >> update [
DiyaNode >> updateTF [
self subclassResponsibility
]
{ #category : #accessing }
DiyaNode >> wdith [
^ extent x
]

View File

@ -4,6 +4,31 @@ Class {
#category : #'Diya-Graphics'
}
{ #category : #'instance creation' }
DiyaRectangle class >> size: size [
^(self new) extent: size; yourself
]
{ #category : #'instance creation' }
DiyaRectangle class >> size: size shader:s [
^(self with:s) extent: size; yourself
]
{ #category : #initialization }
DiyaRectangle >> drawLines [
self drawLineAt: 0.
self drawLineAt: 1.
self drawLineAt: 3.
self drawLineAt: 4.
]
{ #category : #accessing }
DiyaRectangle >> extent: v [
bbox := Rectangle origin:0@0 corner: v.
dirty := true
]
{ #category : #accessing }
DiyaRectangle >> initialize [
super initialize.
@ -11,18 +36,20 @@ DiyaRectangle >> initialize [
translation := nil.
vbuffer := FFIExternalArray externalNewType: GLfloat size:24.
vbuffer autoRelease.
nvertices := 6
]
{ #category : #accessing }
DiyaRectangle >> update [
|extent|
extent := self extent.
{
0.0. extent y. 0.0. 0.0.
0. 0. 0.0. 1.0.
extent x. 0.0. 1.0. 1.0.
0.0. extent y. 0.0. 0.0.
extent x. 0.0. 1.0. 1.0.
extent x. extent y. 1.0. 0.0.
extent x. 0.0. 1.0. 1.0.
extent x. extent y. 1.0. 0.0.
0.0. extent y. 0.0. 0.0.
} doWithIndex: [:e :i| vbuffer at: i put: e].
^true
]

View File

@ -47,8 +47,8 @@ DiyaText >> draw [
context texture0 active.
context vao enableAttribute: 0.
OpenGLVertexArray vertexAttributePointerIndex: 0 size:4 type: GL_FLOAT normalized: GL_FALSE stride: 16 pointer: nil .
context vbo data: GL_ARRAY_BUFFER data: vbuffer size: nvertices*16 usage: GL_STATIC_DRAW.
OpenGL drawArrays: GL_TRIANGLES first:0 count:nvertices.
context vbo data: GL_ARRAY_BUFFER data: vbuffer usage: GL_STATIC_DRAW.
OpenGL drawArrays: GL_TRIANGLES first:0 count: ((vbuffer size) >> 2).
context vao disableAttribute: 0.
"reset value"
self texture drop.
@ -58,22 +58,26 @@ DiyaText >> draw [
{ #category : #accessing }
DiyaText >> drawText [
|vertices index tex2D offset|
nvertices := 0.
index := 1.
offset := 0@0.
tex2D := self texture.
1 to: data size do: [ :i|
vertices := self getCharsVertices:(data at:i) asciiValue offset: offset on: tex2D.
vertices := self getCharsVerticesAt:i offset: offset on: tex2D.
vertices do: [
:e| vbuffer at: index put:e.
index := index + 1.
].
vertices ifNotEmpty: [ nvertices := nvertices + 6 ].
(offset x > extent x and: wrap not) ifTrue: [ ^self ].
(offset y negated > extent y) ifTrue: [ ^self ].
(offset x > self extent x and: wrap not) ifTrue: [ ^self ].
(offset y negated > self extent y) ifTrue: [ ^self ].
].
]
{ #category : #accessing }
DiyaText >> extent: v [
bbox := Rectangle origin: 0@0 corner: v.
dirty := true
]
{ #category : #accessing }
DiyaText >> fontName [
^ fontName
@ -104,10 +108,15 @@ DiyaText >> fontStyle [
]
{ #category : #accessing }
DiyaText >> getCharsVertices:c offset: offset on: tex2D [
|x y w h glyph gsize|
DiyaText >> getCharsVerticesAt:i offset: offset on: tex2D [
|x y w h glyph gsize c |
c := (data at:i) asciiValue.
c = (Character space asciiValue) ifTrue:[
offset setX: (offset x + (tex2D spacing ) ) setY: offset y.
wrap ifTrue: [
(offset x + ((self nextSpaceFrom: i + 1) * (tex2D spacing))) > (self extent x) ifTrue: [
offset setX: 0.0 setY: (offset y )- (tex2D linespace)].
].
^ {}.
].
glyph := tex2D getGlyph: c.
@ -136,6 +145,15 @@ DiyaText >> initialize [
self fontName: 'Ubuntu' style:'Regular' size: 16.
data := nil.
wrap := false.
bbox := nil
]
{ #category : #'as yet unclassified' }
DiyaText >> nextSpaceFrom: index [
index to: (data size) do: [:i|
(data at: i) = (Character space) ifTrue:[^i - index].
].
^ 0
]
{ #category : #accessing }
@ -145,7 +163,7 @@ DiyaText >> texture [
{ #category : #initialization }
DiyaText >> update [
extent ifNil: [ ^false ].
bbox ifNil: [ ^false ].
vbuffer ifNotNil: [vbuffer free].
vbuffer := FFIExternalArray externalNewType: GLfloat size: data size * 24.
vbuffer autoRelease.

View File

@ -73,11 +73,21 @@ OpenGL class >> getIntegerv: pname data: data [
^self ffiCall: #(void glGetIntegerv( GLenum pname,GLint * data))
]
{ #category : #'as yet unclassified' }
OpenGL class >> hint:target mode:mode [
^self ffiCall: #(void glHint( GLenum target,GLenum mode))
]
{ #category : #accessing }
OpenGL class >> libNames [
^#('libGL.so.1')
]
{ #category : #geometry }
OpenGL class >> lineWidth: width [
^ self ffiCall: #(void glLineWidth(GLfloat width))
]
{ #category : #accessing }
OpenGL class >> pixelstorei: pname param: param [
^self ffiCall: #(void glPixelStorei( GLenum pname,GLint param))

View File

@ -37,10 +37,14 @@ Class {
'GL_LINEAR',
'GL_LINES',
'GL_LINE_LOOP',
'GL_LINE_SMOOTH',
'GL_LINE_SMOOTH_HINT',
'GL_LINE_STRIP',
'GL_LINK_STATUS',
'GL_MAX_TEXTURE_SIZE',
'GL_MULTISAMPLE',
'GL_NEAREST',
'GL_NICEST',
'GL_ONE_MINUS_SRC_ALPHA',
'GL_PACK_ALIGNMENT',
'GL_POINTS',
@ -111,6 +115,8 @@ OpenGLConstants class >> initCommonConstants [
GL_ALPHA := 16r1906.
GL_RGB := 16r1907.
GL_RGBA := 16r1908.
GL_LINE_SMOOTH := 16r0B20.
GL_LINE_SMOOTH_HINT := 16r0C52
]
{ #category : #'class initialization' }
@ -138,7 +144,9 @@ OpenGLConstants class >> initCommonMode [
GL_ONE_MINUS_SRC_ALPHA := 16r0303.
GL_CULL_FACE := 16r0B44.
GL_PACK_ALIGNMENT := 16r0D05.
GL_UNPACK_ALIGNMENT := 16r0CF5
GL_UNPACK_ALIGNMENT := 16r0CF5.
GL_NICEST := 16r1102.
GL_MULTISAMPLE := 16r809D
]
{ #category : #'class initialization' }

View File

@ -65,7 +65,7 @@ OpenGLVertexBuffer >> data:target data: data size: size usage: usage [
{ #category : #'as yet unclassified' }
OpenGLVertexBuffer >> data:target data: data usage: usage [
self bind: target.
^OpenGLVertexBuffer bufferData: target size: data size*4 data:data getHandle usage: usage
^OpenGLVertexBuffer bufferData: target size: (data size) << 2 data:data getHandle usage: usage
]
{ #category : #'as yet unclassified' }
@ -84,7 +84,7 @@ OpenGLVertexBuffer >> initialize [
{ #category : #'as yet unclassified' }
OpenGLVertexBuffer >> subData:target offset: offset data:data [
self bind: target.
^OpenGLVertexBuffer subData: target offset: offset size: data size * 4 data: data getHandle
^OpenGLVertexBuffer subData: target offset: offset size: (data size) << 2 data: data getHandle
]
{ #category : #'as yet unclassified' }