-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathwebGLExercise8.html
More file actions
359 lines (302 loc) · 17.5 KB
/
webGLExercise8.html
File metadata and controls
359 lines (302 loc) · 17.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<script src="Libraries/webgl-debug.js"></script>
<script src="Libraries/gl-matrix-min.js"></script>
<script id="vShader" type="x-shader/x-vertex">
attribute vec4 aVertexPosition;
attribute vec4 aVertexColor;
uniform mat4 uModelTransform;
// ΒΗΜΑ.1 Δηλώστε ένα νέο έξτρα uniform (όπως το ακριβώς προηγούμενο) με όνομα uPerspectiveViewTransform
// που θα υποδεχθεί τον πίνακα μετασχηματισμού προοπτικής/κάμερας (Perspective/View)
uniform mat4 uPerspectiveViewTransform;
varying vec4 vColor;
void main() {
// ΒΗΜΑ.2 Το νέο uniform uPerspectiveViewTransform πρέπει να συμμετέχει
// και αυτό στον παρακάτω πολλαπλασιασμό για τη θέση της κάθε κορυφής,
// ως πρώτο στο γινόμενο
// (αφού θέλουμε να εφαρμοστεί μετά από πιθανές μετακινήσεις, δημιουργία αντιγράφων κλπ.
// που περιέχονται στο uniform uVerticesTransform)
gl_Position = uPerspectiveViewTransform * uModelTransform * aVertexPosition;
vColor = aVertexColor;
}
</script>
<script id="fShader" type="x-shader/x-fragment">
precision mediump float;
varying vec4 vColor;
void main() {
gl_FragColor = vColor;
}
</script>
<script>
var gl;
var canvas;
var shadersProgram;
var vertexPositionAttributePointer;
var vertexColorAttributePointer;
var modelUniformPointer;
// ΒΗΜΑ.3. Δηλώστε μία νέα global μεταβλητή με όνομα perspectiveViewUniformPointer
// για την αποθήκευση της διεύθυνσης του νέου uniform
var perspectiveViewUniformPointer;
var vertexBuffer;
var colorBuffer;
var indexBuffer;
var translationMatrix = new Float32Array(16);
var scaleMatrix = new Float32Array(16);
var finalMatrix = new Float32Array(16);
var scaleFactor = 1.01;
var scale = 1.0;
var floorVBuffer;
var floorCBuffer;
var floorIBuffer;
var requestID = 0;
var totalAngle = -1.0; // ΒΗΜΑ.4. (Read-only) To totalAngle θα αλλάξει ρόλο σε σχέση με τις
// προηγούμενες ασκήσεις: θα χρησιμοποιηθεί για την περιστροφή της κάμερας
// (όχι πια για την περιστροφή των αντικειμένων)
// ΒΗΜΑ.5. ΠΡΟΣΘΕΣΤΕ ΕΔΩ ΤΗ ΔΗΛΩΣΗ ΜΙΑΣ GLOBAL ΜΕΤΑΒΛΗΤΗΣ totalZ ΓΙΑ ΤΟ ΣΥΝΟΛΙΚΟ ΥΨΟΣ Z ΤΗΣ ΚΑΜΕΡΑΣ ΚΑΙ ΑΡΧΙΚΟΠΟΙΗΣΤΕ ΤΗ ΣΕ 0.01 (ακολουθεί το ΒΗΜΑ.6. στο τέλος του κώδικα, στην HTML)
var totalZ = 0.01;
// ΒΗΜΑ.7. Δηλώστε τρεις νέους πίνακες για να υποδεχθούν:
// - τον πίνακα προοπτικής perspectiveMatrix
// - τον πίνακα τοποθέτησης της κάμερας viewMatrix
// - και το γινόμενό τους pvMatrix
var perspectiveMatrix = new Float32Array(16);
var viewMatrix = new Float32Array(16);
var pvMatrix = new Float32Array(16);
function createGLContext(inCanvas) {
var outContext = null;
outContext = inCanvas.getContext("webgl");
if (!outContext)
outContext = inCanvas.getContext("experimental-webgl");
if (!outContext)
alert("WebGL rendering context creation error.");
return outContext;
}
function createCompileShader(shaderType, shaderSource) {
var outShader = gl.createShader(shaderType);
gl.shaderSource(outShader, shaderSource);
gl.compileShader(outShader);
if (!gl.getShaderParameter(outShader, gl.COMPILE_STATUS)) {
alert( "Shader compilation error. " + gl.getShaderInfoLog(outShader) );
gl.deleteShader(outShader);
outShader = null;
}
return outShader;
}
function initShaders() {
var vertexShaderSource = document.getElementById("vShader").textContent;
var fragmentShaderSource = document.getElementById("fShader").textContent;
var vertexShader = createCompileShader(gl.VERTEX_SHADER, vertexShaderSource);
var fragmentShader = createCompileShader(gl.FRAGMENT_SHADER, fragmentShaderSource);
shadersProgram = gl.createProgram();
gl.attachShader(shadersProgram, vertexShader);
gl.attachShader(shadersProgram, fragmentShader);
gl.linkProgram(shadersProgram);
if (!gl.getProgramParameter(shadersProgram, gl.LINK_STATUS)) {
alert("Shaders linking error.");
}
gl.useProgram(shadersProgram);
vertexPositionAttributePointer = gl.getAttribLocation(shadersProgram, "aVertexPosition");
gl.enableVertexAttribArray(vertexPositionAttributePointer);
vertexColorAttributePointer = gl.getAttribLocation(shadersProgram, "aVertexColor");
gl.enableVertexAttribArray(vertexColorAttributePointer);
modelUniformPointer = gl.getUniformLocation(shadersProgram, "uModelTransform");
// ΒΗΜΑ.8. Αποθηκεύστε στο σχετικό pointer (η global μεταβλητή) τη διεύθυνση του νέου uniform uPerspectiveViewTransform
// (όπως η ακριβώς γίνεται στην αμέσως προηγούμενη εντολή για το άλλο uniform με τον άλλο pointer
perspectiveViewUniformPointer = gl.getUniformLocation(shadersProgram, "uPerspectiveViewTransform");
}
function initBuffers() {
// ΤΕΤΡΑΕΔΡΑ - Κορυφές, χρώματα και δείκτες
var tetraVertices = new Float32Array([
0.0, 0.0, 0.4, 1.0, // Κορυφή Α
-0.2, -0.2, 0.0, 1.0, // Κορυφή Β
0.2, -0.2, 0.0, 1.0, // Κορυφή Γ
0.0, 0.2, 0.0, 1.0 // Κορυφή Δ
]);
vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, tetraVertices, gl.STATIC_DRAW);
vertexBuffer.itemSize = 4;
vertexBuffer.itemCount = 4;
var tetraColors = new Float32Array([
1.0, 0.0, 0.0, 1.0, // Χρώμα κορυφής Α: κόκκινο
0.0, 1.0, 0.0, 1.0, // Χρώμα κορυφής Β: πράσινο
0.0, 0.0, 1.0, 1.0, // Χρώμα κορυφής Γ: μπλε
1.0, 1.0, 0.0, 1.0 // Χρώμα κορυφής Δ: κίτρινο
]);
colorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
gl.bufferData(gl.ARRAY_BUFFER, tetraColors, gl.STATIC_DRAW);
colorBuffer.itemSize = 4;
colorBuffer.itemCount = 4;
var indexMatrix = new Uint16Array([
0,1,2, // ΑΒΓ
0,2,3, // ΑΓΔ
0,3,1, // ΑΔΒ
1,3,2 // ΒΔΓ
]);
indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indexMatrix,gl.STATIC_DRAW);
indexBuffer.itemCount = 12;
// ΤΕΤΡΑΕΔΡΑ - Τέλος κορυφών, χρωμάτων και δεικτών
// ΠΑΤΩΜΑ - Κορυφές, χρώματα και δείκτες
var floorVertices = new Float32Array([
-0.9, 0.9, 0.0, 1.0, // Κορυφή Α
0.9, 0.9, 0.0, 1.0, // Κορυφή Β
-0.9, -0.9, 0.0, 1.0, // Κορυφή Γ
0.9, -0.9, 0.0, 1.0 // Κορυφή Δ
]);
floorVBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, floorVBuffer);
gl.bufferData(gl.ARRAY_BUFFER, floorVertices, gl.STATIC_DRAW);
floorVBuffer.itemSize = 4;
floorVBuffer.itemCount = 4;
var floorColors = new Float32Array([
0.2, 0.2, 0.2, 1.0, // Χρώμα κορυφής Α: κόκκινο
0.4, 0.4, 0.4, 1.0, // Χρώμα κορυφής Β: πράσινο
0.6, 0.6, 0.6, 1.0, // Χρώμα κορυφής Γ: μπλε
0.8, 0.8, 0.8, 1.0, // Χρώμα κορυφής Δ: κίτρινο
]);
floorCBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, floorCBuffer);
gl.bufferData(gl.ARRAY_BUFFER, floorColors, gl.STATIC_DRAW);
floorCBuffer.itemSize = 4;
floorCBuffer.itemCount = 4;
var floorIMatrix = new Uint16Array([
0,1,2, // ΑΒΓ
1,2,3, // BΓΔ
]);
floorIBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, floorIBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, floorIMatrix,gl.STATIC_DRAW);
floorIBuffer.itemCount = 6;
// ΠΑΤΩΜΑ - Τέλος κορυφών, χρωμάτων και δεικτών
}
function drawScene() {
// Ομάδα εντολών για υπολογισμό συνολικής γωνίας περιστροφής από το βήμα περιστροφής του χρήστη
// και την προηγούμενη τιμή της
var txtStepAngle;
txtStepAngle = document.getElementById("stepAngleTxt").value;
var numStepAngle = parseFloat(txtStepAngle);
numStepAngle = numStepAngle*Math.PI/180.0;
totalAngle += numStepAngle;
// ΒΗΜΑ.9. Προσθέστε τις εντολές για να "ψαρέψετε" την τιμή του βήματος κατά z της κάμερας
// από το αντίστοιχο textbox και να υπολογίσετε το συνολικό z (ύψος) της κάμερας
// από το βήμα του χρήστη (στο textbox) και την προηγούμενη τιμή του
// (παρόμοια με τον υπολογισμό του totalAngle ακριβώς πριν, χωρίς βέβαια τη μετατροπή σε ακτίνια)
var txtCameraHeight;
txtCameraHeight = document.getElementById("cameraHeightTxt").value;
var numCameraHeight = parseFloat(txtCameraHeight);
totalZ += numCameraHeight;
// ***---*** Αρχή δημιουργίας πίνακα προοπτικής/κάμερας και ταΐσματος στο νέο uniform
/* ΒΗΜΑ.10. ΝΑ ΔΗΜΙΟΥΡΓΗΘΕΙ Ο ΠΙΝΑΚΑΣ viewMatrix (View Matrix) ΚΑΙ ΝΑ ΠΕΡΙΕΧΕΙ ΤΟ ΜΕΤΑΣΧΗΜΑΤΙΣΜΟ ΓΙΑ ΤΗ ΤΟΠΟΘΕΤΗΣΗ ΤΗΣ ΚΑΜΕΡΑΣ
Χρησιμοποιήστε τη σχετική συνάρτηση βιβλιοθήκης lookAt, δείτε τις παραμέτρους και στο documentation https://glmatrix.net/docs/module-mat4.html):
- (Α) ΓΙΑ ΤΗ ΘΕΣΗ ΝΑ ΛΑΒΕΤΕ ΥΠ'ΟΨΗ ΤΙΣ ΤΙΜΕΣ ΤΩΝ GLOBAL ΜΕΤΑΒΛΗΤΩΝ ΓΙΑ ΤΗ ΓΩΝΙΑ ΚΑΙ ΤΟ ΥΨΟΣ
-- ΤΟ totalAngle ΑΛΛΑΞΕ ΡΟΛΟ, ΤΩΡΑ ΕΠΗΡΕΑΖΕΙ ΤΗ ΘΕΣΗ ΤΗΣ ΚΑΜΕΡΑΣ ΩΣ ΠΡΟΣ x,y Ή, ΑΛΛΙΩΣ,
ΤΗ ΓΩΝΙΑ ΠΕΡΙΣΤΡΟΦΗΣ ΤΗΣ ΚΑΜΕΡΑΣ ΓΥΡΩ ΑΠΟ ΤΟΝ ΑΞΟΝΑ z.
Δηλαδή, το x της κάμερας θα είναι r*cos(totalAngle) και το y της κάμερας θα είναι r*sin(totalAngle), όπου r η ακτίνα περιστροφής που θέλουμε (π.χ. χρησιμοποιήστε r=2 για ακτίνα κοντά αλλά έξω από το "πάτωμα").
ΧΡΗΣΙΜΟΠΟΙΗΣΤΕ ΤΗΝ ΚΛΑΣΗ/ΒΙΒΛΙΟΘΗΚΗ Math ΤΗΣ Javascript για τα cos και sin
- (Β) ΓΙΑ ΤΗΝ ΚΑΤΕΥΘΥΝΣΗ ΠΑΡΑΤΗΡΗΣΗΣ, Η ΚΑΜΕΡΑ "ΚΟΙΤΑΖΕΙ" ΠΡΟΣ ΤΗΝ ΑΡΧΗ ΤΩΝ ΑΞΟΝΩΝ: [0,0,0]
- (Γ) ΓΙΑ ΤΟΝ ΑΝΩ ΠΡΟΣΑΝΑΤΟΛΙΣΜΟ, ΤΟ ΠΑΝΩ ΜΕΡΟΣ ΤΗΣ ΕΙΝΑΙ ΠΡΟΣ ΤΗ ΘΕΤΙΚΗ ΦΟΡΑ ΤΟΥ z: [0,0,1] */
var r;
var x;
var y;
r = 2;
x = r * Math.cos(totalAngle);
y = r * Math.sin(totalAngle);
glMatrix.mat4.lookAt(viewMatrix, [x, y, totalZ], [0,0,0], [0,0,1]);
/* ΒΗΜΑ.11. ΝΑ ΔΗΜΙΟΥΡΓΗΘΕΙ Ο ΠΙΝΑΚΑΣ perspectiveMatrix (Perspective Matrix) ΚΑΙ ΝΑ ΠΕΡΙΕΧΕΙ ΤΟ ΜΕΤΑΣΧΗΜΑΤΙΣΜΟ ΓΙΑ ΤΗΝ ΠΡΟΟΠΤΙΚΗ (χρησιμοποιήστε τη σχετική συνάρτηση βιβλιοθήκης perspective, δείτε τις παραμέτρους στο documentation https://glmatrix.net/docs/module-mat4.html): */
// Για τις τιμές των παραμέτρων χρησιμοποιήστε:
// near --> 0.01
// far --> 100
// field_of_view --> Math.PI/2
// aspect --> 1
glMatrix.mat4.perspective(perspectiveMatrix, Math.PI/2, 1, 0.01, 100);
/* ΒΗΜΑ.12. ΥΠΟΛΟΓΙΣΤΕ ΤΟ ΓΙΝΟΜΕΝΟ ΤΟΥΣ ΚΑΙ ΑΠΟΘΗΚΕΥΣΤΕ ΤΟ ΣΤΟN pvMatrix
- ΤΟ ΟΝΟΜΑ ΥΠΟΝΟΕΙ ΚΑΙ ΤΗ ΣΕΙΡΑ ΣΤΟΝ ΠΟΛΛΑΠΛΑΣΙΑΣΜΟ */
glMatrix.mat4.multiply(pvMatrix, perspectiveMatrix, viewMatrix);
// ΒΗΜΑ.13. Ταΐζεται ο πίνακας pvMatrix στο νέο uniform
// μέσω του pointer που αντιστοιχεί στο uniform
// (μετά την ολοκλήρωση του ΒΗΜΑΤΟΣ.12. ο πίνακας θα περιέχει
// σε κάθε εκτέλεση της redraw τη νέα θέση της κάμερας και την αντίστοιχη προοπτική)
// Είναι η αντίστοιχη εντολή με τη 3η εντολή μέσα στο σώμα της for παρακάτω
gl.uniformMatrix4fv(perspectiveViewUniformPointer, false, pvMatrix);
// ***---*** Τέλος δημιουργίας πίνακα προοπτικής/κάμερας και ταΐσματος στο νέο uniform
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.vertexAttribPointer(vertexPositionAttributePointer, vertexBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
gl.vertexAttribPointer(vertexColorAttributePointer, colorBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
if (scale > 1.5)
scaleFactor = 0.99;
if (scale < 0.5)
scaleFactor = 1.01;
scale = scaleFactor*scale;
glMatrix.mat4.fromScaling(scaleMatrix,[scale,scale,1.0]);
for (var p = -0.5; p<=0.5; p+=0.5)
{
glMatrix.mat4.fromTranslation(translationMatrix,[p,p,0]);
glMatrix.mat4.multiply(finalMatrix,translationMatrix,scaleMatrix);
gl.uniformMatrix4fv(modelUniformPointer, false, finalMatrix);
gl.drawElements(gl.TRIANGLES,indexBuffer.itemCount,gl.UNSIGNED_SHORT, 0);
}
gl.bindBuffer(gl.ARRAY_BUFFER, floorVBuffer);
gl.vertexAttribPointer(vertexPositionAttributePointer, floorVBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, floorCBuffer);
gl.vertexAttribPointer(vertexColorAttributePointer, floorCBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, floorIBuffer);
glMatrix.mat4.identity(finalMatrix);
gl.uniformMatrix4fv(modelUniformPointer, false, finalMatrix);
gl.drawElements(gl.TRIANGLES,floorIBuffer.itemCount,gl.UNSIGNED_SHORT, 0);
}
function main() {
minDimension = Math.min(window.innerHeight, window.innerWidth);
canvas = document.getElementById("sceneCanvas");
canvas.width = 0.9*minDimension;
canvas.height = 0.9*minDimension;
gl = WebGLDebugUtils.makeDebugContext(createGLContext(canvas));
initShaders();
initBuffers();
gl.clearColor(0.5, 0.5, 0.5, 1.0);
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
gl.enable(gl.DEPTH_TEST);
drawScene();
}
function startAnimation() {
if (requestID == 0)
requestID = window.requestAnimationFrame(animationStep);
}
function animationStep() {
drawScene();
requestID = window.requestAnimationFrame(animationStep);
}
function stopAnimation() {
window.cancelAnimationFrame(requestID);
requestID = 0;
}
</script>
</head>
<body onload="main()">
<canvas id="sceneCanvas">
</canvas>
<p>
Βήμα γωνίας περιστροφής της κάμερας:<input type="text" id="stepAngleTxt" value="1" autocomplete="off">
<!-- ΒΗΜΑ.6. ΠΡΟΣΘΕΣΤΕ ΕΔΩ ΕΝΑ ΤΕΧΤ ΒΟΧ ΓΙΑ ΤΟ ΒΗΜΑ ΤΟΥ ΥΨΟΥΣ ΤΗΣ ΚΑΜΕΡΑΣ (ΠΡΟΤΕΙΝΟΜΕΝΟ VALUE 0.01)--->
Ύψος της κάμερας:<input type="text" id="cameraHeightTxt" value="0.01" autocomplete="off">
<button id="startButton" onclick="startAnimation()">Ξεκίνα!</button>
<button id="stopButton" onclick="stopAnimation()">Σταμάτα!</button>
</p>
</body>
</html>
<!--
ΘΕΜΑ: Προβολή της σκηνής με σπειροειδή κίνηση της κάμερας. Ο χρήστης ελέγχει το βήμα της γωνίας περιστροφής και το βήμα της αλλαγής του ύψους της κάμερας.
ΒΗΜΑ.ΤΑ.1,2,3,8,13
Δήλωση και χρήση νέου uniform στον vertex shader (1,2), δήλωση αντίστοιχου pointer (3), σύνδεση pointer με το νέο uniform (8), παροχή του συνολικού πίνακα προοπτικής/τοποθέτησης κάμερας ("τάισμα") στο uniform, μέσω του pointer (13)
ΒΗΜΑ.ΤΑ.4,5,6,9
Δήλωση και χρήση των μεταβλητών για τη θέση της κάμερας μέσω γωνίας περιστροφής (γύρω από τον άξονα z), και ύψους (z) σε σχέση με το επίπεδο xy. Ο χρήστης καθορίζει βήμα περιστροφής σε μοίρες και βήμα ύψους σε μονάδες του συστήματος συντεταγμένων του κόσμου των αντικειμένων.
ΒΗΜΑ.ΤΑ.7,10,11,12
Τοποθέτηση κάμερας και προοπτική προβολή. Δήλωση σχετικών πινάκων (7), προετοιμασία σχετικών πινάκων τοποθέτησης κάμερας (10) και προοπτικής προβολής (11) με χρήση συναρτήσεων της βιβλιοθήκης πινάκων και υπολογισμός του γινομένου τους (12) ώστε να "ταϊστεί" στο σχετικό uniform
ΑΚΟΛΟΥΘΗΣΤΕ ΤΑ ΒΗΜΑ.ΤΑ ΠΟΥ ΕΜΦΑΝΙΖΟΝΤΑΙ ΣΑΝ ΑΡΙΘΜΗΜΕΝΑ ΣΧΟΛΙΑ ΣΤΟΝ ΚΩΔΙΚΑ, ΣΥΜΠΛΗΡΩΝΟΝΤΑΣ ΤΙΣ ΑΝΤΙΣΤΟΙΧΕΣ ΕΝΤΟΛΕΣ ΜΕ ΤΗ ΣΕΙΡΑ ΤΗΣ ΑΡΙΘΜΗΣΗΣ
-->