Skip to content

Commit 44a3f27

Browse files
authored
Weekly merge into main
Weekly main merge
2 parents f84442a + 9e47b5c commit 44a3f27

File tree

169 files changed

+2493
-638
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

169 files changed

+2493
-638
lines changed

public/cd-icon.svg

Lines changed: 771 additions & 0 deletions
Loading

public/vite.svg

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/components/three-background/index.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import "./styles.css";
2-
import {initCamera, initCanvas, initScene, initStage, renderer} from "./scene.ts";
2+
import {initCamera, initScene, initStage, renderer} from "./scene.ts";
33
import {initBgMeshes} from "./particules.ts";
44
import {initPostProcess} from "./post-process.ts";
55
import {animate} from "./animation-loop.ts";
@@ -9,7 +9,6 @@ import {animate} from "./animation-loop.ts";
99
export function animatedBackground() {
1010
initStage();
1111
initScene();
12-
initCanvas();
1312
initCamera();
1413
initBgMeshes();
1514
initPostProcess();

src/components/three-background/scene.ts

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,7 @@ export let renderer: THREE.WebGLRenderer,
88
windowWidth = window.innerWidth,
99
windowHeight = window.innerHeight;
1010

11-
let graphicCanvas,
12-
canvasWidth = 240,
13-
canvasHeight = 240,
14-
mouseX = 0,
11+
let mouseX = 0,
1512
mouseY = 0,
1613
windowHalfWidth: number,
1714
windowHalfHeight: number;
@@ -31,7 +28,7 @@ export const initStage = () => {
3128
export const initScene = () => {
3229
scene = new THREE.Scene();
3330
scene.fog = new THREE.Fog(0x010102, 1, 3000);
34-
scene.add( new THREE.AmbientLight( 0xcccccc ) );
31+
scene.add( new THREE.AmbientLight( 0x000000 ) );
3532

3633

3734
renderer = new THREE.WebGLRenderer({
@@ -56,11 +53,7 @@ export const initCamera = () => {
5653
camera.position.z = 800;
5754
}
5855

59-
export const initCanvas = () => {
60-
graphicCanvas = document.createElement('canvas');
61-
graphicCanvas.width = canvasWidth;
62-
graphicCanvas.height = canvasHeight;
63-
}
56+
6457

6558
//-----------------------------------------------------------------------
6659

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import {renderWithPostProcess} from "./post-process.ts";
2+
import {sceneAnimation} from "./scene.ts";
3+
4+
5+
export const animate = () => {
6+
requestAnimationFrame(animate);
7+
sceneAnimation();
8+
renderWithPostProcess();
9+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import {initCamera, initScene, initStage, renderer} from "./scene.ts";
2+
import {animate} from "./animation-loop.ts";
3+
import {initRadar, TechUsage} from "./radar.ts";
4+
import {initPostProcess} from "./post-process.ts";
5+
6+
export function threeDataViewer(radarValues: TechUsage[]) {
7+
initStage();
8+
initScene();
9+
initCamera();
10+
initRadar(radarValues);
11+
initPostProcess();
12+
animate();
13+
14+
return renderer.domElement;
15+
}
16+
17+
//-----------------------------------------------------------------------
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import * as THREE from "three";
2+
import {scene} from "./scene.ts";
3+
4+
const offset = 1.35;
5+
const labelMeshes: THREE.Mesh[] = [];
6+
7+
8+
//-----------------------------------------------------------------------
9+
10+
export const label = (label: string, spawnPoint: {x: number, y: number}) => {
11+
const texture = createLabelTexture(label);
12+
const labelMesh = createLabelPlane(texture);
13+
14+
labelMesh.position.set(spawnPoint.x, spawnPoint.y * offset, 0);
15+
scene.add(labelMesh);
16+
labelMeshes.push(labelMesh);
17+
}
18+
19+
//-----------------------------------------------------------------------
20+
21+
const createLabelPlane = (texture: THREE.CanvasTexture) => {
22+
const geometry = new THREE.PlaneGeometry(2, 1);
23+
const material = new THREE.MeshBasicMaterial({
24+
map: texture,
25+
side: THREE.DoubleSide,
26+
transparent: true,
27+
});
28+
29+
const plane = new THREE.Mesh(geometry, material);
30+
return plane;
31+
}
32+
33+
const createLabelTexture = (label: string) => {
34+
const canvas = document.createElement('canvas');
35+
const context = canvas.getContext('2d');
36+
const width = 256;
37+
const height = 128;
38+
canvas.width = width;
39+
canvas.height = height;
40+
41+
context!.fillStyle = 'white';
42+
context!.font = '48px Arial';
43+
context!.textAlign = 'center';
44+
context!.textBaseline = 'middle';
45+
context!.fillText(label, width / 2, height / 2);
46+
47+
const texture = new THREE.CanvasTexture(canvas);
48+
return texture;
49+
}
50+
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import {camera, canvasHeight, canvasWidth, renderer, scene} from "./scene.ts";
2+
import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js';
3+
import { RenderPass } from 'three/addons/postprocessing/RenderPass.js';
4+
import { UnrealBloomPass } from 'three/addons/postprocessing/UnrealBloomPass.js';
5+
import { OutputPass } from 'three/addons/postprocessing/OutputPass.js';
6+
import {Vector2} from "three";
7+
8+
let composer: EffectComposer;
9+
10+
const postProcessConfigs = {
11+
size: Vector2,
12+
threshold: 0.6,
13+
strength: 0.3,
14+
radius: 0.5,
15+
exposure: 0
16+
};
17+
18+
19+
export const initPostProcess = () => {
20+
const renderScene = new RenderPass( scene, camera );
21+
22+
const bloomPass = new UnrealBloomPass(
23+
new Vector2( canvasWidth, canvasHeight ), // size
24+
postProcessConfigs.strength, // strength
25+
postProcessConfigs.radius, // radius
26+
postProcessConfigs.threshold // threshold
27+
);
28+
29+
const outputPass = new OutputPass();
30+
31+
composer = new EffectComposer( renderer );
32+
composer.addPass( renderScene );
33+
composer.addPass( bloomPass );
34+
composer.addPass( outputPass );
35+
}
36+
37+
export const renderWithPostProcess = () => {
38+
composer.render();
39+
}
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import * as THREE from "three";
2+
import {scene} from "./scene.ts";
3+
import {label} from "./label.ts";
4+
5+
const graphicSize = 1.5;
6+
7+
export type TechUsage = {
8+
technology: string,
9+
percentage: number
10+
}
11+
12+
const triangle = [
13+
{x: -graphicSize, y: -graphicSize},
14+
{x: 0, y: graphicSize},
15+
{x: graphicSize, y: -graphicSize}
16+
]
17+
18+
const extrudeSettings = {
19+
steps: 1,
20+
depth: 0,
21+
bevelEnabled: false,
22+
};
23+
24+
25+
//-----------------------------------------------------------------------
26+
27+
export const initRadar = (techs: TechUsage[]) => {
28+
const radarSize = determineRadarSize(techs.length);
29+
if (radarSize == undefined) { return; }
30+
31+
const shape = drawShape(radarSize);
32+
const mainMesh = buildMesh(shape, 0xffffff);
33+
scene.add(mainMesh);
34+
35+
for (let i = 0; i < 4; i++) {
36+
createDepthMesh(shape, i);
37+
}
38+
39+
for (let i = 0; i < techs.length; i++) {
40+
label(techs[i].technology, radarSize[i]);
41+
}
42+
43+
const valueShape = determineValueShape(techs.map(tech => tech.percentage));
44+
const valueMesh = buildMesh(valueShape, 0x3BFFC5);
45+
scene.add(valueMesh);
46+
}
47+
48+
//-----------------------------------------------------------------------
49+
50+
const buildMesh = (shape: THREE.Shape, shapeColor: THREE.ColorRepresentation) => {
51+
const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);
52+
const material = new THREE.MeshBasicMaterial({
53+
color: shapeColor,
54+
wireframe: true
55+
});
56+
57+
return new THREE.Mesh(geometry, material);
58+
}
59+
60+
const createDepthMesh = (depthShape: THREE.Shape, iteration: number) => {
61+
const mesh = buildMesh(depthShape, 0x333333);
62+
const size = iteration * 0.25;
63+
const offset = 2.5;
64+
65+
mesh.scale.set(size, size, size);
66+
mesh.position.z = iteration * 0.6 - offset;
67+
scene.add(mesh);
68+
}
69+
70+
const drawShape = (points: {x: number, y: number}[]) => {
71+
const shape = new THREE.Shape();
72+
73+
if (points.length > 0) {
74+
shape.moveTo(points[0].x, points[0].y);
75+
for (let i = 1; i < points.length; i++) {
76+
shape.lineTo(points[i].x, points[i].y);
77+
}
78+
shape.lineTo(points[0].x, points[0].y);
79+
}
80+
81+
return shape;
82+
}
83+
84+
const determineValueShape = (values: number[]) => {
85+
let valueShape: {x: number, y: number}[] = [];
86+
const score = values.map(value => ((100 - value) / 100) * graphicSize);
87+
88+
valueShape = [
89+
{x: triangle[0].x + score[0], y: triangle[0].y + score[0]},
90+
{x: triangle[1].x, y: triangle[1].y - score[1]},
91+
{x: triangle[2].x - score[2], y: triangle[2].y + score[2]}
92+
];
93+
94+
return drawShape(valueShape);
95+
}
96+
97+
const determineRadarSize = (size: number) => {
98+
if (size == 3) {
99+
return triangle;
100+
}
101+
else {
102+
console.log("Invalid number of technology. Create a new radar size or modify the number of technologies.");
103+
return;
104+
}
105+
}
106+
107+
108+
109+

0 commit comments

Comments
 (0)