This commit is contained in:
Benjamín 2021-08-21 20:45:29 +02:00
commit 03fe1df64b
56 changed files with 1001 additions and 0 deletions

Binary file not shown.

BIN
images/0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
images/1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

BIN
images/1d.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

BIN
images/2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

BIN
images/3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

BIN
images/3d.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

BIN
images/3d.png~ Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

BIN
images/4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

BIN
images/4d.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

BIN
images/4d.png~ Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

BIN
images/5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

BIN
images/anglesToRotate.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

BIN
images/basicRotations.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

BIN
images/heightmap.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

BIN
images/knownRotations2D.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

BIN
images/main.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

BIN
images/newRotations.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

BIN
images/projected3Ddonut.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 KiB

315
index.html Normal file

@ -0,0 +1,315 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="styles/style.css"/>
<script src="libraries/jquery-3.6.0.min.js"></script>
<title>Understanding 4D</title>
</head>
<body>
<header>
<nav></nav>
</header>
<p class="title"><strong>Understanding 4D</strong></p>
<div class="a">
<span class="highlight_text">0. Introduction</span> <br/>
<p class="normal_text mtop">
Hello, I am Tucan. <br/>
In this course I will be explaining some ways of how to
think about 4D and then explain rotations of a 4D object that kinda looks like a donut. There will be a lot of interactive stuff so look forward to that. <br/>
Intuition is all you'll need.
</p>
</div>
<div class="a">
<p class="normal_text">
Also please download
<a href="./desktop app/Understanding 4D.zip" class="normal_text" download>this application.</a>
(<a href="https://drive.google.com/file/d/1iRUxC5VLrMRLLMBHvf7_ZTHKjQovYyPa/view?usp=sharing" class="normal_text" download>source code</a>)<br/>
It contains several scenes that will be useful in our explanation. <br/>
You can continue without the app if you want to. <br/>
There will be screenshots of the scenes, but they won't be interactive.
</p>
</div>
<div class="a">
<span class="highlight_text">1. What are we going to see?</span>
<p class="normal_text mtop">
Before we look at 4D and try understanding it, we need to know what are we going to be seeing and how. <br/>
To answer that, first let's look at what person in 1D would see.
</p>
<img src="./images/1d.png" class="normal_image"/>
<p class="normal_text mtop">
Person in 1D would see 1 piece of information or 0D. <br/>
Now let's look what happens in 2D. (use slider to move the points around)
</p>
<canvas class="c" width=1100px height=360px></canvas>
<p class="normal_text mtop">
As we saw above person in 2D would see a line or section of 1D. <br/>
Let's continue to 3D.
</p>
<img src="./images/3d.png" class="normal_image"/>
<p class="normal_text mtop">
In 3D we see section of 2D. As shown on the image, by projecting onto 2D surface we get rid of z coordinates. <br/>
Now let's look what would a person in 4D see.
</p>
<img src="./images/4d.png" class="normal_image"/>
<p class="normal_text mtop">
Every time we had person in some dimension what he saw was section of lower dimension. <br/>
For example we live in 3D but see 2D. Similarly, a person in 4D would see 3D. <br/>
But we can't see 3D space like person in 4D. <br/>
For us, we need to project again, 3D => 2D. <br/>
Then we can see 2D section that we end up with.<br/>
Let me give you example of projecting twice. 3D => 2D => 1D
</p>
<img src="./images/projectingTwiceFrom3D.png" class="normal_image"/>
<p class="normal_text mtop">
Now, let's move onto our case 4D => 3D => 2D.
We'll ignore 4D person for less confusion.
</p>
<img src="./images/projectingTwiceFrom4D.png" class="normal_image"/>
<p class="normal_text mtop">
By projecting twice we get something that we can see. <br/>
</p>
</div>
<div class="a">
<span class="highlight_text">2. Visualizing w axis using color</span>
<p class="normal_text mtop">
Before we do w axis let's try visualizing z axis with color in 2D. <br/>
To do that we can use heightmaps. In heightmaps color is used to indicate height.<br/>
Below we have 3D surface on the left and its heightmap on the right. <br/>
</p>
<div class="row">
<video width="854" height="480" controls class="normal_video">
<source src="./videos/Terrain3D.mp4" type="video/mp4">
</video>
<img src="./images/heightmap.png" class="normal_image"/>
</div>
<p class="normal_text mtop">
Using only black and white can be problematic with negative values. <br/>
By using more colors we can get more information from looking at heightmaps. <br/>
Let's use blue and green.
</p>
<img src="./images/colorVisualizationFor2D.png" class="normal_image"/>
<p class="normal_text mtop">
We can also use this to visualize the w axis.
</p>
<img src="./images/colorVisualizationForW.png" class="normal_image"/>
</div>
<div class="a">
<span class="highlight_text">3. Creating 4D object</span>
<p class="normal_text mtop">
Now it's going to start getting exciting. <br/>
4D object that we're going to create is in some ways similar to donut. <br/>
That's why we will look at how to create a donut first. <br/>
We can create a donut by rotating circle around a line. <br/>
Below is how it would look in 2D visualized by color. <br/>
Note that object below is only half donut. (sigle color per circle used for simplicity) <br/>
</p>
<img src="./images/halfDonutVisualizedIn2D.png" class="normal_image"/>
<p class="normal_text mtop">
As we saw above 2D person would see a circle that's getting squashed and its color changes. <br/>
We're going to create our 4D object similarly but use spheres instead and rotate into the 4th dimension. <br/>
Before that let's look at what we need to do basic rotations. <br/>
All we need for basic rotation are 2 variables forming a plane. <br/>
Its nicely demonstrated on the image below.
</p>
<img src="./images/basicRotations.png" class="normal_image"/>
<p class="normal_text mtop">
Now we can start creating our 4D object. <br/>
Were going to do something similar to making a donut from circle. <br/>
But instead of circles were going to use spheres, and rotate into 4D using rotation with x and w. <br/>
Explore 3D scene that's illustrating half of the rotation. (signle color per sphere used for simplicity)
</p>
<iframe src="./spline scenes/4_d_donut_creation/index.html" frameborder=0 class="spline_scene"></iframe>
<p class="normal_text mtop">
Now let's go back to normal donut. <br/>
What would a person in 2D see when we project the donut. <br/>
We count that the donut was created using method above and not manipulated yet.
</p>
<img src="./images/projected3Ddonut.png" class="normal_image"/>
<p class="normal_text mtop">
When person that's in 2D saw that projected donut, <br/>
it looked something like rectangle with rounded corners. <br/>
Because we created our 4D object using similar method we can use this. <br/>
If this scales nicely, we should see something like cuboid (stretched cube) with rounded corners. <br/>
Please open the desktop app mentioned at the begging. <br/>
Then click on the button shown below to run projection of 4D object. (in app)
</p>
<img src="./images/0.png" class="normal_image"/>
<img src="./images/images from desktop app/0.png" class="normal_image mleft"/>
<p class="normal_text mtop">
As we saw, it looked like cuboid with rounded corners.
</p>
</div>
<div class="a">
<span class="highlight_text">4. Exploring 4D object</span>
<p class="normal_text mtop">
There are a lot of confusing things that can happen when we rotate higher dimensional objects. <br/>
So to get a little less confused we're going to look at rotations and their behavior first. <br/>
Below is table with dimensions and rotations that become possible in that dimension.
</p>
<img src="./images/newRotations.png" class="normal_image"/>
<p class="normal_text mtop">
Now let's split rotations into known and unknown. <br/>
Known rotations will be those that exist in our dimension. <br/>
And unknown rotations will be those that are in higher dimensions. <br/>
The number of unknown rotations will always be infinite like the number of higher dimensions. <br/>
For example, if we're in 2D we have 1 known rotation.
</p>
<img src="./images/known and unknown rotations.png" class="normal_image"/>
<p class="normal_text mtop">
Using known rotations on higher dimensional objects doesn't change the behavior of known rotations. <br/>
For example, if we're in 2D and use known rotation on 3D donut it would rotate like we would expect.
</p>
<img src="./images/knownRotations2D.png" class="normal_image"/>
<p class="normal_text mtop">
Also in the first scene that we used app to run were only known rotations inplace. <br/>
That's why you haven't seen any unusual motion. <br/>
To create higher dimensional objects in some dimension we used unknown rotations. <br/>
Let's look again at where we used them.
</p>
<img src="./images/unknownRotationsUsedForCreatingObjects.png" class="normal_image"/>
<p class="normal_text mtop">
Now we will use these unknown rotations to rotate the objects. <br/>
We're going to start with normal donut. <br/>
For person in 2D it looks as if the points are cycling through the object.
</p>
<img src="./images/unknownRotationOnDonut.png" class="normal_image"/>
<p class="normal_text mtop">
Next we're going to do the same with our 4D object. <br/>
Click the button shown below. (in app)
</p>
<img src="./images/5.png" class="normal_image"/>
<img src="./images/images from desktop app/5.png" class="normal_image mleft"/>
<p class="normal_text mtop">
Another thing we can do is use reverse rendering. <br/>
Here, that means seeing whats furthest away first. <br/>
This way we can see more useful information. <br/>
Let's start with rendering normal 3D donut with reverse. <br/>
Click the button shown below. (in app)
</p>
<img src="./images/1.png" class="normal_image"/>
<img src="./images/images from desktop app/1.png" class="normal_image mleft"/>
<p class="normal_text mtop">
Using reverse we could see the backside and partially see front side as well when they overlapped. <br/>
Next were going to use reverse with our 4D object. <br/>
Click the button shown below. (in app)
</p>
<img src="./images/2.png" class="normal_image"/>
<img src="./images/images from desktop app/2.png" class="normal_image mleft"/>
<p class="normal_text mtop">
Next we'll change lighting. <br/>
Instead of normal lighting we can use ambient light gradients (alg). <br/>
With them we can get better sense of distance. <br/>
Image below is showing difference between directional lighting and alg.
</p>
<img src="./images/directionalLightAndAmbientLightGradient.png" class="normal_image"/>
<p class="normal_text mtop">
Actually alg that's used in the app is a little different to improve performance. <br/>
But it still looks similar enough. <br/>
Now we'll try alg with 3D donut. <br/>
Click the button shown below. (in app)
</p>
<img src="./images/3.png" class="normal_image"/>
<img src="./images/images from desktop app/3.png" class="normal_image mleft"/>
<img src="./images/images from desktop app/3_.png" class="normal_image mleft"/>
<p class="normal_text mtop">
Let's continue with our 4D object. <br/>
Click the button shown below. (in app)
</p>
<img src="./images/4.png" class="normal_image"/>
<img src="./images/images from desktop app/4.png" class="normal_image mleft"/>
<p class="normal_text mtop">
There's one more thing we will do in this explanation. <br/>
We never combined known and unknown rotations together with our 4D object. <br/>
Because of that we never got to see all states of our 4D object. <br/>
To access all rotated states of 4D object we need 3 angles. <br/>
Below image illustrates this.
</p>
<img src="./images/anglesToRotate.png" class="normal_image"/>
<p class="normal_text mtop">
Now, let's try it with our 4D object. <br/>
Click the button shown below. (in app)
</p>
<img src="./images/main.png" class="normal_image"/>
<img src="./images/images from desktop app/main0.png" class="normal_image mleft"/>
<img src="./images/images from desktop app/main1.png" class="normal_image mleft"/>
<img src="./images/images from desktop app/main1_.png" class="normal_image mleft"/>
<p class="normal_text mtop">
And with that, here ends the explanation. <br/> <br/>
<a href="https://github.com/Tucan444/Understanding-4D" class="normal_text">Github<a/>
</p>
</div>
<script src="scripts/2Dprojection.js"></script>
</body>
</html>

2
libraries/jquery-3.6.0.min.js vendored Normal file

File diff suppressed because one or more lines are too long

333
scripts/2Dprojection.js Normal file

@ -0,0 +1,333 @@
function rgb_to_hex(r, g, b) {
r = Math.round(r).toString(16);
g = Math.round(g).toString(16);
b = Math.round(b).toString(16);
if (r.length < 2) {
r = "0" + r;
}
if (g.length < 2) {
g = "0" + g;
}
if (b.length < 2) {
b = "0" + b;
}
return `#${r}${g}${b}`;
}
class RotatingPoint2D {
constructor(x, y, theta, magnitude, size, color) {
this.x = x;
this.y = y;
// r as rotated
this.rx = x;
this.ry = y;
this.theta = theta;
this.magnitude = magnitude;
this.size = size;
this.color = color;
this.shaded_color = [0, 0, 0];
this.d = 0;
this.linewidth = 4;
this.offset = [400, 180];
this.TAU = Math.PI * 2;
}
shade = function(light_x, light_y, light_intensity) {
let differences = [this.rx - light_x, this.ry - light_y];
let distance = Math.sqrt(Math.pow(differences[0], 2) + Math.pow(differences[1], 2));
let alpha = Math.max(0, -(distance - light_intensity) / light_intensity);
this.shaded_color = [this.color[0] * alpha, this.color[1] * alpha, this.color[2] * alpha];
}
rotate = function(alpha = 0) {
let beta = alpha + this.theta;
this.rx = Math.cos(beta) * this.magnitude;
this.ry = Math.sin(beta) * this.magnitude;
}
find_d = function(player_pos) {
let offseted_player_pos = [player_pos[0] - this.offset[0], player_pos[1] - this.offset[1]];
let differences = [this.rx - offseted_player_pos[0], this.ry - offseted_player_pos[1]];
this.d = Math.pow(differences[0], 2) + Math.pow(differences[1], 2);
}
draw_line_to_player = function(ctx, player_pos) {
ctx.beginPath();
ctx.strokeStyle = rgb_to_hex(this.shaded_color[0], this.shaded_color[1], this.shaded_color[2]);
ctx.lineWidth = this.linewidth;
ctx.moveTo(this.rx + this.offset[0], this.ry + this.offset[1])
ctx.lineTo(player_pos[0], player_pos[1]);
ctx.stroke();
}
blit = function(ctx) {
ctx.beginPath();
ctx.fillStyle = rgb_to_hex(this.shaded_color[0], this.shaded_color[1], this.shaded_color[2]);
ctx.arc(this.rx + this.offset[0], this.ry + this.offset[1], this.size, 0, this.TAU);
ctx.fill();
}
get_projected_positions = function(player_pos, projection_size, canvas_height) {
let player_pos_x = player_pos[0] - this.offset[0];
let projected_pos = this.ry * (projection_size[0] / (player_pos_x - this.rx)) * (canvas_height / projection_size[1]);
return projected_pos + player_pos[1];
}
}
class VerticalSliderPoint {
constructor (x, y, r, colors, constrains) {
this.x = x;
this.y = y;
this.r = r;
this.colors = colors; // 0 for idle 1 for hover 2 for active
this.constrains = constrains;
this.TAU = Math.PI * 2;
}
set_y = function(y) {
if (y < this.constrains[0]) {
this.y = this.constrains[0];
} else if (y > this.constrains[1]) {
this.y = this.constrains[1];
} else {
this.y = y;
}
}
collidepoint = function (x, y) {
let differences = [this.x - x, this.y - y];
let distance = Math.sqrt(Math.pow(differences[0], 2) + Math.pow(differences[1], 2));
return (distance <= this.r);
}
get_progress = function() {
let progress = this.y - this.constrains[0];
progress /= this.constrains[1] - this.constrains[0];
return progress;
}
blit = function(ctx, color_index) {
ctx.beginPath();
ctx.lineWidth = 1;
ctx.fillStyle = this.colors[color_index];
ctx.arc(this.x, this.y, this.r, 0, this.TAU);
ctx.fill();
}
}
console.log("a");
$(document).ready(function(){
console.log("b");
let c = $(".c")[0];
let ctx = c.getContext("2d");
let TAU = Math.PI * 2;
let canvas_size = [1100, 360];
let view_width = 120;
let thin_line_width = 6;
let normal_line_width = 20;
let alpha = 0;
let mousedown = false;
let on_slider = false;
let player_pos = [canvas_size[0] - 360, canvas_size[1] /2];
let projection_size = [100, 120];
let slider_padding_top_bottom = 40;
let slider_angle = TAU * 1.2;
let creamy_white = "#c3c3c3";
let creamy_gray_light = "#a3a3a3"
let creamy_gray = "#999999";
let creamy_gray_dark = "#777777";
let green = "#6de256";
let sliderMode = 0;
let sliderPoint = new VerticalSliderPoint(50, slider_padding_top_bottom, 16,
[creamy_gray, creamy_gray_light, creamy_white],
[slider_padding_top_bottom, canvas_size[1] - slider_padding_top_bottom]);
let points = [new RotatingPoint2D(60, 0, 0, 60, 20, [255, 100, 100]),
new RotatingPoint2D(Math.cos((Math.PI / 3) * 2) * 80, Math.sin((Math.PI / 3) * 2) * 80, (Math.PI / 3) * 2, 80, 20, [255, 100, 100]),
new RotatingPoint2D(Math.cos((Math.PI / 3) * 4) * 110, Math.sin((Math.PI / 3) * 4) * 110, (Math.PI / 3) * 4, 110, 20, [255, 100, 100])];
for (let i = 0; i < points.length; i++) {
points[i].shade(100, 100, 400);
points[i].find_d(player_pos);
points[i].draw_line_to_player(ctx, player_pos);
}
points.sort((a, b) => (a.d < b.d) ? 1 : -1);
draw_projected_view();
draw_static_objects();
sliderPoint.blit(ctx, 0);
for(let i = 0; i<points.length; i++) {
points[i].blit(ctx);
}
function draw_static_objects() {
ctx.beginPath();
ctx.strokeStyle = creamy_white;
ctx.lineWidth = normal_line_width;
ctx.moveTo(canvas_size[0] - view_width, 0);
ctx.lineTo(canvas_size[0] - view_width, canvas_size[1])
ctx.stroke();
ctx.beginPath();
ctx.strokeStyle = creamy_gray_dark;
ctx.lineWidth = thin_line_width;
ctx.moveTo(50, slider_padding_top_bottom);
ctx.lineTo(50, canvas_size[1] - slider_padding_top_bottom);
ctx.stroke();
ctx.beginPath();
ctx.strokeStyle = creamy_white;
ctx.moveTo(player_pos[0], player_pos[1]);
ctx.lineTo(player_pos[0] - projection_size[0], player_pos[1] - (projection_size[1] / 2));
ctx.lineTo(player_pos[0] - projection_size[0], player_pos[1] + (projection_size[1] / 2));
ctx.lineTo(player_pos[0], player_pos[1]);
ctx.stroke();
ctx.beginPath();
ctx.fillStyle = green;
ctx.arc(player_pos[0], player_pos[1], 20, 0, TAU);
ctx.fill();
}
function draw_projected_view() {
ctx.lineWidth = normal_line_width;
for (var i = 0; i < points.length; ++i) {
ctx.beginPath();
ctx.strokeStyle = rgb_to_hex(points[i].shaded_color[0], points[i].shaded_color[1], points[i].shaded_color[2]);
let projected_pos = points[i].get_projected_positions(player_pos, projection_size, canvas_size[1]);
ctx.moveTo(canvas_size[0] - view_width, projected_pos);
ctx.lineTo(canvas_size[0], projected_pos);
ctx.stroke();
}
}
function clear_canvas () {
ctx.beginPath();
ctx.fillStyle = "#282828";
ctx.fillRect(0, 0, canvas_size[0], canvas_size[1]);
}
function draw_all () {
clear_canvas();
for (let i = 0; i < points.length; i++) {
points[i].rotate(alpha);
points[i].shade(100, 100, 400);
points[i].find_d(player_pos);
points[i].draw_line_to_player(ctx, player_pos);
}
points.sort((a, b) => (a.d < b.d) ? 1 : -1);
draw_projected_view();
draw_static_objects();
sliderPoint.blit(ctx, sliderMode);
for(let i = 0; i<points.length; i++) {
points[i].blit(ctx);
}
}
$(".c").mousemove(function(event){
let mouse_pos = get_mouse_pos(event);
if (mousedown && on_slider) {
sliderMode = 2;
sliderPoint.set_y(mouse_pos[1]);
console.log(sliderPoint.y);
alpha = slider_angle * sliderPoint.get_progress();
} else if (sliderPoint.collidepoint(mouse_pos[0], mouse_pos[1])) {
sliderMode = 1;
} else {
sliderMode = 0;
}
draw_all();
});
$(".c").mousedown(function(event){
let mouse_pos = get_mouse_pos(event);
mousedown = true;
if (sliderPoint.collidepoint(mouse_pos[0], mouse_pos[1])) {
on_slider = true;
sliderMode = 2;
draw_all();
}
});
$("body").mouseup(function(event) {
let mouse_pos = get_mouse_pos(event);
mousedown = false;
if (on_slider) {
on_slider = false;
sliderMode = 1 * sliderPoint.collidepoint(mouse_pos[0], mouse_pos[1]);
draw_all();
}
});
// other functions
function get_mouse_pos(event) {
let rect = c.getBoundingClientRect();
return [event.clientX - rect.left, event.clientY - rect.top];
}
});

@ -0,0 +1,57 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
body { width: 100%;
height: 100%;
margin: 0;
position: fixed;
background: rgba(25,25,25, 1) }
canvas { width: 100%; height: 100%; outline: none; }
#container { width: 100%; height: 100%; position: relative; }
.spline-watermark {
position: absolute;
bottom: 16px;
right: 16px;
width: 32px;
height: 32px;
z-index: 2;
}
.spline-watermark:hover {
opacity: 0.8;
}
.spline-watermark img {
display: block;
width: 100%;
height: 100%;
}
</style>
<title>4D donut creation</title>
<link rel="icon" type="image/png" href="https://spline.design/_assets/_images/icon_favicon16x16.png" sizes="16x16">
<link rel="icon" type="image/png" href="https://spline.design/_assets/_images/icon_favicon32x32.png" sizes="32x32">
</head>
<body>
<div id='container'>
<canvas id="canvas3d"></canvas>
<a class="spline-watermark" href="https://spline.design">
<img src="https://spline.design/_assets/_images/icon_favicon32x32.png">
</a>
</div>
<script src="https://unpkg.com/three@0.131.3/build/three.min.js"></script>
<script src="js/spline.runtime.min.js"></script>
<script src="js/main.js"></script>
</body>
</html>

@ -0,0 +1,4 @@
const app = new SpeRuntime.Application();
app.start('./scene.json');

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

55
styles/_classes.sass Normal file

@ -0,0 +1,55 @@
@import ./_variables
@import ./_mixins
.title
text-align: center
margin-top: 2%
margin-bottom: 2%
font-size: 60px
width: 100%
color: $text_color_0
.a
margin: 0% 5% 5% 5%
padding: 2%
border-radius: 10px
background-color: $primary_light
box-shadow:: 5px 5px 12px #141414
.normal_text
@include normal_text
background-color: $primary_light
.highlight_text
@include highlight_text
background-color: $primary_light
.mtop
margin-top: $mtop
.mleft
margin-left: $mleft
.normal_image
margin-top: $mtop + $image_margins_size
margin-bottom: $image_margins_size
box-shadow: 10px 10px 24px #111
.normal_video
margin-top: $mtop + $video_margins_size
margin-bottom: $video_margins_size
box-shadow: 10px 10px 24px #111
.row
margin-top: $mtop
display: flex
justify-content: space-around
flex-direction: row
border-radius: 10px
.spline_scene
margin-top: $mtop + $spline_scene_margins_size
margin-bottom: $spline_scene_margins_size
box-shadow: 10px 10px 24px #111
width: 1000px
height: 600px

12
styles/_main_tags.sass Normal file

@ -0,0 +1,12 @@
@import ./_variables
nav
width: 100%
height: 30px
box-shadow: 0px 0px 20px #000
background-color: $primary_dark
canvas
margin-top: $mtop + $canvas_margins_size
margin-bottom: $canvas_margins_size
box-shadow: 10px 10px 24px #111

21
styles/_mixins.sass Normal file

@ -0,0 +1,21 @@
@import ./_variables
@mixin smaller_text
font-size: $smaller_text_font_size
color: text_color_0
font-family: Arial, Helvetica, sans-ser
letter-spacing: 0.6px
@mixin normal_text
font-size: $normal_text_font_size
color: $text_color_0
font-family: Arial, Helvetica, sans-ser
letter-spacing: 2px
@mixin highlight_text
font-size: $highlight_text_font_size
color: $text_color_1
font-family: Arial, Helvetica, sans-serif
letter-spacing: 1px

19
styles/_variables.sass Normal file

@ -0,0 +1,19 @@
$primary: #282828
$primary_dark: #895d5d
$primary_light: #313131
$scrollbar_track_color: #373737
$scrollbar_thumb_color: #4b4b4b
$text_color_0: #d2d2d2
$text_color_1: #e3e3e3
$small_text_font_size: 22px
$normal_text_font_size: 26px
$highlight_text_font_size: 34px
$mtop: 1.2%
$mleft: 1.2%
$image_margins_size: 1.2%
$video_margins_size: 1.2%
$canvas_margins_size: 1.2%
$spline_scene_margins_size: 1.2%

117
styles/style.css Normal file

@ -0,0 +1,117 @@
nav {
width: 100%;
height: 30px;
-webkit-box-shadow: 0px 0px 20px #000;
box-shadow: 0px 0px 20px #000;
background-color: #895d5d;
}
canvas {
margin-top: 2.4%;
margin-bottom: 1.2%;
-webkit-box-shadow: 10px 10px 24px #111;
box-shadow: 10px 10px 24px #111;
}
.title {
text-align: center;
margin-top: 2%;
margin-bottom: 2%;
font-size: 60px;
width: 100%;
color: #d2d2d2;
}
.a {
margin: 0% 5% 5% 5%;
padding: 2%;
border-radius: 10px;
background-color: #313131;
-webkit-box-shadow: 5px 5px 12px #141414;
box-shadow: 5px 5px 12px #141414;
}
.normal_text {
font-size: 26px;
color: #d2d2d2;
font-family: Arial, Helvetica, sans-ser;
letter-spacing: 2px;
background-color: #313131;
}
.highlight_text {
font-size: 34px;
color: #e3e3e3;
font-family: Arial, Helvetica, sans-serif;
letter-spacing: 1px;
background-color: #313131;
}
.mtop {
margin-top: 1.2%;
}
.mleft {
margin-left: 1.2%;
}
.normal_image {
margin-top: 2.4%;
margin-bottom: 1.2%;
-webkit-box-shadow: 10px 10px 24px #111;
box-shadow: 10px 10px 24px #111;
}
.normal_video {
margin-top: 2.4%;
margin-bottom: 1.2%;
-webkit-box-shadow: 10px 10px 24px #111;
box-shadow: 10px 10px 24px #111;
}
.row {
margin-top: 1.2%;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-ms-flex-pack: distribute;
justify-content: space-around;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-ms-flex-direction: row;
flex-direction: row;
border-radius: 10px;
}
.spline_scene {
margin-top: 2.4%;
margin-bottom: 1.2%;
-webkit-box-shadow: 10px 10px 24px #111;
box-shadow: 10px 10px 24px #111;
width: 1000px;
height: 600px;
}
* {
padding: 0px;
margin: 0px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
background-color: #282828;
line-height: 1.3;
}
::-webkit-scrollbar {
width: 10px;
}
::-webkit-scrollbar-track {
background-color: #373737;
}
::-webkit-scrollbar-thumb {
background-color: #4b4b4b;
}
/*# sourceMappingURL=style.css.map */

18
styles/style.css.map Normal file

@ -0,0 +1,18 @@
{
"version": 3,
"mappings": "ACEA,AAAA,GAAG,CAAC;EACA,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,IAAI;EACZ,UAAU,EAAE,iBAAiB;EAC7B,gBAAgB,ECLL,OAAO;CDKgB;;AAEtC,AAAA,MAAM,CAAC;EACH,UAAU,EAAE,IAA4B;EACxC,aAAa,ECOK,IAAI;EDNtB,UAAU,EAAE,mBAAmB;CAAG;;AERtC,AAAA,MAAM,CAAC;EACH,UAAU,EAAE,MAAM;EAClB,UAAU,EAAE,EAAE;EACd,aAAa,EAAE,EAAE;EACjB,SAAS,EAAE,IAAI;EACf,KAAK,EAAE,IAAI;EACX,KAAK,EDFM,OAAO;CCEK;;AAE3B,AAAA,EAAE,CAAC;EACC,MAAM,EAAE,WAAW;EACnB,OAAO,EAAE,EAAE;EACX,aAAa,EAAE,IAAI;EACnB,gBAAgB,EDbJ,OAAO;ECcnB,UAAU,EAAG,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO;CAAK;;AAE1C,AAAA,YAAY,CAAC;EEPT,SAAS,EHDW,IAAI;EGExB,KAAK,EHLM,OAAO;EGMlB,WAAW,EAAE,0BAA0B;EACvC,cAAc,EAAE,GAAG;EFMnB,gBAAgB,EDlBJ,OAAO;CCkBgB;;AAEvC,AAAA,eAAe,CAAC;EELZ,SAAS,EHNc,IAAI;EGO3B,KAAK,EHVM,OAAO;EGWlB,WAAW,EAAE,4BAA4B;EACzC,cAAc,EAAE,GAAG;EFInB,gBAAgB,EDtBJ,OAAO;CCsBgB;;AAEvC,AAAA,KAAK,CAAC;EACF,UAAU,EDfP,IAAI;CCea;;AAExB,AAAA,MAAM,CAAC;EACH,WAAW,EDjBP,IAAI;CCiBc;;AAE1B,AAAA,aAAa,CAAC;EACV,UAAU,EAAE,IAA2B;EACvC,aAAa,EDnBI,IAAI;ECoBrB,UAAU,EAAE,mBAAmB;CAAG;;AAEtC,AAAA,aAAa,CAAC;EACV,UAAU,EAAE,IAA2B;EACvC,aAAa,EDvBI,IAAI;ECwBrB,UAAU,EAAE,mBAAmB;CAAG;;AAEtC,AAAA,IAAI,CAAC;EACD,UAAU,ED/BP,IAAI;ECgCP,OAAO,EAAE,IAAI;EACb,eAAe,EAAE,YAAY;EAC7B,cAAc,EAAE,GAAG;EACnB,aAAa,EAAE,IAAI;CAAG;;AAE1B,AAAA,aAAa,CAAC;EACV,UAAU,EAAE,IAAkC;EAC9C,aAAa,EDjCW,IAAI;ECkC5B,UAAU,EAAE,mBAAmB;EAC/B,KAAK,EAAE,MAAM;EACb,MAAM,EAAE,KAAK;CAAG;;AHjDpB,AAAA,CAAC,CAAC;EACE,OAAO,EAAE,GAAG;EACZ,MAAM,EAAE,GAAG;EACX,WAAW,EAAE,IAAI;EACjB,gBAAgB,EETV,OAAO;EFUb,WAAW,EAAE,GAAG;CAAG;;AAEvB,AAAA,mBAAmB,CAAC;EAChB,KAAK,EAAE,IAAI;CAAG;;AAElB,AAAA,yBAAyB,CAAC;EACtB,gBAAgB,EEZI,OAAO;CFYgB;;AAE/C,AAAA,yBAAyB,CAAC;EACtB,gBAAgB,EEdI,OAAO;CFcgB",
"sources": [
"style.sass",
"_main_tags.sass",
"_variables.sass",
"_classes.sass",
"_variables.sass",
"_mixins.sass",
"_variables.sass",
"_variables.sass",
"_mixins.sass",
"_variables.sass"
],
"names": [],
"file": "style.css"
}

20
styles/style.sass Normal file

@ -0,0 +1,20 @@
@import ./_main_tags
@import ./_classes
@import ./_variables
@import ./_mixins
*
padding: 0px
margin: 0px
user-select: none
background-color: $primary
line-height: 1.3
::-webkit-scrollbar
width: 10px
::-webkit-scrollbar-track
background-color: $scrollbar_track_color
::-webkit-scrollbar-thumb
background-color: $scrollbar_thumb_color

BIN
videos/Terrain3D.mp4 Normal file

Binary file not shown.