Summary Files Commits Branches @commit @diff @stats
diff options
context:
space:
mode:
Commite469e8d3a5a66b29a76fe7fb8e7888d9d7786d15 (patch)
Author
 Syndamia <kamen@syndamia.com>
2022-10-28 10:18:41 +0300
Committer
 Syndamia <kamen@syndamia.com>
2022-10-28 10:18:41 +0300
Files4c72c3489b43422c64c6fb4f462edb3ad14609c6
uni-projects-e469e8d3a5a66b29a76fe7fb8e7888d9d7786d15.tar
uni-projects-e469e8d3a5a66b29a76fe7fb8e7888d9d7786d15.tar.gz
uni-projects-e469e8d3a5a66b29a76fe7fb8e7888d9d7786d15.zip
Parentb209b1eb0fcd5b762d727851b7df20838a5278ba (diff)
[WGL/H03] Implemented view points, vertical rows, fixed color, added comments
1 files changed, 41 insertions, 20 deletions
-rw-r--r--Year 2/Computer Graphics with WebGL/Homework 03 - The wall/Homework.html61
diff --git a/Year 2/Computer Graphics with WebGL/Homework 03 - The wall/Homework.html b/Year 2/Computer Graphics with WebGL/Homework 03 - The wall/Homework.html
index 2d528c3..11393ef 100644
--- a/Year 2/Computer Graphics with WebGL/Homework 03 - The wall/Homework.html
+++ b/Year 2/Computer Graphics with WebGL/Homework 03 - The wall/Homework.html
@@ -45,7 +45,21 @@
var proj = perspMatrix(30,gl.canvas.width/gl.canvas.height,1,40000);
gl.uniformMatrix4fv(uProjectionMatrix,false,proj);
- var view = viewMatrix([1, 60, 1], [0,0,-7], [0,0,1]);
+ /***
+ *** Изгледите се променят с тази променлива!
+ ***/
+ const VIEW_INDEX = 1; // 0 - Отстрани, 1 - Отгоре, 2 - От близко
+
+ var view;
+ switch (VIEW_INDEX) {
+ case 0:
+ view = viewMatrix([-25, 30, -25], [-3,5,-6], [1.1,0,1]); break;
+ case 1: default:
+ view = viewMatrix([0, 60, -3], [0,0,-7], [0,0,1]); break;
+ case 2:
+ view = viewMatrix([-13, 3.2, -23], [0,3.2,-9], [0,90,1]); break;
+ }
+
gl.uniformMatrix4fv(uViewMatrix,false,view);
gl.viewport(0, 0, 600, 400);
@@ -75,19 +89,20 @@
gl.enableVertexAttribArray(aXYZ);
gl.vertexAttribPointer(aXYZ,3,gl.FLOAT,false,0,0);
- gl.uniform3f(uColor,127,0,0);
+ gl.uniform3f(uColor,0.5,0,0);
// Вместо единичен куб, да се нарисува стена под формата на сърце
// от 20 реда застъпващи се тухли, използвайки трансформиран куб
- var brickLength = 1.5;
- var brickHeight = 0.5;
- var rows = 1;
- var radius = 6;
- var gap = 0.4;
- var bottomHeight = 19;
+ var rows = 20;
+ var brickLength = 0.75;
+ var brickHeight = 0.25;
+ var brickWidth = 0.5;
+ var radius = 6; // определя радиус на полукръговете и амплитуда на синусоида за втората половина (виж drawBodyLine)
+ var gap = 0.2; // дупка между тухлите и два пъти дупка между редовете
+ var bottomHeight = 19; // височина от полукръговете до най-долната част на сърцето
- var brickScale = [1, brickHeight, brickLength];
+ var brickScale = [brickWidth, brickHeight, brickLength];
function drawBrick() {
useMatrix();
gl.drawArrays(gl.LINE_LOOP,0,4);
@@ -96,39 +111,45 @@
}
var degreeStep = (brickLength + gap) / radius;
- function drawHalfCircle(xOffset) {
- for (var i = 0; i < Math.PI + 0.1; i += degreeStep) {
+ function drawHalfCircle(y, offsetBricks, xOffset) {
+ for (var i = (offsetBricks) ? degreeStep / 2 : 0; i < Math.PI + 0.1; i += degreeStep) {
identity();
- translate([Math.cos(i) * radius + xOffset, 0, Math.sin(i) * radius]);
+ translate([Math.cos(i) * radius + xOffset, y, Math.sin(i) * radius]);
yRotate((Math.PI - i) * 180 / Math.PI);
scale(brickScale); drawBrick();
}
}
const SLOPE_EPSILON = 0.01;
- function drawBodyLine(xOffset, direction, rotationCoefficient) {
+ function drawBodyLine(y, offsetBricks, xOffset, direction, rotationCoefficient) {
function calcX(z) {
+ // direction е -1 или 1, като така разглеждаме синус в [-PI/2, PI/2] или [PI/2, PI] с амплитуда radius
return Math.sin(Math.PI / 2 * direction + Math.PI * z / bottomHeight) * radius - xOffset;
}
- var zStep = 0;
- for (var z = -brickLength - gap; z >= -bottomHeight - 0.1; z -= zStep) {
+ var zStep = 0; // ненужно, но иначе е малко объркващо
+ for (var z = -brickLength - gap + ((offsetBricks) ? brickLength / 2 : 0); z > -bottomHeight - 0.1; z -= zStep) {
var xDistance = calcX(z);
identity();
- translate([xDistance, 0, z]); yRotate(Math.sin(Math.PI * z / bottomHeight) * rotationCoefficient);
+ translate([xDistance, y, z]); yRotate(Math.sin(Math.PI * z / bottomHeight) * rotationCoefficient);
scale(brickScale); drawBrick();
+ // За равномерно разпределение по кривата, разглеждаме един малък участък като права, намираме наклона m
+ // и така преместваме тухлата вертикално, че разстоянието между сегашната и следващата тухла да е gap
+ // Най-перфектния начин е с интегриране, но това дава доста добър резултат за доста лесни (в сравнение) сметки
var m = Math.abs(SLOPE_EPSILON / (xDistance - calcX(z + SLOPE_EPSILON)));
+ // Намираме от системата d = sqrt((x-x0)^2 + (y-y0)^2) и m = (y-y0)/(x-x0), където (x0, y0) е сегашната точка
+ // (центъра на тухлата), а (x, y) са следващите
zStep = (brickLength + gap) * m / Math.sqrt(m * m + 1);
}
}
for (var row = 0; row < rows; row++) {
- drawHalfCircle(radius); // Горна лява четвърт
- drawHalfCircle(-radius); // Горна дясна четвърт
- drawBodyLine( radius, -1, 45); // Долна дясна четвърт
- drawBodyLine(-radius, 1, -45); // Долна лява четвърт
+ drawHalfCircle(row * (brickHeight + gap / 2), (row % 2 === 1), radius); // Горна лява четвърт
+ drawHalfCircle(row * (brickHeight + gap / 2), (row % 2 === 1), -radius); // Горна дясна четвърт
+ drawBodyLine( row * (brickHeight + gap / 2), (row % 2 === 1), radius, -1, 45); // Долна дясна четвърт
+ drawBodyLine( row * (brickHeight + gap / 2), (row % 2 === 1), -radius, 1, -45); // Долна лява четвърт
}
// Debugging