Skip to content

Commit

Permalink
Changes
Browse files Browse the repository at this point in the history
  • Loading branch information
alexristinmaa committed Apr 16, 2024
1 parent 103c8a9 commit d0f4ced
Show file tree
Hide file tree
Showing 11 changed files with 801 additions and 26 deletions.
560 changes: 560 additions & 0 deletions alexanderristinmaa/app/(experiments)/[experiment]/info/markdown.css

Large diffs are not rendered by default.

36 changes: 36 additions & 0 deletions alexanderristinmaa/app/(experiments)/[experiment]/info/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// styles
import './markdown.css';

// other
import * as fs from 'fs';
import {marked} from 'marked';
import parseMD from 'parse-md';

marked.use({
gfm: true
})

export function generateStaticParams() {
const experiments =
fs.readdirSync('./app/(experiments)', {withFileTypes: true})
.filter(pathname => pathname.isDirectory() && fs.existsSync(`./app/(experiments)/${pathname.name}/page.md`))
.map(foldername => ({experiment: foldername.name}));

// Should return a list of objects with the parameter experiment (because the dynamic path is [experiment])
// with the value of the path [experiment]/info where experiment is the different paths
// ex return [{experiment: 'donut/info'}]
return experiments;
}

// Multiple versions of this page will be statically generated
// using the `params` returned by `generateStaticParams`
export default async function Page({ params } : { params: { experiment: string } }) {
const { experiment } = params;
const markdownString = fs.readFileSync(`./app/(experiments)/${experiment}/page.md`, 'utf8');
const htmlFromMarkdown = await marked.parse(parseMD(markdownString).content);

return (
<div style={{minHeight: '100vh'}} dangerouslySetInnerHTML={{__html: htmlFromMarkdown}}>
</div>
)
}
48 changes: 48 additions & 0 deletions alexanderristinmaa/app/(experiments)/donut/page.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
---
name: The (3D) Donut
description: A little spinning 3d donut made with three.js
tags:
- three.js
- 3d
---
# THE (3D) DONUT

This amazing viewer-experience shows a (SPINNING) model of a 3D donut using three.js with some encouraging music.

## How does it work?
Using three.js and a 3d object stored in a .gltf file it is no problem loading and displaying it.

The setup is **identical** to the [three.js startup docs](https://threejs.org/docs/index.html#manual/en/introduction/Creating-a-scene).
```typescript
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
```

*then* adding the **donut** to the scene using the builtin GLTFLoader.
```typescript
const loader = new GLTFLoader();
const donut = ... => loader.load('/donuts.gltf', ...);
scene.add(donut.scene);
```

Animating the donut is as simple as creating a function which calls `renderer.render(scene, camera)` and then requests an animation frame for itself. In between these, update the donut's rotation.
```typescript
const renderScene = () => {
requestAnimationFrame(renderScene);

donut.scene.rotation.x += 0.01;
donut.scene.rotation.y += 0.01;

renderer.render(scene, camera);
};

renderScene();
```


# Credit
This work is based on "DONUTS" (https://sketchfab.com/3d-models/donuts-1710b0f3f44d429ea7b41114f3ce0a09) by jun_sketchsoft (https://sketchfab.com/jun_sketchsoft) licensed under CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/)

Music by Bensound.com
License code: RZYLPS60JH8KEXM5
6 changes: 6 additions & 0 deletions alexanderristinmaa/app/(experiments)/donut/page.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,10 @@
transform: translateX(-50%);
color: white;
font-size: 30px;
}

#enableAudio {
top: 10px;
left: 10px;
color: white;
}
53 changes: 34 additions & 19 deletions alexanderristinmaa/app/(experiments)/donut/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client'

import { useEffect, useRef } from 'react';
import { createRef, useEffect, useRef, useState } from 'react';
// style
import styles from './page.module.css';

Expand All @@ -12,10 +12,34 @@ import { GLTF, GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';

export default function Home() {
const containerRef = useRef<HTMLDivElement>(null);
const audioRef = createRef<HTMLAudioElement>();
let [hasPlayed, setHasPlayed] = useState(false);

useEffect(() => {
const handleResize = () => {
const width = window.innerWidth;
const height = window.innerHeight;

camera.aspect = width / height;
camera.updateProjectionMatrix();

renderer.setSize(width, height);
};

window.addEventListener('resize', handleResize);

const handleFirstPlay = (event : any) => {
setHasPlayed(true);
event.target.removeEventListener('timeupdate', handleFirstPlay);
}

audioRef.current?.addEventListener('timeupdate', handleFirstPlay);

// THREEJS BUSINESS
// LOAD AND RENDER DONUT

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.01, 10000);
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);

Expand All @@ -26,52 +50,43 @@ export default function Home() {
const loader = new GLTFLoader();

(async () => {
let donut = await new Promise((resolve, reject) => loader.load('/donuts.gltf', data => resolve(data), undefined, reject)) as GLTF;
const donut = await new Promise((resolve, reject) => loader.load('/donuts.gltf', data => resolve(data), undefined, reject)) as GLTF;

scene.add(donut.scene);
// Render the scene and camera

// Add this function inside the useEffect hook
const renderScene = () => {
requestAnimationFrame(renderScene);

donut.scene.rotation.x += 0.01;
donut.scene.rotation.y += 0.01;

renderer.render(scene, camera);
requestAnimationFrame(renderScene);
};

// Call the renderScene function to start the animation loop
renderScene();
})();


const handleResize = () => {
const width = window.innerWidth;
const height = window.innerHeight;

camera.aspect = width / height;
camera.updateProjectionMatrix();

renderer.setSize(width, height);
};

window.addEventListener('resize', handleResize);

return () => {
// Cleanup of the renderer element
// Cleanup of the window element
// Good article here: https://react.dev/learn/synchronizing-with-effects#step-3-add-cleanup-if-needed

renderer.domElement.remove();
window.removeEventListener('resize', handleResize);
audioRef.current?.removeEventListener('timeupdate', handleFirstPlay);
}
}, []);


return (
<div>
{hasPlayed ? '' : <span className={styles.text} id={styles.enableAudio}>Please enable audio and refresh the page.</span>}
<span className={styles.text} id={styles.thebox}>THE DONUT</span>
<div ref={containerRef} />
<audio autoPlay hidden>
<source src="/onrepeat.mp3" type="audio/mpeg"/>
<audio src='/onrepeat.mp3' autoPlay hidden ref={audioRef}>
If you're reading this, audio isn't supported.
</audio>
</div>
Expand Down
8 changes: 8 additions & 0 deletions alexanderristinmaa/app/(experiments)/mandelbrot/page.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
name: Mandelbrot in WASM!
description: The beautiful mandelbrot fractal computed and rendered with compiled WebAssembly!
tags:
- WebAssembly
- Fractals
---
# Mandelbrot with Webassembly
6 changes: 6 additions & 0 deletions alexanderristinmaa/app/(homepage)/layout.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,10 @@
justify-content: center;
text-align: center;
white-space: pre-line;
}

@media screen and (max-width: 900px) {
#main {
padding: 20px 40px;
}
}
35 changes: 31 additions & 4 deletions alexanderristinmaa/app/(homepage)/page.module.css
Original file line number Diff line number Diff line change
@@ -1,14 +1,41 @@
#imgDiv {
width: 50%;
float: right;
#contentDiv {
display: flex;
gap: 20px;
}

#contentDiv > div {
flex: 1;
}

#imgDiv > p{
#imgDiv > p {
margin-top: 8px;
float: right;
}

#img {
width: 100%;
border: 2px solid var(--black);
}

#experimentsTitle {
font-size: 1.05em;
margin-bottom: 10px;
}

#experimentsList {
list-style: none;
}

#experimentsList > * > li {
margin-bottom: 10px;
}

.experimentTitle {
margin-bottom: 4px;
}

@media screen and (max-width: 900px) {
#contentDiv {
flex-direction: column;
}
}
36 changes: 33 additions & 3 deletions alexanderristinmaa/app/(homepage)/page.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,46 @@
// nextjs
import Link from 'next/link'
import { metadata } from './layout';

// style
import styles from './page.module.css';

// other
import * as fs from 'fs';
import parseMD from 'parse-md';

export default function Home() {
let getExperiments = () => {
return fs.readdirSync('./app/(experiments)', {withFileTypes: true})
.filter(v => v.isDirectory() && fs.existsSync(`./app/(experiments)/${v.name}/page.md`))
.map(v => ({data: fs.readFileSync(`./app/(experiments)/${v.name}/page.md`, 'utf8'), experiment: v.name}))
.map(v => ({metadata: parseMD(v.data).metadata as any, experiment: v.experiment}));
}


return (
<div>
<p>Om du vågar kolla runt kan du säkert hitta v<Link href='/hemligt'>a</Link>d du letar efter.</p>
<div id={styles.contentDiv}>
<div>
<p>Om du vågar kolla runt kan du säkert hitta v<Link href='/hemligt'>a</Link>d du letar efter.</p><br />
<p id={styles.experimentsTitle}><b>Mina senaste experiment:</b></p>
<ul id={styles.experimentsList}>
{
getExperiments().map((v) => {
return (
<Link href={`/${v.experiment}`}>
<li key={v.metadata.name}>
<p className={styles.experimentTitle}><u>{v.metadata.name}</u></p>
<p>{v.metadata.description}</p>
</li>
</Link>
)
})
}
</ul>
</div>
<div id={styles.imgDiv}>
<img id ={styles.img} src="/Alexander Ristinmaa.JPG" alt="Cool img" />
<p>Kebnekaise toppstuga och en räddningshelikopter</p>
<p><i>Kebnekaise toppstuga och en räddningshelikopter</i></p>
</div>

</div>
Expand Down
37 changes: 37 additions & 0 deletions alexanderristinmaa/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit d0f4ced

Please sign in to comment.